C++多重继承二义性原理实例解析
作者:知道了呀 发布时间:2021-10-08 20:18:33
标签:C++,多重,继承,二义性
在派生类中对基类成员访问应该是唯一的,但是在多继承时,可能会导致对基类某成员访问出现不一致的情况,这就是C++多继承中的二义性。
有两种继承的情况会产生多义性
一、如果一个派生类从多个基类派生,而这些基类又有一个共同的基类,则在对该基类中声明的成员变量进行访问时,可能产生二义性,继承关系如下图所示:
#include <iostream>
using namespace std;
class A{
public:
int a;
};
class B1 : public A{
public:
int b1;
};
class B2 : public A{
public:
int b2;
};
class C : public B1, public B2{
public:
int c;
};
int main(){
C c1;
c1.b1 = 100;
c1.b2 = 200;
c1.c = 300;
c1.a = 500; //报错,不能确定成员变量a具体在那个类
cout << "end..." << endl;
system("pause");
return 0;
}
解决方法:虚继承
注意:C++编译系统在实例化C类时,只会将虚基类A的构造函数调用一次,忽略虚基类的其他派生类(class B1,class B2)对虚继承的构造函数的调用,从而保证了虚基类的数据成员不会被多次初始化。
在虚基类A中有一个虚指针指向一个虚表,虚表中记录了虚基类与本类的地址偏移,通过这个地址偏移可以找到虚基类的成员变量a的地址
#include <iostream>
using namespace std;
class A{
public:
int a;
};
class B1 : virtual public A{
public:
int b1;
};
class B2 : virtual public A{
public:
int b2;
};
class C : public B1, public B2{
public:
int c1;
};
int main(){
C c1;
c1.b1 = 100;
c1.b2 = 200;
c1.c1 = 300;
c1.a = 500; //虚继承使得成员变量a只有一份拷贝,通过虚指针可以确定地址
cout << "end..." << endl;
system("pause");
return 0;
}
二、一个派生类同时继承两个基类,这两个基类存在相同的成员函数
#include<iostream>
using namespace std;
class Base1 {
public:
void fun() {
cout << "I am base-1 " << endl;
};
};
class Base2
{
public:
void fun() {
cout << "I am base-2 " << endl;
};
};
class A: public Base1, public Base2 {
public:
void print() {
}
};
int main() {
A obj;
obj.fun(); //调用的方法产生歧义
system("pause");
return 0;
}
解决方法:使用作用域运算符::来解决,明确指向的方法,例如obj.Base1::fun()
来源:https://www.cnblogs.com/-citywall123/p/13175635.html


猜你喜欢
- 今天看《第一行代码》上面关于拍照和从相册选取图片那一部分,发现始终出不来效果,所以搜索其他资料学习一下相关知识,写一个简单的Demo。&nb
- 一.方法的基本使用1.什么是方法方法是一个代码片段,类似于C语言中的函数2.方法基本语法基本语法 // 方法定义
- 目录引言配置yml文件创建数据源配置类为每个数据库创建配置类引言今天为大家带来一些非常有用的实战技巧,比如在我们需要对两个数据库进行操作的时
- 大家好,我是梦辛工作室的灵,最近在帮客户修改安卓程序时,有要求到一个按钮要浮动在键盘的上方,下面大概讲一下实现方法:其实很简单,分三步走第一
- /* * 文 件 名: DataCleanManager.java * 描 &nb
- SQL 映射XML 文件是所有sql语句放置的地方。需要定义一个workspace,一般定义为对应的接口类的路径。写好SQL语句映射文件后,
- 这个是常见的对二叉树的操作。总结一下:设节点的数据结构,如下:class TreeNode { char
- 摘要:介绍使用Java Stream流排序器Comparator对List集合进行多字段排序的方法,包括复杂实体对象多字段升降序排序方法。综
- Git和其他版本控制系统如SVN的一个不同之处就是有暂存区的概念。先来看名词解释。工作区(Working Directory)就是你在电脑里
- 1. 确保你项目能编译通过,安装java jdk 环境填写环境变量2. 添加SpringBootServletInitializer的子类重
- 在IntelliJ IDEA中一不小心将你本地代码给覆盖了,这个时候,你 ctrl + z
- 目前地图开放平台三大巨头:高德、百度、腾讯基本都支持Flutter插件开发集成。从这里也能看出Flutter的生态在逐渐的完善。下面介绍下在
- 一、Quartz的特点* 按作业类的继承方式来分,主要有以下两种:1.作业类继承org.springframework.scheduling
- android提供的工具链和开发工具比较完善,因此它的开发环境的搭建比较简单,相信许多朋友都已经搭建好环境,并编写了HelloA
- 这篇文章主要介绍了Java内存缓存工具Guava LoadingCache使用解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有
- 前言在前面的2个章节中,一一哥 带大家实现了在Spring Security中添加图形验证码校验功能,其实Spring Security的功
- name和url属性的作用定义feign是声明式的web service客户端,它让微服务之间的调用变得更简单了,类似controller调
- 前言:Stream API 和 Lambda 是Java8的重要特性让我们可以使用更具功能性的语法风格。但是在编写的代码时候一个更大的问题是
- 前言:这里所说的全局Dialog是指无论当前应用是处于哪一个页面上,都能够及时弹出Dialog来提示用户一些信息,用户体验不会很好,一般应用
- Spring-boot目的Spring是为了解决企业应用开发的复杂性而创建的,简化开发Spring如何简化开发1.基于POJO的轻量级和最小