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