Правила программирования на Си и Си++



         

117. Избегайте дружественных классов


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

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

посылать множество сообщений объекту list, но я не хочу, чтобы эти сообщения были реализованы посредством открытых функций, потому что никто не будет их посылать, кроме объектов list_node. Мой list может сделать эти функции закрытыми и предоставить статус дружественного объекту list_node, но list_node

тогда сможет получить доступ к каждому закрытому члену list. На самом деле я хочу следующего: "Функции-члены этого дружественного класса могут вызвать вот эти три закрытые функции-члена, но не могут получить доступ к чему-либо еще закрытому". К сожалению, язык Си++ не располагает методом ограничения доступа к заданному подмножеству обработчиков сообщений:

доступно все или ничего.

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

class granting

{

   // ...

private: friend

class grantee

   // Функции, определенные в этом разделе, будут доступны

   // членам класса grantee, но не доступны для открытого

   // использования извне.

   message_sent _from_grantee();

   another_message_sent_from_grantee();

private:

   // Настоящие закрытые функции располагаются здесь. Хотя

   // grantee мог бы получить доступ к этим функциям, но не

   // получает.

   // ...

};

Помните, что мы на самом деле не ограничиваем дружбы; это просто соглашение о записи, чтобы помочь читателю нашего определения класса угадать наше намерение. Надеемся, что кто-бы ни писал класс grantee, он будет достаточно взрослым, чтобы не обмануть нашего дружелюбия нежелательными улучшениями.




Содержание  Назад  Вперед