Е. К. Пугачев Объектно-ориентированное программирование Под общей редакцией Ивановой Г. С. Рекомендовано Министерством общего и профессионального образования Российской Федерации в качестве учебник

Вид материалаУчебник

Содержание


3.5.Дружественные функции и классы
Пример 3.51. Внешняя дружественная функция
Пример 3.52. Дружественная функция - компонент другого класса
Подобный материал:
1   ...   16   17   18   19   20   21   22   23   ...   39
^

3.5.Дружественные функции и классы


Как было отмечено ранее (раздел 3.1), механизм управления доступом позволяет выделить внутренние (private), защищенные (protected) и общедоступные (public) компоненты классов. Причем внутренние компоненты локализованы в классе и не доступны извне, а защищенные доступны только компонентным функциям класса и его наследникам. Такое ограничение на доступ к внутренним и защищенным компонентам класса может оказаться неоправданно строгим. Оно может существенно сужать возможности наследования других классов от данного и сокращать количество вариантов его использования.

Бывают случаи, когда не компонентные функции должны иметь возможность обращаться к внутренним компонентам класса. В такой ситуации класс может предоставить особые привилегии определенным внешним функциям или компонентным функциям другого класса. Эти функции получили название дружественных.

По определению, дружественной функцией класса называется функция, которая, не являясь компонентом некоторого класса, имеет доступ ко всем его компонентам. Функция не может стать другом класса «без его согласия». Для получения прав друга функция должна быть описана в теле класса со спецификатором friend. Именно при наличии такого описания класс предоставляет функции права доступа к защищенным и внутренним компонентам.

^ Пример 3.51. Внешняя дружественная функция

#include

#include

class FIXED

{ private: int a;

public:

FIXED(int v):a(v){}

friend void show(FIXED);

};

void show(FIXED Par)

{ cout< // функция имеет доступ к внутреннему полю a

Par.a+=10;

cout<


void main()

{ clrscr();

FIXED aa(25);

cout << "результаты работы: "<

show(aa); // выводит: 25 35

getch();

}

Друзьями класса могут являться и компонентные функции другого класса. Однако следует заметить, что такую привилегию методу другого класса может предоставить лишь автор данного класса, а не автор метода.

^ Пример 3.52. Дружественная функция - компонент другого класса

#include

#include

class FLOAT; // объявление класса без его определения

class FIXED

{ private: int a;

public:

FIXED(int v):a(v){}

double Add(FLOAT);

void print(){cout <

};

class FLOAT

{ private: double b;

public:

FLOAT(double val){b=val;}

void print(){cout <

friend double FIXED::Add(FLOAT); /* компонентная функция класса FIXED объявляется дружественной классу FLOAT */


};

double FIXED::Add(FLOAT Par)

{ return a+Par.b;} /* функция получает доступ к внутреннему полю класса FLOAT */

void main()

{ clrscr();

FIXED aa(25); FLOAT bb(45);

cout << "результаты работы: "<

cout<; // выводит: 70

aa.print(); // выводит: 25

bb.print(); // выводит: 45

getch();

}

Следует отметить некоторые особенности дружественных функций. Дружественная функция при вызове не получает указатель this. Объекты класса должны передаваться дружественной функции явно (через параметры).

Так как дружественная функция не является компонентом класса, на нее не распространяется действие спецификаторов доступа (public, protected, private). Место размещения прототипа дружественной функции внутри определения класса безразлично. Права доступа дружественной функции не изменяются и не зависят от спецификаторов доступа.

Использование механизма дружественных функций позволяет упростить интерфейс между классами. Например, дружественная функция может получить доступ к внутренним и защищенным компонентам сразу нескольких классов. Тогда из этих классов можно убрать компонентные функции, предназначенные только для обеспечения доступа к «скрытым» компонентам.

Поскольку ограничение доступа к дружественной функция не относится, работать она будет достаточно быстро, и написать ее не труднее, чем функцию доступа к обычной структуре С++.

Если необходимо, чтобы все функции некоторого класса имели доступ к внутренним полям другого класса, то весь класс может быть объявлен дружественным:

friend class <имя класса >.

Пример 3.53. Объявление дружественного класса.

#include

#include

class SHOW; // объявление класса без его определения

class PAIR

{ private: char *Head,*Tail;

public:

PAIR(char *one,char *two):Head(one),Tail(two){}

friend class SHOW; // объявление дружественного класса

};

class SHOW /*всем функциям класса SHOW доступны внутренние поля класса PAIR*/

{ private: PAIR Twins;

public:

SHOW(char *one,char *two):Twins(one,two){}

void Head(){cout <

void Tail(){cout <

};

void main()

{ clrscr();

SHOW aa("HELLO","FRIEND");

cout << "результаты работы: "<

aa.Head(); // выводит: HELLO

aa.Tail(); // выводит: FRIEND

getch(); }