C++ 二义性是什么?怎么解决?

C++ 二义性是什么?怎么解决?

一、什么是二义性

在多继承的场景里,当父类中存在同名变量时,子类访问父类的同名变量,将出现二义性,因为编译器不知道你将要访问的是哪个父类中的变量。

举个例子:

class A

{

public:

int a; // B1,B2 都将继承一个变量 a

};

class B1 : public A

{

};

class B2 : public A

{

};

class C : public B1, public B2

{

};

int main()

{

C c;

c.a = 10; // ERROR ! 二义性 !!!

return 0;

}

二、怎么解决

1. 不使用多继承

一般来说,单继承就可以满足我们 99% 的需求了,我们应该尽量避免使用多继承带来的二义性问题。(注意:这里说的单继承不包括下面说的这种类似于 “接口” 的父类)。

由于 C++ 中不存在接口,但是可以使用只包含纯虚函数的抽象类替代,如果是只包含纯虚函数的抽象类,再多继承都将不会发生二义性(父类都没有变量了当然不会有二义性)。

2. 使用虚继承

虚继承只能解决多个父类的同名变量都是从公共基类中继承而来的情况,就是下图这种:

使用虚继承:

class A

{

public:

int a;

};

class B1 : virtual public A // 虚继承

{

};

class B2 : virtual public A // 虚继承

{

};

class C : public B1, public B2

{

};

int main()

{

C c;

c.a = 10; // OK,不会有二义性了

return 0;

}

原理:使用虚继承时,C++ 编译器会做特殊处理,只会调用一个公共基类 A 的构造方法,这样就不会创建出多个同名变量 a 了。

3. 使用 “类名::变量名” 显性访问

还有一种二义性出现的场景,就是多个父类都是独立的,它们没有公共基类,这些独立的父类中存在同名变量的话,就不能使用虚继承来解决了,类似下图这样子:

这种情况,我们就只能使用 “类名::变量名” 显性访问,避免二义性了:

class B1

{

public:

int a;

};

class B2

{

public:

int a;

};

class C : public B1, public B2

{

};

int main()

{

C c;

c.B1::a = 10;

c.B2::a = 20;

return 0;

}

同样,如果父类还存在同名方法,我们也可以使用 “类名::方法名” 这样显性调用。

相关推荐

仓鼠的寿命有多长?死前有什么征兆?
365bet滚球网

仓鼠的寿命有多长?死前有什么征兆?

📅 06-27 👁️ 2174
建行腾讯e龙卡怎样取现?取现手续费是多少?
监控sh365下载

建行腾讯e龙卡怎样取现?取现手续费是多少?

📅 06-27 👁️ 2856
搞基 漫画
beat365唯一官网

搞基 漫画

📅 07-02 👁️ 7200
excel表四舍五入怎么取消
365bet滚球网

excel表四舍五入怎么取消

📅 06-30 👁️ 9184
详细步骤教你如何在Excel表格中进行数据排序
365bet滚球网

详细步骤教你如何在Excel表格中进行数据排序

📅 06-28 👁️ 4683
请教:胼胝体解剖及功能定位
beat365唯一官网

请教:胼胝体解剖及功能定位

📅 07-03 👁️ 6840
含篑字的成语大全
365bet滚球网

含篑字的成语大全

📅 06-29 👁️ 641
《尼尔机械纪元》存档在哪 游戏存档位置一览
beat365唯一官网

《尼尔机械纪元》存档在哪 游戏存档位置一览

📅 07-04 👁️ 7548
《炉石传说》40卡组版本各职业强度分析,助你选择最佳职业