我有以下C ++代码:
class A {
protected:
struct Nested {
int x;
};
};
class B: public A {
friend class C;
};
class C {
void m1() {
B::Nested n; // or A::Nested
}
};
使用g ++ 4.4编译这个片段,无论我在m1中使用B :: Nested还是A :: Nested,都没有区别。 Clang接受B::Nested
,但如果我A::Nested
则不会编译。这是g ++或clang中的错误吗?
答案 0 :(得分:8)
根据标准,GCC是正确的,而且Clang是错的。它说是11.2 / 4
如果
,则在N类中命名时可以访问成员m
- m作为N的成员受到保护,并且引用发生在N类的成员或朋友中,或者发生在从N派生的P类的成员或朋友中,其中作为P的成员的m是私有的或受保护的
这是这个Clang bugreport的主题,它阻止了Clang构建Qt:http://llvm.org/bugs/show_bug.cgi?id=6840。一个Clang家伙说
实际上,我还没有实施过这条规则。它要么是一个 起草错误或可怕的错误。它整个'受保护' 说明符,它使得代码的良好形成依赖于 存在完全不相关的类,它会带来很高的成本 实现,并且在模板存在的情况下它是正式不可判定的。
答案 1 :(得分:1)
在C ++中,朋友不是传递性的。朋友的朋友不一定是我的朋友。
通过在A中使Nested受保护,您指示所有子类都可以使用此元素,但是不允许其他人使用它。你可以认为这是一种朋友。 A使所有子类成为关于访问嵌套结构的朋友。
现在B使C成为朋友,但这并不意味着C也是A的朋友。所以C应该无法访问嵌套。
但是:行为是从C ++ 03改变的。在C ++ 03中,嵌套类是封闭类的完整成员,因此具有完全访问权限。友谊仍然不是传递性的,但现在成员访问是。
您可能需要查看http://www.rhinocerus.net/forum/language-c-moderated/578874-friend-transitive-nested-classes.html,这解释了类似的问题。