Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ для начинающих (Стенли Липпман) 3-е хххх.pdf
Скачиваний:
86
Добавлен:
30.05.2015
Размер:
5.92 Mб
Скачать

С++ для начинающих

638

class Account {

typedef double Money; //...

private:

static Money _interestRate; static Money initInterest();

};

// Money должно быть квалифицировано именем класса Account::

Account::Money Account::_interestRate = initInterest();

С каждым классом ассоциируется отдельная область видимости, причем у разных классов эти области различны. К членам одного класса нельзя напрямую обращаться в определениях членов другого класса, если только один из них не является для второго базовым. (Наследование и базовые классы рассматриваются в главах 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().

С++ для начинающих

639

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

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. Говорят, что такой объект скрыт за

С++ для начинающих

640

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

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

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