尽管有友谊,但无法进入的基类

Inaccessible base class despite friendship

本文关键字:基类 友谊      更新时间:2023-10-16

关于这个错误有很多问题,所有的答案似乎都暗示着向下投射是不可能的。只有这个答案提到友谊是可能的解决方案,至少据我所知。但是,以下代码(为清楚起见,删除了不相关的内容(无法编译:

class C;
class A {
    friend class C;  // this does not help
};
class B : protected A {
    friend class C;  // this does not help either
};
class C {
    public:
    void foo(A* a) {};
};
B b;
C c;
void bar()
{
    c.foo(&b);  // this produces error: class A is an inaccessible base of B
}

为什么友谊在参考上不起作用?毕竟,"C"完全能够通过指向"B"的指针调用"A"的受保护方法。

完整的错误是

prog.cc: In function 'void bar()':
prog.cc:20:13: error: 'A' is an inaccessible base of 'B'
   20 |     c.foo(&b);

您的代码等效于以下内容:

B b;
C c;
A * a = &b; // <- This cast produces the error
c.foo(a);

您不能将&b转换为A*,因为基类受到保护,无论C的友谊如何。

问题是从B*A*(需要友谊的那个(的转换不是发生在C的成员函数中,而是发生在包含bc的代码的上下文中(即不相关的函数bar()(。

如果您在接受B* C中创建了一个成员函数,然后从其中调用foo(),则可以正常工作。这将使转换发生在具有必要访问权限C的背景下(感谢友谊(。

在全局范围内,由于受保护的继承,B 不可见为 A。

只有B类

本身,从B类继承的类和C类(因为友谊关系("知道"B继承了A。但世界其他地区(包括全球范围(没有。

所以要实现你想要的,你可以打电话

c.foo(&b)

在 C 范围内,例如使用一些包装器函数,例如(尽管设计决策很糟糕(:

#include <iostream>
#include <cstdlib>
class C;

class A {
    friend class C;  // this does not help
};
class B : protected A {
    friend class C;  // this does not help either
};
class C {
public:
    void foo() {
        B b;
        foo(&b);  // this call is OK within C-scope
    }
private:
    void foo(A* /*a*/) {
        std::cout << "C::foo(A* a)n";
    };
};

int main()
{
    std::cout << "Hello, Wandbox!" << std::endl;
    B b;
    C c;
    //c.foo(&b);  // this produces error: class A is an inaccessible base of B
    c.foo();      // this is calling c.foo(A*) internally
}

或直播: