суббота, 5 декабря 2009 г.

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

Дружественные функции класса определяются вне области действия этого класса, но имеют право доступа к закрытым элементам 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)
Друзьями класса можно определить перегруженные функции. Каждая перегруженная функция, предназначенная в друзья, должна быть явно объ­явлена в описании класса как друг этого класса.

Комментариев нет:

Отправить комментарий