Этот код компилируется в msvc / g ++:
class A{
protected:
int i;
class B{
public:
A* a;
B(A* a_)
:a(a_){
}
void doSomething(){
if (a)
a->i = 0;//<---- this part
}
};
public:
A()
:i(0){
}
};
Как видите, B получает доступ к «protected msgstr "раздел включающего класса, хотя он не объявлен как друг.
Это стандартное (соответствующее стандартам) поведение?
Я иногда использую эту функцию, но не помню правила, согласно которому вложенный защищенный класс должен автоматически получать доступ ко всем защищенным данным включающего класса.
В стандарте C ++ 03 в 11.8p1 сказано:
Члены вложенного класса не имеют специального доступа к членам включающего класса.
Однако разрешение для отчета о дефектах 45 (к стандарту) утверждает обратное и, следовательно, определяет поведение, которое вы видите:
Вложенный класс является членом и, как таковой, имеет тот же доступ права, как и любой другой член.
В C ++ 0x текст 11.8 был изменен, чтобы отразить этот факт,так что это допустимое поведение для компиляторов, соответствующих C ++ 03 и C ++ 0x.
См. Также эту ветку на форумах cprogramming.com .
У меня нет под рукой копии C ++ 03, но есть черновик (n3090) C ++ 0x:
11.8 Вложенные классы
1 A вложенный класс является членом и как таковой имеет то же права доступа, как и любой другой член. В члены окружающего класса не имеют специальный доступ к членам вложенного класс; обычные правила доступа (пункт 11) должны соблюдаться.
[Пример:
class E {
int x;
class B { };
class I {
B b; // OK: E::I can access E::B
int y;
void f(E* p, int i) {
p->x = i; // OK: E::I can access E::x
}
};
int g(I* p) {
return p->y; // error: I::y is private
}
};
Итак, по крайней мере, в следующем стандарте вложенные классы могут обращаться к членам внешнего класса, как и любая обычная функция-член.
Обновление: Это запрещено текущим стандартом. Но отчет о дефекте ( DR 45 ) был подан, чтобы исправить это. (Редакция SigTerm убрала это. Пожалуйста, будьте осторожны.)
Обновление №2: Я пробовал с VS2010, g ++ (4.0.1 Apple) с -Wall -ansi -pedantic -std = c ++ 98
и Comeau (4.3.10.1) в строгом режиме C ++ 03 с отключенными расширениями C ++ 0x - все они, похоже, принимают доступ к членам внешнего класса private
в члены внутреннего класса.
См. 9,7 долл. США / 1.
«Вложенный класс находится в области действия своего включающего класса. За исключением использования явных указателей, ссылок и имен объектов, объявления во вложенном классе могут использовать только имена типов, статические члены и перечислители из включающего класса "
Является ли это стандартным (соответствующим стандарту) поведением?
Нет .
Согласно C ++ - 2003
Раздел 11.8.1
Вложенные классы
Члены вложенного класса не имеют специального доступа к членам включающего класса, а также к классам или функциям, которые предоставили дружбу для включающий класс; должны соблюдаться обычные правила доступа (пункт 11). Члены включающего класса не имеют специального доступа к членам вложенного класса; должны соблюдаться обычные правила доступа (пункт 11).
[Example:
class E {
int x;
class B { };
class I {
B b; //error: E::B is private
int y;
void f(E* p, int i)
{
p->x = i; //error: E::x is private
}
};
int g(I* p)
{
return p->y; //error: I::y is private
}
};
—end example]
Но есть небольшая модификация этого раздела в ISO / IEC N 3092
, в котором говорится
Вложенный класс является членом и, как таковой, имеет те же права доступа, что и любой другой член . Члены включающего класса не имеют специального доступа к членам вложенного класса; должны соблюдаться обычные правила доступа (пункт 11).