声明受保护的功能朋友

pre*_*eys 5 c++ function protected friend

是否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
Run Code Online (Sandbox Code Playgroud)

如果A :: foo受到保护,Visual Studio 2013认为没问题,但GCC 4.8.1认为它不是,并希望它是公开的.哪个编译器正确?我最初的直觉是它可以被宣布为受保护.毕竟,B是从A派生的,所以应该可以访问A :: foo(因为B :: goo简单地演示).

Nik*_*iou 2

VS在这里是正确的

\n\n

该名称A::foo实际上可以在 范围内访问,B因为它是从 公开派生的A。为了证明这一点,考虑

\n\n
class A {\n    protected:\n        void foo(int x);\n};\n\nclass B : A {\n    using A::foo; // it\'s OK to refer to the name A::foo\n};\n\nvoid A::foo(int x) {}  \n
Run Code Online (Sandbox Code Playgroud)\n\n

因此,通过使用引号 \xc2\xa7 11.3 [友元函数]

\n\n
\n

由友元声明指定的名称应在包含友元声明的类范围内可访问。

\n
\n\n

我们可以说这没有违反规则(foo在派生类中也受到保护)。

\n\n

似乎在 gcc 中,一旦将friend关键字放在友元函数声明前面,名称查找就会开始忽略继承(尽管友谊不可继承,但与此无关)

\n\n
\n\n

正如40two在评论中提到的,Clang 发出了相同的错误,并且有一个错误报告;这个问题也提到了DR209。对于实施者来说,要做到这一点似乎相当困难。

\n