尽管有友谊,但无法访问基地 class
Inaccessible base class despite friendship
关于这个错误有很多问题,所有的答案似乎都暗示向下转换是不可能的。只有 提到友谊是可能的解决方案,至少在我看来是这样。但是,以下代码(为清楚起见删除了不相关的内容)无法编译:
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*
到 A*
(需要友谊的那个)的转换不会发生在 C
的成员函数中,而是发生在包含 b
和 c
的代码(即不相关的函数 bar()
)。
如果您在 C
中创建一个接受 B*
的成员函数,然后从其中调用 foo()
,它会很好地工作。这将使转换发生在 C
的上下文中,它具有必要的访问权限(感谢友谊)。
您的代码等同于:
B b;
C c;
A * a = &b; // <- This cast produces the error
c.foo(a);
您不能将 &b
转换为 A*
,因为基数 class 受到保护,无论 C
.
的友谊如何
在全局范围内,由于受保护的继承,B 作为 A 不可见。
只有classB本身,class继承自B和classC(因为友情关系)"know"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:
关于这个错误有很多问题,所有的答案似乎都暗示向下转换是不可能的。只有
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*
到 A*
(需要友谊的那个)的转换不会发生在 C
的成员函数中,而是发生在包含 b
和 c
的代码(即不相关的函数 bar()
)。
如果您在 C
中创建一个接受 B*
的成员函数,然后从其中调用 foo()
,它会很好地工作。这将使转换发生在 C
的上下文中,它具有必要的访问权限(感谢友谊)。
您的代码等同于:
B b;
C c;
A * a = &b; // <- This cast produces the error
c.foo(a);
您不能将 &b
转换为 A*
,因为基数 class 受到保护,无论 C
.
在全局范围内,由于受保护的继承,B 作为 A 不可见。
只有classB本身,class继承自B和classC(因为友情关系)"know"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: