Дружественные функции класса определяются вне области действия этого класса, но имеют право доступа к закрытым элементам private (и, как мы увидим в главе 9 «Наследование», к элементам protected) данного класса. Функция или класс в целом могут быть объявлены другом (friend) другого класса.
Дружественные функции используются для повышения производительности. Приведем формальный пример, показывающий, как работает дружественная функция. Далее в этой книге дружественные функции применяются для перегрузки операций, используемых классами, и для создания классов итераторов. Объекты класса итератора используются, чтобы последовательно выделять элементы или выполнять операции над элементами в объекте класса контейнера (смотри раздел 7.9). Объекты классов контейнеров способны хранить множество элементов в форме, подобной массиву.
Чтобы объявить функцию как друга (friend) класса, перед ее прототипом в описании класса ставится ключевое слово friend. Чтобы объявить класс ClassTwo как друга класса ClassOne, запишите объявление в форме
friend ClassTwo
в определение класса ClassOne.
Замечание по технике программирования 7.5
Спецификаторы доступа к элементам private, protected и public не имеют отношения к объявлениям дружественности, так что эти объявления дружественности могут помещаться в любом месте в описании класса.
Помещайте объявления дружественности первыми в классе непосредственно после его заголовка и не предваряйте их каким-либо спецификатором доступа к элементам.
Дружественность требует разрешения, т.е. чтобы класс В стал другом класса А, класс А должен объявить, что класс В — его друг. Таким образом дружественность не обладает ни свойством симметричности, ни свойством транзитивности, т.е. если класс А — друг класса В, а класс В — друг класса С, то отсюда не следует, что класс В — друг класса А, что класс С — друг класса В, или что класс А — друг класса С.
Некоторые члены сообщества объектно-ориентированного программирования считают, что «дружественность» портит скрытие информации и ослабляет значения объектно-ориентированного подхода к проектированию.
Программа на рис. 7.5 демонстрирует объявление и использование дружественной функции setX для установки закрытого элемента данных х класса count. Заметим, что объявление friend появляется первым (по соглашению) в объявлении класса, даже раньше объявления закрытых функ- ций-элементов.
// FIG7_5.CPP
// Друзья могут иметь доступ к закрытым элементам класса. #include ciostream.h>
// Измененный класс Count class Count{
// объявление друга // // |
friend void setX(Count &, int); public:
конструктор вывод |
Count() { x = 0; }
// элемент данных |
void print() const {cout « x < private: int x;
Рис. 7.5. Друзья могут иметь доступ к закрытым элементам класса (часть 1 из 2) |
} ;
c.x = val; |
// Можно изменять закрытую переменную класса Count, // так как setX объявлена как дружественная функция класса Count void setX(Count &c, int val) |
// разрешено: setX - друг Count
}
main() {
Count object;
cout << "object.x после своего создания: "; object.print();
cout << "object.x после вызова дружественной функции setX: setX(object, 8); // задание x другом
object.print ();
return 0;
object.x после своего создания: О
object.x после вызова дружественной функции setX: 8 Рис. 7.5. Друзья могут иметь доступ к закрытым элементам класса (часть 2 из 2)
Программа на рис. 7.6 демонстрирует сообщения, вырабатываемые компилятором, когда для изменения закрытого элемента данных х вызывается функция cannotSetX, не являющаяся дружественной. Рисунки 7.5 и 7.6 предназначены для ознакомления с формальным механизмом использования дружественных функций; практические примеры использования дружественных функций появятся в последующих главах.
// FIG7_6.CPP
// конструктор // выход |
// Функции не друзья или не элементы не могут иметь доступ //к закрытым элементам класса, iinclude <iostream.h> // Измененный класс Count class Count { public:
= 0; } const { cout « |
x « endl; } |
// элемент данных |
Count() { x void print( private: int x;
} ;
// Функция пытается изменить закрытые данные класса Count, // но не может, так как она - не друг Count, void cannotSetX(Count Sc, int val)
{
c.x = val; |
// ОШИБКА: 'Count::x' недоступна
}
main () {
// cannotSetX не друг |
Count object;
cannotSetX(object, 3);
return 0; }
Рис. 7.6. Функции, не яфляющиеся друзьями или элементами, не могут иметь доступ к закрытым элементам класса (часть 1 из 2)
|
Compiling FIG7_6.CPP: Error FIG7 6.CPP 17: 'Count::x' is not accessible Warning FIG7 6.CPP 18: Parameter 'c' is never used Warning FIG7 6.CPP 18: Parameter 'val' is never used
Рис. 7.6. Функции, не яфляющиеся друзьями или элементами, не могут иметь доступ к закрытым элементам класса (часть 2 из 2)
Друзьями класса можно определить перегруженные функции. Каждая перегруженная функция, предназначенная в друзья, должна быть явно объявлена в описании класса как друг этого класса.
Комментариев нет:
Отправить комментарий