在C ++中传递参数时,继承类之间的类型转换

时间:2013-01-02 05:02:08

标签: c++ inheritance reference type-conversion

下图显示了针对此问题的三个独立测试:

(我只关注声明但不关注函数的定义~~)

http://i.stack.imgur.com/wYtA6.png

我想知道为什么正确的人得到错误“'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;
}

感谢您的帮助!〜

2 个答案:

答案 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的选择很少会改变程序的功能,只是程序是否有效。因此,初始化会在可能的情况下直接绑定对子对象的引用,而不是使用用户定义的转换,在进行该选择之后,编译器会检查访问权限。