Программирование >>  Инициализация объектов класса, структура 

1 ... 236 237 238 [ 239 ] 240 241 242 ... 395


class String {

friend bool operator==( const String s, const String s );

friend bool operator==( const char *, const String s );

friend bool operator==( const String s, const char * );

public:

... остальная часть класса String объявления сразу после заголовка класса:

В этих трех строчках три перегруженных оператора сравнения, принадлежащие глобальной области видимости, объявляются друзьями класса String, а следовательно, в

/ / дружественнхе операторы напрям обращаются к закрыт членам класса String

bool operator==( const String sstr1, const String sstr2 ) {

if ( str1. size != str2. size ) return false;

return strcmp( str1. string, str2. string ) ? false : true; их определениях можно напрямую обращаться к закрытым членам данного класса:

inline bool operator==( const String sstr, const char *s ) {

return strcmp( str. string, s ) ? false : true;

и т . д.

Можно возразить, что в данном случае прямой доступ к членам size и string необязателен, так как встроенные функции c str() и size() столь же эффективны и при этом сохраняют инкапсуляцию, а значит, нет особой нужды объявлять операторы равенства для класса String его друзьями.

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

Альтернативной реализацией является объявление глобальн1х операторов равенства друзьями класса String. Если функция или оператор объявлены таким образом, им предоставляется доступ к неоткрытым членам.

Объявление друга (оно начинается с ключевого слова friend) встречается только внутри определения класса. Поскольку друзья не являются членами класса, объявляющего дружественные отношения, то безразлично, в какой из секций - public, private или protected - они объявлены. В примере ниже мы решили поместить все подобные



extern ostreams storeCn( ostream s, Screen s ); extern BitMaps storeCn( BitMap s, Screen s );

...

class Screen {

friend ostreams storeCn( ostream s, Screen s ); friend BitMaps storeCn( BitMap s, Screen s ); ...

он хочет дать неограниченные права доступа: };

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

class Window; это всего объявление

class Screen {

friend bool is eal( Screen s, Window s );

...

class Window {

friend bool is eal( Screen s, Window s );

...

Объявление функции другом двух классов должно выглядеть так: };

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

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

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

Класс должен объявлять другом каждую из множества перегруженных функций, которой



class Window; class Screen {

Screen

copy() - член класса Screen Screens copy( Window s );

class Window {

Screen::copy() - друг класса Window friend Screens Screen::copy( Window s );

Screens Screen::copy( Window s ) { /* ... */ }

Функция-член одного класса не может быть объявлена другом второго, пока компилятор не увидел определения ее собственного класса. Это не всегда возможно. Предположим, что Screen должен объявить некоторые функции-члены Window своими друзьями, а Window - объявить таким же образом некоторые функции-члена Screen. В таком случае

class Window; class Screen {

friend class Window;

...

весь класс Window объявляется другом Screen: };

К закрытым членам класса Screen теперь можно обращаться из любой функции-члена Window.

Упражнение 15.6

Реализуйте операторы ввода и вывода, определенн1е для класса Screen в упражнении 15.5, в виде друзей и модифицируйте их определения так, чтобы они напрямую обращались к закрытым членам. Какая реализация лучше? Объясните почему.

15.3. Оператор -

Присваивание одного объекта другому объекту того же класса выполняется с помощью копирующего оператора присваивания. (Этот специальный случай был рассмотрен в разделе 14.7.)

Для класса могут быть определены и другие операторы присваивания. Если объектам класса надо присваивать значения типа, отличного от этого класса, то разрешается определить такие операторы, принимающие подобные параметры. Например, чтобы

String car ( Volks );

поддержать присваивание C-строки объекту String:

car = Studebaker ;



1 ... 236 237 238 [ 239 ] 240 241 242 ... 395

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика