Правила программирования на С и С++. Главы 7-8
Страница 33. Избегайте дружественных классов


 

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, он будет достаточно взрослым, чтобы не обмануть нашего дружелюбия нежелательными улучшениями.

 

 
« Предыдущая статья   Следующая статья »