此代码不起作用(MS VS 2005),
b->funcA();
B::iterator iter;
无法访问A类声明的受保护成员。
如果我删除D类,一切都很好地编译。
我想知道这只是一个错误还是标准?
class A
{
protected:
void funcA() { }
class iterator { };
};
class D {
class B : public A {
class C {
B* b;
public:
void funcC() {
b->funcA();
B::iterator iter;
}
};
public:
void funcB() {
funcA();
}
};
};
谢谢!
答案 0 :(得分:3)
当前的C ++标准(C ++ 03)具有以下限制,会使您的代码格式错误:
嵌套类的成员对封闭类的成员没有特殊访问权限,也没有对已经为封闭类授予友谊的类或函数;应遵守通常的准入规则(C ++ 03 11.8 / 1)。
但是,这条规则在即将推出的C ++标准(C ++ 0x)中已被颠倒过来。该段落现为:
嵌套类是成员,因此具有与任何其他成员相同的访问权限。封闭类的成员对嵌套类的成员没有特殊访问权限;应遵守通常的访问规则(C ++ 0x Draft N3225 11.8 / 1)。
所以,根据旧的解释,你的代码是不正确的,但在新的解释下,它是正确的。这基本上是原始C ++标准中的一个缺陷;该缺陷于1998年被注意到,并且在2001年同意更正。您可以在CWG Defect 45中找到相关详细信息。
请注意,无论您想使用哪种解释,我认为编译器中仍然存在错误。以下是最小repro,并在使用Visual C ++ 2010时生成相同的错误:
class A {
protected:
void f() { }
};
struct D {
struct B : A {
struct C {
void g() {
B().f();
}
};
};
};
但是,如果删除D
并将B
放在全局命名空间中,编译器将接受该代码。
答案 1 :(得分:0)
C嵌套在B中的事实并没有给B的成员提供C特殊访问权限。
funcA()的解决方案: (1)使funcA()公开。 或(2)改为调用funcB()(委托给funcA())。
迭代器解决方案:将迭代器设为公共。
答案 2 :(得分:0)
C
是B
的嵌套类。嵌套类无法访问封闭类的私有成员和受保护成员。这就是为什么代码不能编译,并正确地给出编译错误。
C ++标准版(2003)以11.8美元/ 1 [class.access.nest]的形式说,
嵌套类的成员没有 特殊访问成员 封闭类,也不包括类或 授予友谊的功能 到一个封闭的班级;通常 准入规则(第11条)应为 服从。一个封闭的成员 class没有特殊的访问权限 嵌套类的成员;通常 准入规则(第11条)应为 服从。
标准本身的例子:
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
}
};
因此,根据它,D
的存在或不存在不会影响任何事情。它应该给出编译错误,即使D不存在。
昨天创建了类似主题:Are inner classes in C++ automatically friends?
顺便说一句,它是C ++ 03中的一个缺陷,已在C ++ 0x中得到纠正。
这在C ++ 0x中是允许的。见Access to nested classes