int x;
int y;
class enclose {
public:
int x;
static int s;
class inner {
void f(int i)
{
x = i; // ошибка: присваивание enclose::x
s = i; // нормально: присваивание enclose::s
::x = i; // нормально: присваивание глобальному x
y = i; // нормально: присваивание глобальному y
}
void g(enclose* p, int i)
{
p-›x = i; // нормально: присваивание enclose::x
}
};
};
inner* p = 0; // ошибка: `inner' вне области видимости
Функции-члены вложенного класса не имеют особых прав доступа к членам объемлющего класса, они подчиняются обычным правилам доступа (§R.11). Аналогично, функции-члены объемлющего класса не имеют особых прав доступа к членам вложенного класса и подчиняются обычным правилам доступа, например:
class E {
int x;
class I {
int y;
void f(E* p, int i)
{
p-›x = i; // ошибка: E::x частный член
}
};
int g(I* p)
{
return p-›y; // ошибка: I::y частный член
}
};
Функции-члены и представляющие данные, статические члены из вложенного
класса можно определить в глобальной области видимости, например:
class enclose {
class inner {
static int x;
void f(int i);
};
};
typedef enclose::inner ei;
int ei::x = 1;
void enclose::inner::f(int i) {/*… */}
Подобно функции-члену дружественная функция, определенная в данном классе, находится в области видимости этого класса. Она подчиняется тем же правилам связывания имен, что и функции-члены (они указаны выше и в §R.10.4), и не имеет так же как они особых прав доступа к членам объемлющего класса и к локальным переменным функций этого класса (§R.11).
R.9.8 Описания локальных классов
Класс можно описать в определении функции, такой класс называется локальным. Имя локального класса считается локальным в объемлющей области видимости, а областью видимости локального класса является объемлющая область видимости. В описаниях локального класса из объемлющей области видимости можно использовать только имена типов, статических переменных, внешних переменных и функций, а также элементы перечисления. Приведем пример:
int x;
void f()
{
static int s;
int x;
extern int g();
struct local {
int h() { return x; } // ошибка: `x' автоматическая
int j() { return s; } // нормально
int k() { return ::x; } // нормально
int l() { return g(); } // нормально
}
}
Объемлющая функция не имеет особых прав доступа к членам локального класса, она подчиняется обычным правилам доступа (§R.11). Функцию-член локального класса следует определять в определении этого класса. Локальный класс не может иметь статических членов, представляющих данные.
R.9.9 Имена локальных типов
Имена типов подчиняются точно таким же правилам областей видимости, как и другие имена. В частности, имена типов, определенные в описании класса, нельзя использовать вне этого класса без уточнения, например:
class X {
public:
typedef int I;
class Y {/*… */}
I a;
};
I b; // ошибка
Y c; // ошибка
X::Y d; // ошибка
Следующее положение ограничивает зависимость от контекста правил описания членов класса, а так же правила переноса тела функций, являющихся подстановками. После использования в описании класса имя константы, имя-класса или имя-typedef не может переопределяться в описании этого класса. Имя, не являющееся именем-класса или именем-typedef не может быть определено в описании класса как имя-класса или имя-typedef, если оно уже использовалось иначе в описании этого класса. Рассмотрим пример:
typedef int c;
enum { i = 1 };
class X {
char v[i];
int f() { return sizeof(c); }
char c; // ошибка: имя typedef
// переопределяется после использования
enum { i = 2 }; // ошибка: `i' переопределяется после
// использования в задании типа `char[i]'
};
typedef char* T;
struct Y {
T a;
typedef long T; // ошибка: имя T уже использовано
T b;
};
В описании класса можно указать список базовых классов с помощью следующих конструкций:
спец-базовых:
: список-базовых
список-базовых:
спецификация-базовых
список-базовых , спецификация-базовых
Читать дальше