A::foo
是否需要公开B
才能宣布它为朋友?
class A {
protected: // public ?
void foo(int x);
};
class B : public A {
friend void A::foo(int); // not fine with GCC 4.8.1 but fine with VS 2013
void goo(int x) {foo(x);} // fine
static void hoo(int x) {}
};
void A::foo(int x) {B::hoo(x);} // friend declaration needed for this
Visual Studio 2013认为如果A :: foo受到保护是好的,但是GCC 4.8.1认为它不是并且希望它是公开的。哪个编译器正确?我最初的直觉是它可以被宣布为受保护。毕竟,B是从A派生的,所以应该可以访问A :: foo(因为B :: goo很简单地演示)。
答案 0 :(得分:2)
VS在这里是正确的。
A::foo
名称B
实际上可以在A
范围内访问,因为它来自class A {
protected:
void foo(int x);
};
class B : A {
using A::foo; // it's OK to refer to the name A::foo
};
void A::foo(int x) {}
。要prove这个,请考虑
foo
所以使用引用§11.3[朋友功能]
朋友声明提名的名称应在包含朋友声明的类的范围内访问。
我们可以争辩说,没有违反规则(friend
在派生类中也受到保护)。
好像在gcc中,一旦将{{1}}关键字放在友元函数声明的前面,名称查找就会开始忽略继承(虽然友谊不可继承,但无所事事)
正如40two在评论中提到的那样,Clang发出了相同的错误,并且bug report为;此问题也适用于DR209。似乎对于实施者来说,做到这一点非常困难。