下图显示了针对此问题的三个独立测试:
(我只关注声明但不关注函数的定义~~)
我想知道为什么正确的人得到错误“'A'是'B'无法访问的基础。”
为什么g ++似乎用派生类初始化对base的引用(由于受保护的继承而导致错误),
而不是像中间的那样使用转换运算符将B转换为A并传入(这是0错误和0警告)?
这是图片中右边的代码:
struct A {
A &operator=( const A & ) { return *this; }
}a;
struct B : protected A {
operator A() { return A(); };
}b;
int main( void )
{
a = b;
return 0;
}
感谢您的帮助!〜
答案 0 :(得分:4)
当你在a = b;
或类外(世界上)编写main()
时,转换发生在那里,而不是在类中,并且可访问性规则适用于转换点(这是课外的)。要进行此类转换,需要从外部(世界)访问基类。
在您的情况下,由于B
是使用A
关键字从protected
派生的,这意味着全世界无法访问A
的{{1}}子对象,因为它无法将b
转换为B
。这一切都发生是因为A
的基数(B
)由于A
继承而无法从世界中获取。设为protected
,转换也会在世界上发生。
现在,这个问题:
为什么不使用用户转换函数而不是继承转换?
由于继承转换优先于用户定义的转换功能,因此您可以将此首选项视为第一步,将第二步视为可访问性规则,转换失败!
答案 1 :(得分:2)
第12.3.2节:
转换函数永远不会用于将(可能是cv限定的)对象转换为(可能是cv限定的)相同的对象类型(或对它的引用),转换为(可能是cv限定的)基类类型(或对它的引用),或(可能是cv-qualified)void。
此外,除了少数例外情况,public
/ protected
/ private
的选择很少会改变程序的功能,只是程序是否有效。因此,初始化会在可能的情况下直接绑定对子对象的引用,而不是使用用户定义的转换,在进行该选择之后,编译器会检查访问权限。