Следует заметить, что хотя определение типа Money в классе Account использует тот же тип, что и определение во внешней области видимости, этот код все же ошибочен.

Хотя переопределение имени типа является ошибкой, не все компиляторы обнаружат эту ошибку. Некоторые спокойно примут такой код, даже если программа ошибочна.

Определения имен типов обычно располагаются в начале класса. Так, любой член класса, который использует этот тип, будет расположен после определения его имени.

При поиске имен в областях видимости члены класса следуют обычным правилам

Поиск имени, используемого в теле функции-члена, осуществляется следующим образом.

• Сначала поиск объявления имени осуществляется в функции-члене. Как обычно, рассматриваются объявления в теле функции, только предшествующие месту использования имени.

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

• Если объявление имени в классе не найдено, поиск продолжится в области видимости перед определением функции-члена.

Обычно не стоит использовать имя другого члена класса как имя параметра в функции-члене. Но для демонстрации поиска имени нарушим это правило в функции dummy_fcn():

// обратите внимание: это сугубо демонстрационный код, отражающий

// плохую практику программирования. Обычно не стоит использовать

// одинаковое имя для параметра и функции-члена

int height; // определяет имя, впоследствии используемое в Screen

class Screen {

public:

 typedef std::string::size_type pos;

 void dummy_fcn(pos height) {

  cursor = width * height; // какое имя height имеется в виду?

 }

private:

 pos cursor = 0;

 pos height = 0, width = 0;

};

Когда компилятор обрабатывает выражение умножения в функции dummy_fcn(), он ищет имена сначала в пределах данной функции. Параметры функции находятся в области видимости функции. Таким образом, имя height, используемое в теле функции dummy_fcn(), принадлежит ее параметру.

В данном случае имя height параметра скрывает имя height переменной-члена класса. Если необходимо переопределить обычные правила поиска, то это можно сделать так:

// плохой подход: имена, локальные для функций-членов, не должны

// скрывать имена переменных-членов класса

void Screen::dummy_fcn(pos height) {

 cursor = width * this->height; // переменная-член height

 // альтернативный способ указания переменной-члена

 cursor = width * Screen::height; // переменная-член height

}

Несмотря на то что член класса скрыт, его все равно можно использовать. Достаточно указать его полное имя, включающее имя класса, либо явно применить указатель this.

Значительно проще обеспечить доступ к переменной-члену height, присвоив параметру другое имя:

// хороший подход: не используйте имена переменных-членов для

// параметров или других локальных переменных

void Screen::dummy_fcn(pos ht) {

 cursor = width * height; // переменная-член height

}

Теперь, когда компилятор будет искать имя height, в функции dummy_fcn() он его не найдет. Затем компилятор просмотрит класс Screen. Поскольку имя height используется в функции-члене dummy_fcn(), компилятор просмотрит все объявления членов класса. Несмотря на то что объявление имени height расположено после места его использования в функции dummy_fcn(), компилятор решает, что оно относится к переменной-члену height.

После поиска в области видимости класса продолжается поиск в окружающей области видимости

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

// плохой подход: не скрывайте необходимые имена, которые

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

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

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