Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Язык программирования С++ и его «подводные камни».DOC
Скачиваний:
44
Добавлен:
01.05.2014
Размер:
1.02 Mб
Скачать

2.3. Друзья классов

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

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

class MyClass

{

private:

int nVar;

friend void friendFunc (MyClass &clArg, int narg); // Дружественная

// функция public: void memberFunc (int nArg); // Метод класса

// Определения функций

void friend friendFunc (MyClass &clArg,int nArg)

{clArg.nVar = nArg;}

void memberFunc (int nArg) {nVar = nArg;}

. . .

// Создаём объект класса

MyClass clObj;

// Обращаемся к частному компоненту класса

friendFunc(clObj,7);

memberFunc(7);

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

В качестве дружественной функции может выступать и некоторый метод другого класса:

class Myclass1

{

. . .

// Метод memberfuncMyclass2 класса Myclass2 объявляется дружественным

// классу MyClass1

friend void MyClass2 :: memberFuncMyClass2(. . .);

. . .

};

По аналогии с функциями и методами можно объявить дружественным весь класс. При этом все методы такого дружественного класса смогут обращать­ся ко всем компонентам класса:

class Myclass {

{

. . .

// Класс MyFriend объявляется дружественным классу MyClass

friend class MyFriend;

. . .

};

И ещё два замечания:

«Дружба» классов не транзитивна. Другими словами, если класс MyClass1 – друг класса MyClass2, а MyClass2 – друг MyClass3, то это не означает, что MyClass1 – друг MyClass3. Однако «дружба» наследуется, но об этом – более подробно после знакомства с на­сле­до­ва­нием.

«Дружба» классов – не симметрична, т. е. если класс MyFriend объявлен другом MyClass, то это не означает, что MyClass имеет доступ к частным и защищенным компонентам класса MyFriend. Таким образом, права для доступа к классу может предоставить только автор класса, а не програм­мист, написавший функцию или некоторый другой класс.

Пойдём дальше. Как правило, перед использованием объект должен быть ини­ци­а­ли­зи­ро­ван. В языке С этот процесс выполнялся либо автоматически (для глобальных и статических элементов), либо путем определения специ­альной функции, которая вызывается сразу после создания объекта, до его использования. Аналогичный подход можно использовать и в С++. Однако в нём предусмотрен способ лучше.