文章目录

  • 前言:
  • 1.多重继承
    • 1.1 多重继承的概念
    • 1.2 多重继承的用法
    • 1.3 多重继承的弊端:二义性
  • 2.虚基类
    • 2.1 虚基类的概念
    • 2.2 虚基类的初始化
    • 2.3 使用注意事项

前言:

本篇文章主要介绍了C++多重继承和虚基类


1.多重继承

1.1 多重继承的概念

多继承/多重继承:
一个派生类可以有两个或多个基类(父类)。
多重继承在中小型项目中较少使用,在Java、C#等语言中直接取消多继承, 以避免复杂性.

1.2 多重继承的用法

class D: public A, private B, protected C{//多继承的构造函数D(形参列表):A(实参列表),B(实参列表),C(实参列表)
};

注意:多继承的构造函数的调用顺序
基类构造函数的调用顺序和和它们在派生类构造函数中出现的顺序无关,
而是和声明派生类时基类出现的顺序相同。

1.3 多重继承的弊端:二义性

假设派生类C有两个基类A和B,并且A和B都有print方法。那么,当C类对象调用print方法时会产生歧义。

class A {public:void print(){cout << "A:hello" << endl;}
};
class B {public:void print(){cout << "B:hello" << endl;}
};
class C : public A,public B{public:void C::print(){A::print();B::print();cout << "C:hello" << endl;}
};
int main() {C c;//解决歧义的方法1:使用类名指定从哪个基类继承的方法c.A::print();c.B::print();//解决歧义的方法2:在子类中重新实现这个同名方法 并在这个方法内部,\使用基类名进行限定, 来调用对应的基类方法c.print();return  0;
}

2.虚基类

2.1 虚基类的概念

当在多条继承路径上有一个公共的基类,在这些路径中的某几条汇合处,这个公共的基类就会产生多个实例(或多个副本),若只想保存这个基类的一个实例,可以将这个公共基类说明为虚基类。

在继承中产生歧义的原因有可能是继承类继承了基类多次,从而产生了多个拷贝,即不止一次的通过多个路径继承类在内存中创建了基类成员的多份拷贝。虚基类的基本原则是在内存中只有基类成员的一份拷贝。这样,通过把基类继承声明为虚拟的,就只能继承基类的一份拷贝,从而消除歧义。用virtual限定符把基类继承说明为虚拟的。 假设D类继承自B和C类,B和C类又都继承自A类,为了不让D中继承自A的内容重复,此时可以把A类要说明为虚基类。

#include <iostream>
#include <string>
#include <sstream>using namespace std;class A {public:A(){cout << __FUNCTION__ << endl;}void print(){cout << "msg:" << msg << endl;}
protected:string msg = "A";
};
//只需在继承时用关键字virtual修饰,即可把父类说明为虚基类(在该条继承路径上)
class B : virtual public A {public:B():A(){cout << __FUNCTION__ << endl;msg = "B";}
};
class C : virtual public A{public:C():A(){cout << __FUNCTION__ << endl;msg = "C";}
};
class D : public B,public C{public:D():A(),B(),C(){ // 忽略A,B之前的构造cout << __FUNCTION__ << endl;// C::msg = "D";msg = "D";}
};
int main() {D d;d.print();return  0;
}

2.2 虚基类的初始化

虚基类的初始化与一般多继承的初始化在语法上是一样的,但构造函数的调用次序不同。派生类构造函数的调用次序有三个原则:
(1)虚基类的构造函数在非虚基类之前调用;
(2)若同一层次中包含多个虚基类,这些虚基类的构造函数按它们说明的次序调用;
(3)若虚基类由非虚基类派生而来,则仍先调用基类构造函数,再调用派生类的构造函数。

2.3 使用注意事项

(1) 一个类可以在一个类族中既被用作虚基类,也被用作非虚基类。
(2) 在派生类的对象中,同名的虚基类只产生一个虚基类子对象,而某个非虚基类产生各自的子对象。
(3) 虚基类子对象是由最远派生类的构造函数通过调用虚基类的构造函数进行初始化的。
(4) 最远派生类是指在继承结构中建立对象时所指定的类。
(5) 派生类的构造函数的成员初始化列表中必须列出对虚基类构造函数的调用;如果未列出,则表示使用该虚基类的缺省构造函数(默认)。
(6) 从虚基类直接或间接派生的派生类中的构造函数的成员初始化列表中都要列出对虚基类构造函数的调用。但仅仅用建立对象的最远派生类的构造函数调用虚基类的构造函数,而该派生类的所有基类中列出的对虚基类的构造函数的调用在执行中被忽略,从而保证对虚基类子对象只初始化一次。
(7) 在一个成员初始化列表中同时出现对虚基类和非虚基类构造函数的调用时,虚基类的构造函数先于非虚基类的构造函数执行。

C++类的多继承和虚基类相关推荐

  1. C++中的虚继承与虚基类

