bear.ZooAnimal::ival;
Тем самым мы говорим компилятору, что объявление ival следует искать в области видимости класса ZooAnimal.
Проиллюстрируем использование оператора разрешения области видимости на несколько абсурдном примере (надеемся, вы никогда не напишете чего-либо подобного в реальном коде):
int ival;
int Bear::mumble( int ival )
{
return ival + // обращение к параметру
::ival + // обращение к глобальному объекту
ZooAnimal::ival +
Bear::ival;
}
Неквалифицированное обращение к ival разрешается в пользу формального параметра. (Если бы переменная ival не была определена внутри mumble(), то имел бы место доступ к члену класса Bear. Если бы ival не была определена и в Bear, то подразумевался бы член ZooAnimal. А если бы ival не было и там, то речь шла бы о глобальном объекте.)
Разрешение имени члена класса всегда предшествует выяснению того, является ли обращение к нему корректным. На первый взгляд, это противоречит интуиции. Например, изменим реализацию mumble():
int dval;
int Bear::mumble( int ival )
{
// ошибка: разрешается в пользу закрытого члена ZooAnimal::dval
return ival + dval;
}
Можно возразить, что алгоритм разрешения должен остановиться на первом допустимом в данном контексте имени, а не на первом найденном. Однако в приведенном примере алгоритм разрешения выполняется следующим образом:
(a) Определено ли dval в локальной области видимости функции-члена класса Bear? Нет.
(b) Определено ли dval в области видимости Bear? Нет.
(c) Определено ли dval в области видимости ZooAnimal? Да. Обращение разрешается в пользу этого имени.
После того как имя разрешено, компилятор проверяет, возможен ли доступ к нему. В данном случае нет: dval является закрытым членом, и прямое обращение к нему из mumble() запрещено. Правильное (и, возможно, имевшееся в виду) разрешение требует явного употребления оператора разрешения области видимости:
return ival + ::dval; // правильно