尽管友谊却无法进入基层

时间:2019-06-19 18:20:52

标签: c++ inheritance friend

关于此错误,有很多问题,所有答案似乎都暗示着向下转换是不可能的。至少据我了解,只有this answer提到友谊是可能的解决方案。但是,以下代码(为清晰起见,删除了不相关的内容)不会编译:

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);

3 个答案:

答案 0 :(得分:14)

您的代码与此等效:

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

由于基类受到保护,因此无论&b的友情如何,都不能将A*转换为C

答案 1 :(得分:13)

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

如果您在C中创建了一个成员函数并接受了B*,然后从其中调用了foo(),它将很好地工作。这样可以在具有必要访问权限(感谢友情)的C上下文中进行转换。

答案 2 :(得分:1)

由于受保护的继承,在全局范围中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
}

live