    1.Cpp中的虚继承与虚基类 在多继承时,很容易产生命名冲突的问题,即使我们很小心地将所有类中的成员变量和成员函数都命名为不同的名字,命名冲突依然有可能发生,比如典型的是菱形继承,如下图所示: 类A派 ...

  2. [YTU]_2622(B 虚拟继承(虚基类)-沙发床(改错题))

    题目描述 有一种特殊的床,既能当床(Bed)用又能当沙发(Sofa)用,所以叫沙发床(SleeperSofa). 同时床和沙发又是一种特殊的家具(Furniture),具有一切家具的特性. 利用虚拟继 ...

  3. 多重继承、虚继承与虚基类

    一.多重继承 单重继承--一个派生类最多只能有一个基类 多重继承--一个派生类可以有多个基类 class 类名: 继承方式 基类1,继承方式 基类2,-. {-.}; 派生类同时继承多个基类的成员,更 ...

  4. C++ 虚拟继承与虚基类

    1.多重继承带来的问题 C++ 虚拟继承一般发生在多重继承的情况下.C++ 允许一个类有多个父类,这样就形成多重继承.多重继承使得派生类与基类的关系变得更为复杂,其中一个容易出现问题是某个基类沿着不同 ...

  5. C++中的各种“虚“-- 虚函数、纯虚函数、虚继承、虚基类、虚析构、纯虚析构、抽象类讲解

    C++中的各种"虚" 1. 菱形继承 1.1 虚继承 && 虚基类 1.2 虚基类指针(vbptr)&& 虚基类表(vbtable) 2. 多态 2 ...

  6. C++:94---类继承(菱形继承、虚继承(virtual虚基类))

    一.菱形继承 在介绍虚继承之前介绍一下菱形继承 概念:A作为基类,B和C都继承与A.最后一个类D又继承于B和C,这样形式的继承称为菱形继承 菱形继承的缺点: 数据冗余:在D中会保存两份A的内容 访问不 ...

  7. 【C++】继承和派生、虚继承和虚基类、虚基类表和虚基类指针

    继承和派生.虚继承和虚基类.虚基类表和虚基类指针 继承和派生 继承概述 继承基本概念 派生类中的成员 继承的内容 派生类定义 派生类访问控制 对象构造和析构 对象构造和析构的调用顺序 继承中的构造和析 ...

  8. C++虚继承和虚基类详解(二)

    虚继承(Virtual Inheritance) 为了解决多继承时的命名冲突和冗余数据问题,C++ 提出了虚继承,使得在派生类中只保留一份间接基类的成员. 在继承方式前面加上 virtual 关键字就 ...

  9. 类型转换,类与类之间的转换,继承关系,继承与静态变量,子类父类重名,多继承,虚基类

     常量的基本类型转换,例如:int num(10.8),这种方式是隐式转换. 通过函数的构造函数实现转换. 类类转换函数,当构造函数不能将类型转换成基本类型时.所以就有了类类转换函数,通过这种方式 ...

最新文章

  1. 折半插入排序稳定吗_C++实现经典算法--折半插入排序
  2. 写python程序用什么软件最好-Python必学之编译器用哪个好?你用错了吧!
  3. 第二章: ORacle 自带用户讲解、oracle的开发工具、oracle客户端的配置、以及常见连接报错
  4. python中模块和函数_Python中函数和模块的体验与使用
  5. 2019年,你需要关注这些Node API和Web框架
  6. 数字图像处理实验(2):PROJECT 02-02, Reducing the Number of Gray Levels in an Image
  7. 注入工具的原理和开发
  8. C#基于Socket的CS模式的完整例子
  9. koa --- 使用中间件多层级抛出错误
  10. continue 的用户及实例
  11. Teams架构剖析(2019年版本)
  12. 使用Lucene的搜索服务器搜索Jira问题
  13. ffmpeg检测文件是否损坏_教你一招如何检测硬盘,让你知道硬盘是否有损坏?还有几天寿命?...
  14. Linux脚本验证的常见方法,linux shell常用循环与判断语句(for,while,until,if)使用方法...
  15. Nginx中的upstream轮询机制介绍
  16. 如何更改mssq,SSAS l代理运行身份验证
  17. git SSH密钥生成及部署
  18. 【经验贴】本科生毕业论文答辩经验
  19. 【规范】C/C++注释格式
  20. apipost中文版

热门文章

  1. python解析jmeter.jtl文件_通过ant-jmeter读取jtl文件拆分数据并insert DB
  2. 架设Apache服务器
  3. DiskGenius分区工具
  4. Discuz! 6.1.0提示来路信息不正确问题的解决办法
  5. jacob操作word查找替换转为pdf
  6. Android 展示一个图片,可以双击放大/缩小(放大后可以移动)
  7. c++代码模拟微信抢红包算法,没人抢得过你!
  8. 一中高考的成绩查询2021年,2021年张家口高考成绩排名及成绩公布时间什么时候出来...
  9. I Wanna Go Home(Dijkstra)--C++实现
  10. Android高仿qq及微信底部菜单的几种实现方式