friend std::ostream& storeOn(std::ostream &, Screen &); // ...

};

Класс Screen объявляет другом версию функции storeOn, получающей поток ostream&. Версия, получающая параметр BitMap&, особых прав доступа к объектам класса Screen не имеет.

Объявление дружественных отношений и область видимости

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

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

struct X {

 friend void f() { /* дружественная функция может быть определена

                      в теле класса */ }

 X() { f(); } // ошибка: нет объявления для f

 void g();

 void h();

};

void X::g() { return f(); } // ошибка: f не была объявлена

void f();                   // объявляет функцию, определенную в X

void X::h() { return f(); } // ok: объявление f теперь в области

                            // видимости

Важно понимать, что объявление дружественной затрагивает доступ, но не является объявлением в обычном смысле.

Помните: некоторые компиляторы не выполняют правил поиска имен друзей (см. раздел 7.2.1).

Упражнения раздела 7.3.4

Упражнение 7.32. Определите собственные версии классов Screen и Window_mgr, в которых функция clear() является членом класса Window_mgr и другом класса Screen.

<p><image l:href="#reader.png"/>7.4. Область видимости класса</p>

Каждый класс определяет собственную область видимости. Вне области видимости класса (class scope) к обычным данным и функциям его члены могут обращаться только через объект, ссылку или указатель, используя оператор доступа к члену (см. раздел 4.6). Для доступа к членам типа из класса используется оператор области видимости. В любом случае следующее за оператором имя должно быть членом соответствующего класса.

Screen::pos ht = 24, wd = 80; // использование типа pos, определенного

                              // в классе Screen

Screen scr(ht, wd, ' ');

Screen *p = &scr

char c = scr.get(); // доступ к члену get() объекта

scr c = p->get();   // доступ к члену get() из объекта, на который

                    // указывает p

Область видимости и члены, определенные вне класса

Тот факт, что класс определяет область видимости, объясняет, почему следует предоставить имя класса наравне с именем функции, при определении функции-члена вне ее класса (см. раздел 7.1.2). За пределами класса имена ее членов скрыты.

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

Вернемся, например, к функции-члену clear() класса Window_mgr (см. раздел 7.3.4). Параметр этой функции имеет тип, определенный в классе Window_mgr:

void Window_mgr::clear(ScreenIndex i) {

 Screen &s = screens[i];

 s.contents = string(s.height * s.width, ' ');

}

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

С другой стороны, тип возвращаемого значения функции обычно располагается перед именем функции. Когда функция-член определяется вне тела класса, любое имя, используемое в типе возвращаемого значения, находится вне области видимости класса. В результате тип возвращаемого значения должен определять класс, членом которого он является. Например, мы могли бы добавить в класс Window_mgr функцию addScreen(), добавляющую еще одно окно на экран. Этот член класса возвратит значение типа ScreenIndex, которое пользователь впоследствии сможет использовать для поиска этого окна:

class Window_mgr {

public:

Перейти на страницу:

Похожие книги