Определения членов класса, появляющиеся вне его тела, – это еще один пример части программы, которая находится в области видимости класса. В ней имена членов распознаются несмотря на то, что оператор доступа или оператор разрешения области видимости при обращении к ним не применяется. Как же разрешаются имена в определениях членов?
Как правило, если такое определение появляется вне тела, то часть программы, следующая за именем определяемого члена, считается находящейся в области видимости класса вплоть до конца определения члена. Вынесем определение оператора operator[]() из класса String:
class String {
public:
typedef int index_type;
char& operator[]( index_type );
private:
char *_string;
};
// в operator[]() есть обращения к index_type и _string
inline char& operator[]( index_type elem )
{
return _string[ elem ];
}
Обратите внимание, что в списке параметров встречается typedef index_type без квалифицирующего имени класса String::.Текст, следующий за именем члена String::operator[] и до конца определения функции, находится в области видимости класса. Объявленные в этой области типы рассматриваются при разрешении имен типов, использованных в списке параметров функции-члена.
Определения статических данных-членов также появляются вне определения класса. В них часть программы, следующая за именем статического члена вплоть до конца определения, считается находящейся в области видимости класса. Например, инициализатор статического члена может непосредственно, без соответствующих операторов, ссылаться на члены класса:
class Account:
// ...
private:
static double _interestRate;
static double initInterestRate();
};
// ссылается на Account::initInterest()
double Account::_interestRate = initInterest();
Инициализатор _interestRate вызывает статическую функцию-член Account::initInterest() несмотря на то, что ее имя не квалифицировано именем класса.
Не только инициализатор, но и все, что следует за именем статического члена _interestRate до завершающей точки с запятой, находится в области видимости класса Account. Поэтому в определении статического члена name может быть обращение к члену класса nameSize:
class Account:
// ...
private:
static const int nameSize = 16;
static const char name[nameSize];
// nameSize не квалифицировано именем класса Account
const char Account::name[nameSize] = "Savins Account";
Хотя член nameSize не квалифицирован именем класса Account, определение name не является ошибкой, так как оно находится в области видимости своего класса и может ссылаться на его члены после того, как компилятор прочитал Account::name.
В определении члена, которое появляется вне тела, часть программы перед определяемым именем не находится в области видимости класса. При обращении к члену в этой части следует пользоваться оператором разрешения области видимости. Например, если типом статического члена является typedef Money, определенный в классе Account, то имя Money должно быть квалифицировано, когда статический член данных определяется вне тела класса:
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 разрешение не привело к успеху, то просматриваются объявления в пространстве имен перед определением класса. Напомним, что глобальная область видимости – это тоже область видимости пространства имен. (О пространствах имен речь шла в разделе 8.5.)