7.4. Область видимости класса
Каждый класс определяет собственную область видимости. Вне области видимости класса (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:
// добавить окно на экран и возвратить его индекс
ScreenIndex addScreen(const Screen&);
// другие члены, как прежде
};
// тип возвращаемого значения видим прежде, чем начинается область
// видимости класса Window_mgr
Window_mgr::ScreenIndex
Window_mgr::addScreen(const Screen &s) {
screens.push_back(s);
return screens.size() - 1;
}
Поскольку тип возвращаемого значения встречается прежде имени класса, оно находится вне области видимости класса Window_mgr. Чтобы использовать тип ScreenIndex для возвращаемого значения, следует определить класс, в котором определяется этот тип.
Упражнения раздела 7.4
Упражнение 7.33. Что будет, если добавить в класс Screen переменную-член size(), определенную следующим образом? Исправьте все обнаруженные ошибки.
pos Screen::size() const {
return height * width;
}