Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ для начинающих.pdf
Скачиваний:
199
Добавлен:
01.05.2014
Размер:
3.97 Mб
Скачать

С каждым классом ассоциируется отдельная область видимости, причем у разных классов эти области различны. К членам одного класса нельзя напрямую обращаться в определениях членов другого класса, если только один из них не является для второго базовым. (Наследование и базовые классы рассматриваются в главах 17 и 18.)

13.9.1. Разрешение имен в области видимости класса

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

Имя, использованное внутри определения класса (за исключением определений встроенных функций-членов и аргументов по умолчанию), разрешается следующим образом:

1.Просматриваются объявления членов класса, появляющиеся перед употреблением имени.

2.Если на шаге 1 разрешение не привело к успеху, то просматриваются объявления в пространстве имен перед определением класса. Напомним, что глобальная область видимости – это тоже область видимости пространства имен. (О пространствах имен речь шла в разделе 8.5.)

typedef double Money; class Account {

// ...

private:

static Money _interestRate; static Money

initInterest();

// ...

Например:

};

Сначала компилятор ищет объявление Money в области видимости класса Account. При этом учитываются только те объявления, которые встречаются перед использованием Money. Поскольку таких объявлений нет, далее поиск ведется в глобальной области видимости. Объявление глобального typedef Money найдено, именно этот тип и используется в объявлениях _interestRate и initInterest().

Имя, встретившееся в определении функции-члена класса, разрешается следующим образом:

1.Сначала просматриваются объявления в локальных областях видимости функциичлена. (О локальных областях видимости и локальных объявлениях говорилось в разделе 8.1.)

2.Если шаг 1 не привел к успеху, то просматриваются объявления для всех членов класса.

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

int _height;

class Screen { public:

Screen( int _height ) {

_height = 0; // к чему относится _height? К параметру

}

private:

short _height;

Имена, встречающиеся в теле встроенной функции-члена, разрешаются так:

};

В поисках объявления имени _height, которое встретилось в определении конструктора Screen, компилятор просматривает локальную область видимости функции и находит его там. Следовательно, это имя относится к объявлению параметра.

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

int _height;

class Screen { public:

Screen( long _height ) { this->_height = 0; // относится к

Screen::_height

//тоже правильно:

//Screen::_height = 0;

}

private:

short _height;

квалифицировать имя члена именем его класса или явно использовать указатель this:

};

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

int _height;

class Screen { public:

Screen( long _height ) {

::_height = 0; // относится к глобальному объекту

}

private:

short _height;

};

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

class Screen { public:

// ...

void setHeight( int ); private:

short _height;

};

int verify(int);

void Screen::setHeight( int var ) {

//var: относится к параметру

//_height: относится к члену класса

//verify: относится к глобальной

функции

_height = verify( var );

члена:

}

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

Имя, встретившееся в определении статического члена класса, разрешается следующим образом:

1.Просматриваются объявления всех членов класса.

2.Если шаг 1 не привел к успеху, то просматриваются объявления, расположенные в областях видимости пространств имен перед определением статического члена, а не только предшествующие определению класса.

Упражнение 13.18 Назовите те части программы, которые находятся в области видимости класса. Упражнение 13.19