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;
}
同样,如果父类还存在同名方法,我们也可以使用 “类名::方法名” 这样显性调用。
C++ 二义性是什么?怎么解决?相关推荐
- C++中的同名二义性和路径二义性
继承机制中的二义性分为:同名二义性和路径二义性.以下用两个图解释两种二义性的区别和解决方法: 或(图画的丑不要介意) 如图1: D d; d.x;此时d.x指的是C的x还是D的x,即出现了同名二义性. ...
- VMprotect静态跟踪 字节码反编译
文章目录 VMprotect静态跟踪 (1)虚拟执行特点: (2)执行引擎的虚拟执行 (3)分析条件跳转的两条出边 字节码反编译 (1)中间表示语言 (2)指令化简和优化 **常数收缩:** **活跃 ...
- [一道搜狗输入法的面试题]C++转换构造函数和类型转换函数
今天面试遇到一道有关C++转换构造函数的题目,之前经常见到默认构造函数.拷贝构造函数.析构函数,但是从没听说过转换构造函数,隐式转换函数也是一样,C++的确是够博大精深的,学习之路很长啊! 其实我们已 ...
- 学习算法你必须知道的一些基础知识(文末福利)
点击标题下「异步社区」可快速关注 机器学习是解决很多文本任务的基本工具,本文自然会花不少篇幅来介绍机器学习.要想搞明白什么是机器学习,一定要知道一些概率论和信息论的基本知识,本文就简单回顾一下这些知识 ...
- 【C++快速入门】面向对象篇
面向对象 类与对象 对象的内存布局 *this 与 指针访问对象成员的本质 封装性 内存空间的布局 堆空间 memset与堆内存的初始化 对象的内存(数据段.栈空间.堆空间) 构造函数(Constru ...
- 度量相似性数学建模_数学之美读书笔记
2020年6月读,先通读一遍,随后为写读书笔记又重新读了一遍,收获颇丰,虽然没有很多数学或者编程方面的知识,但正如作者所说,这本书讲述的是道,而非术. 读这本书让我领略到了科学的趣味,并不是枯燥的敲代 ...
- Java学习之路——接口
Java学习之路--接口 概述 总所周知,我们是父母的孩子.我们的身上既继承了爸爸的基因也继承了妈妈的基因.这就是多继承. 然而在 Java 程序中,是不支持多继承的.Java 仅仅支持单继承.但是接 ...
- C++期末考试选择题题库100道
1. 对于常数据成员,下面描述正确的是 [ B ] A. 常数据成员必须被初始化,并且不能被修改 B. 常数据成员可以不初始化,并且不能被修改 C. 常数据成员可以不初始化,并且可以被修改 D. 常数 ...
- C++学习笔记和面试备考(二, 转)
简述局部作用域,全局作用域和类作用域的异同 一个定义于某模块中的函数的全局作用域是该模块的命名空间,而不是该函数的别名被定义或调用的位置 虽然作用域是静态定义的,在使用时作用域是动态的.在任何运行时刻 ...
- 【实习秋招篇之C++面经】
C++必背面经 一. C++的理解,C和C++的区别. 二. Struct和class的区别 三. Strlen和sizeof的区别 四. 面向对象的理解 五. C++内存分布 六. 智能指针 七. ...
最新文章
- 一部手机,万物皆可复制粘贴,将AR玩出了新高度
- [转][Timer学习]wall time和monotonic time
- CMarkup类在VC中的使用
- 设计爬虫Hawk背后的故事
- unity 日志级别_【Unity】通用的Debugger日志模块
- 《媒体曝70多万种药品“底价”:普遍超厂价5-6倍》——典型的媒体噱头唬人行为...
- LeetCode 283. Move Zeroes
- iOS 两种易混淆的存储路径
- 菜鸟教程php上传图片,PHP 文件上传
- 2019.1.31及以前
- Python基础-字典(字典常用函数/操作/字典遍历)
- POJ 3683 Priest John's Busiest Day
- Android 去除头部标题
- 计算机检测不到蓝牙,图解Win10 1809系统中检测不到蓝牙设备的方法
- Strings must be encoded before hashing
- 奇葩说Cisco router与PC交互(一)
- [学习笔记]使用GNU Toolchain在STM32上跑起一个最小OS
- wxappUnpacker 微信小程序反编译 2019 9月使用问题总结
- 我,32岁零基础转大数据,不需要别人怎么看!
- 装了 Linux 之后就感到迷茫、不知该干什么的朋友看过来
热门文章
- python调用scp上传目录_python执行scp命令拷贝文件及文件夹到远程主机的目录方法...
- 中国不是不能开发出自己的浏览器,而是没必要
- 蓝牙(BLE)自动配对
- 读论文:Fine-grained Image Classification via Combining Vision and Language
- linux安装nginx防火墙,Centos7 防火墙关闭与nginx无法访问
- pwm调速流程图小车_求智能小车 PWM调速?
- 精益看板方法从理论到实战 (5)—— 控制在制品数量(上)
- 微信Mars-xlog日志加密踩坑指南
- 高仿android 版微信(服务端,客户端都有)
- win10 系统锁屏壁纸的目录