C++多路径继承中通过基类作用域访问成员为何无歧义?
问题原因分析
1. 为什么没有出现歧义报错
- 首先明确:该代码不符合C++标准要求,你观察到的无报错是特定编译器的非标准扩展行为。
- 按照C++标准的名字查找规则:你的代码中B、C都非虚继承自A,所以D类实例会包含两个独立的A类子对象(分别属于B路径和C路径)。当你使用
d.A::x写法时,编译器无法确定你要访问哪一个A子对象的x成员,标准规定这种场景必须抛出歧义错误。 - 你没有得到报错,大概率是使用了旧版本MSVC编译器,它默认开启了非标准扩展:遇到这种歧义场景时,会默认选择类继承声明列表中第一个基类对应的A子对象,不会抛出报错。
2. 为什么输出值为5
- 你的D类继承声明顺序是
public B, public C,B是第一个声明的基类,按照上述编译器扩展的规则,实际访问的是B路径下的A子对象。 - 构造D实例
d(5,6)时,传给B构造函数的参数是5,B的构造函数会调用A的带参构造函数将x赋值为5,所以最终输出结果为5。
符合C++标准的正确写法
如果你要明确指定访问的成员路径,应该写全继承路径:
- 访问B路径下A的x成员:
d.B::x或者d.B::A::x - 访问C路径下A的x成员:
d.C::x或者d.C::A::x
如果你要从设计上消除D的多份A子对象问题,可以使用你提到的虚继承:将B、C的继承声明修改为class B : virtual public A、class C : virtual public A即可,此时D实例只会保留一份A子对象,直接访问d.x也不会有歧义。
内容的提问来源于stack exchange,提问作者Vivek Mangal
相关产品推荐
相关产品推荐

