Вложенные классы: доступ к защищенному члену входящего класса из вложенного защищенного класса
Этот код компилируется на 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 получает доступ к "защищенному" разделу охватывающего класса, хотя он не объявляется как друг.
Является ли это стандартным (стандартно-совместимым) поведением?
Я иногда использую эту функцию, но я не помню правила о том, что вложенный защищенный класс должен автоматически получить доступ ко всем защищенным данным окружающего класса.
Ответы
Ответ 1
В стандарте С++ 03, 11.8p1 говорит:
Члены вложенного класса не имеют специального доступа к членам охватывающего класса.
Тем не менее, разрешение для отчета о дефектах 45 (до стандарта) указывает противоположное и, следовательно, определяет поведение, которое вы видите:
Вложенный класс является членом и как таковой имеет те же права доступа, что и любой другой член.
В С++ 0x текст 11.8 был изменен, чтобы отразить этот факт, поэтому это допустимое поведение как для компиляторов С++ 03, так и для С++ 0x.
См. также этот поток из cprogramming.com форум.
Ответ 2
У меня нет копии С++ 03, но из черновика (n3090) С++ 0x:
11.8 Вложенные классы
1 Вложенный класс является членом и как таковой имеет тот же права доступа как любой другой член. члены закрывающего класса не имеют специальный доступ к членам вложенного класс; обычные правила доступа (пункт 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) в строгом режиме С++ 03 с отключенными расширениями С++ 0x - все они кажутся принимать доступ к внешним классам private
во внутренних членах класса.
Ответ 3
Обратитесь за $9.7/1.
"Вложенный класс находится в области его охватывающего класса. За исключением использования явных указателей, ссылок и имен объектов объявления в вложенном классе могут использовать только
имена типов, статические элементы и счетчики из охватывающего класса. "
Ответ 4
Является ли это стандартным (стандартно-совместимым) поведением?
Нет.
В соответствии с С++ - 2003
Section 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).