单继承&多继承

一个子类只有一个直接父类时称这种继承关系为单继承。
一个子类有两个或者两个以上的父类时称这种继承关系为多继承。

菱形继承 ---------特殊的多继承


有很大的缺点:

  • 二义性
    如上图,D中会有两份相同的数据,本质都来源于A,在调用派生类里面的这个数据时就会出现问题时就会出现二义性问题。
  • 数据冗余
    D有两个父类,则数据会很多,甚至有重复的,造成数据冗余

解决办法一:加作用域可以解决二义性问题

class Person
{
public:
string _name ; // 姓名
};
class Student : public Person
{
protected :
int _num ; //学号
};
class Teacher : public Person
{
protected :
int _id ; // 职工编号
};
class Assistant : public Student, public Teacher
{
protected :
string _majorCourse ; // 主修课程
};
void Test ()
{
// 显示指定访问哪个父类的成员
Assistant a ;
a.Student ::_name = "xxx";
a.Teacher ::_name = "yyy";
}

解决办法二:虚继承----解决菱形继承的二义性问题和数据冗余问题

虚继承解决二义性与数据冗余的原理

先看这个代码

class A
{
public:int a;
};class B:public A
{
public:int b;
};
class C : public A
{
public:int c;
};class D:public B, public C
{
public:int d;
};int main()
{D d;d.B::a = 1;//有二义性问题,所以加作用域d.C::a = 2;//没加virtual时,这两个a的地址不同d.b = 3; d.c = 4 ;d.d = 5;}

查看两个a的内存,结果就是B,C里面的a内存地址单元不同

d中其他数据:

虚继承以后,B,C中的a的内存单元只有一个,值为2,内存单元中的值先为1,其后变为2

class A
{
public:int a;
};class B:virtual public A   //虚继承
{
public:int b;
};
class C :virtual public A   //虚继承
{
public:int c;
};class D:public B, public C
{
public:int d;
};int main()
{D d;d.B::a = 1;d.C::a = 2;d.b = 3; d.c = 4 ;d.d = 5;}

虚函数解决二义性与数据冗余的本质----虚基表


所以虚继承的特点是虚基类共享同一个对象地址,节省了空间,也避免了数据冗余以及二义性的问题。


lass A
{
public:void set_a(int m){a = m;}int a ;};class B :public A
{
public:void set_b(int n){b = n;}int b;
};class C:public A
{
public:void set_c(int n){c = n;}int c;
};
class D :public B,public C
{
public:void set_d(int n){d = n;}int d;};int  main()
{D d;d.set_a(200);      //a在类B和类C中都有,所以报错,调用不明确d.A::set_a(200);  //加上作用域可以解决这个问题d.set_b(300);d.set_c(400);d.set_d(500);system("pause");return 0;
}
//使用虚基类class A
{
public:void set_a(int m){a = m;cout << a << endl;}int a ;};class B : virtual public A      //虚基类
{
public:void  set_b(int n){b = n;cout << b << endl;}int b;
};class C: virtual public A          //虚基类
{
public:void  set_c(int n){c = n;cout << c << endl;}int c;
};
class D :public B,public C
{
public:void   set_d(int n){d = n;cout << d << endl;}int d;};int  main()
{D d; d.set_a(200);          //设置虚基类类后不会报错d.set_b(300);d.set_c(400);d.set_d(500);cout << d.a << endl;system("pause");return 0;
}

因此菱形继承也会产生二义性和数据冗余的问题的问题,所以尽量不要设计菱形继承,否则就需要用菱形虚继承来解决问题

虚继承和直接继承有什么区别?

  1. 时间上:派生类访问虚继承的所用的时间更久,因为这是通过某种引用来完成的,增加了寻址功能。其实就是调整this指针指向虚基类对象。
  2. 空间上:由于共享所以不必在对象内存中保存多份虚基类对象的拷贝,这样比直接继承省空间。

继承于static成员函数

基类定义了一个(static)静态成员,派生类可以继承,实际上来说整个继承体系中都只有一个static成员,无论有多少个派生类,派生类和父类中的static共用空间。

class base
{
public:static int a;
};
int base::a = 100;class devired  :public base
{
public:int d;
};int main()
{devired d;cout<<d.a<<endl;   //结果为100system("pause");}

继承与友元

在C++中,派生类把基类中所有的成员继承过来,除了构造函数和析构函数。
友元函数不属于类,它只是给类开了一个后门
本来类外不可以访问类的私有成员,通过友元函数就可以
所以不能继承。子类继承父类,那么默认的,就是继承了父类的成员函数和成员变量。

继承(下)----虚继承相关推荐

  1. 继承、虚继承、虚函数内存分布(MSVC下)

    前提知识: 对象的内存中只包含成员变量,存储在栈区或堆区(使用 new 创建对象): 成员函数与对象内存分离,存储在代码区. 对象的大小,可以自己分析,int 四个字节,指针也是四个字节.(在x86中 ...

  2. C++ 多继承和虚继承的内存布局

    原文链接:https://www.oschina.net/translate/cpp-virtual-inheritance 警告. 本文有点技术难度,需要读者了解C++和一些汇编语言知识. 在本文中 ...

  3. C++继承详解三 ----菱形继承、虚继承

    转载:http://blog.csdn.net/pg_dog/article/details/70175488 今天呢,我们来讲讲菱形继承与虚继承.这两者的讲解是分不开的,要想深入了解菱形继承,你是绕 ...

  4. 菱形继承和虚继承、对象模型和虚基表

    1.菱形继承(钻石继承):两个子类继承同一父类,而又有子类同时继承这两个子类.例如B,C两个类同时继承A,但是又有一个D类同时继承B,C类. 2.菱形继承的对象模型 class A { public: ...

  5. C++继承机制(三)——多继承、菱形继承、虚继承原理

    目录: C++继承机制(一)--基本语法.三种继承方式.继承哪些数据 C++继承机制(二)--继承中的构造和析构顺序.继承同名成员的处理方式 C++继承机制(三)--多继承.菱形继承.虚继承原理 本篇 ...

  6. C++对象模型:单继承,多继承,虚继承

    什么是对象模型 有两个概念可以解释C++对象模型: 语言中直接支持面向对象程序设计的部分. 对于各种支持的底层实现机制. 类中成员分类 数据成员分为静态和非静态,成员函数有静态非静态以及虚函数 cla ...

  7. C++57个入门知识点_50 菱形继承与虚继承(C++中语法允许多重继承造成菱形继承;会造成近亲结婚的问题;可以通过虚继承的方式解决;实际项目中不多用多重继承)

    上篇C++57个入门知识点_49 多重继承与组合(一个类同时具有多个类的属性的方法:多重继承或者组合:多重继承:一个类同时继承多个类:多重继承构造和析构的顺序与普通继承类似:组合:类中包含多个成员对象 ...

  8. C++普通继承和虚继承详解

    继承 继承概念 所谓的继承就是一个类继承了另一个类的属性和方法,这个新的类包含了上一个类的属性和方法,被称为子类或者派生类,被继承的类称为父类或者基类. 继承特点 子类拥有父类的所有属性和方法(除了构 ...

  9. C++多继承与虚继承

    目录 多继承与虚继承以及存在的问题 例子 多继承与虚继承以及存在的问题 虚继承 有了多继承,虚继承才会有意义 如果有个菱形结构的继承,爷爷类为A,然后B,C是A的派生类,最后D是B和C的派生类, 如果 ...

  10. C++之菱形继承与虚继承(含虚函数)

    面向对象的三大特征:封装,多态,继承 前面我们已经讲了继承的一些知识点,在这基础上,我们讲的时候再涉猎一些多态的只是. 下面我们先接着上次讲有虚函数的菱形虚继承 首先什么是虚函数.? 虚函数:在类里面 ...

最新文章

  1. Error:warning: Ignoring InnerClasses attribute for an anonymous inner class
  2. Zip Slip目录遍历漏洞已影响多个Java项目
  3. android 验证输入,最佳实践:输入验证(Android)
  4. docker环境给elasticsearch安装ik分词
  5. 上海启动5G试用!104页PPT,为你深度解析5G终端的创新和机遇
  6. 周志华《机器学习》读书笔记(一)
  7. Nacos源码NacosAutoServiceRegistration
  8. 弱口令上传shell_emlog后台拿shell
  9. Spring构造函数注入和参数名称
  10. 抢占式和非抢占式的进程调度
  11. 论文浅尝 - COLING2020 | 桥接文本和知识的多原型嵌入在少样本关系三元组抽取中的研究...
  12. 什么是气泡图?怎样用Python绘制?怎么用?终于有人讲明白了
  13. Fragment学习笔记
  14. WPF 自定义BarChartControl(可左右滑动的柱状图)
  15. 苹果和FBI出庭日期延后
  16. 车载网络技术革新-CAN FD浅析
  17. css浮动会有什么影响,CSS,浮动及其影响
  18. Rplidar A2 屏蔽固定角度
  19. 计算机课堂小游戏活跃气氛,活跃气氛课堂互动小游戏大全
  20. 易语言从c盘开始搜索文件夹,易语言递归寻找文件及文件夹

热门文章

  1. Thymeleaf 表单回填
  2. snat与dnat的区别
  3. 软件实施工程师远程连接_新研究生远程软件工程师的大流行生存指南。
  4. Visual Studio 2019(VS2019) 基本操作
  5. zabbix6.0安装成功路上的小插曲
  6. 地图上如何量方位角_正距方位图是怎么画出来的?应该怎么看?有什么特点?...
  7. (转)TSQL和PLSQL的区别
  8. Linux一键安装xrdp,如何在Linux系统Ubuntu 20.04中安装xrdp实现远程桌面连接RDP
  9. BeanUtils.populate()封装bean属性为null的四种失效原因
  10. golang: Google Play退款订单数据查询