在钻石继承体系中,一定要用虚继承!

1.下面的代码块儿无法通过编译,原因是,A3无法确定自己到底是用哪一个父类中的函数。

class A
{
public:
virtual void f(){}
virtual void g(){}
};
class A1 : virtual public A
{
public:
virtual void f()
{
}
};
class A2:  virtual public A
{
public:
virtual void f()
{
}
};
class A3 : public A1, public A2
{
};

下面这个通过了编译。原因是,A3确定了自己的实现方式。

class A
{
public:
virtual void f(){}
virtual void g(){}
};
class A1 : virtual public A
{
public:
virtual void f()
{
}
};
class A2:  virtual public A
{
public:
virtual void f()
{
}
};
class A3 : public A1, public A2
{
public:
virtual void f()
{
}
};

下面的代码中,A3仍然无法确定自己的实现方式。但是可以定义A3的对象。这是因为每一个函数只有一个虚函数表。

class A
{
public:
virtual void f(){}
virtual void g(){}
};
class A1:  public A{};
class A2:  public A{};
class A3:  public A1, public A2{};

同理,下面的代码也能通过编译:

class A
{
public:
virtual void f(){}
virtual void g(){}
};
class A1:  public A //不需要虚继承
{
public:
virtual void f(){}
};
class A2:  public A //不需要虚继承
{
public:
virtual void g(){}
};
class A3:  public A1, public A2
{
};

同理,下面的代码也能通过编译:

class A  { public:virtual void f(){} };
class A1: public A{};
class A2: public A{};
class A3: public A1, public A2{};

但是。这三种方式存在一个致命的弱点,就是,如果不用虚继承。下面的代码无法通过编译:

  A3 a3;   A& a = a3;

用虚继承:则可通过

class A
{
public:
virtual void f(){}
virtual void g(){}
};
class A1:  virtual public A
{
public:
virtual void f(){}
};
class A2:  virtual public A
{
public:
virtual void g(){}
};
class A3:  public A1, public A2
{
};
 A3 a3;
A& a = a3;
虚继承的含义是,不一定会为孙子类提供实现。
为孙子类提供实现的有可能是自己,也有可能是兄弟,也有可能是父类。
在钻石继承体系中,一定要用虚继承来避免在钻石体系中的二义性

关于虚继承(在钻石继承体系中,一定要用虚继承!)相关推荐

  1. C++编程进阶5(内联函数、如何降低编译成本、处理继承体系中同名不同参的成员函数、私有虚函数)

    十七.内联函数 在https://blog.csdn.net/Master_Cui/article/details/106391552中,已经简单的说过内联函数的作用. 函数体较小的内联函数经过编译后 ...

  2. C++多继承中重写不同基类中相同原型的虚函数

    在C++多继承体系当中,在派生类中可以重写不同基类中的虚函数.下面就是一个例子: class CBaseA  {  public:  virtual void TestA();  };  class ...

  3. c/c++入门教程 - 2.4.6 继承、公共继承、保护继承、私有继承、virtual虚继承(概念、语法、方式、构造和析构顺序、同名成员处理、继承同名静态成员处理、多继承语法、菱形继承、钻石继承)

    目录 4.6 继承 4.6.1 继承的基本语法 4.6.2 继承方式 4.6.3 继承中的对象模型 4.6.4 继承中构造和析构顺序 4.6.5 继承同名成员处理方式 4.6.6 继承同名静态成员处理 ...

  4. 浅谈c++中继承体系中易错点

    浅谈c++中继承体系中易错点 目前,就我工作经验来看,在c++中继承体系中总爱搞错的有两点: 不把基类中需要覆盖的方法为设置为虚方法. 不把基类中的析构函数设置为虚方法. 就第一点而言,如果基类中需要 ...

  5. C++对象内存布局--③测试多继承中派生类的虚函数在哪一张虚函数表中

    C++对象内存布局--③测试多继承中派生类的虚函数在哪一张虚函数表中 测试2:证明派生类的虚函数的地址跟第一基类的虚函数地址保存在同一张虚函数表中. 派生类有多少个拥有虚函数的基类,派生类对象就有多少 ...

  6. C++学习笔记-----继承体系中函数的重载,覆盖和隐藏的区别

    1.重载,在同一个作用域中定义的同名不同参的一些函数为重载. 2.隐藏,若在基类中定义了某一non_virtual函数,在派生类重存在同名函数(不需要参数列表相同),基类的该函数在派生类中是不可见的, ...

  7. 某IT公司有多名员工,按员工负责的工作不同,进行了部门的划分(研发部员工、维护部员工)。完成员工体系中所有类的定义,并指定类之间的继承关系。进行xx工程师类的对象创建,完成工作方法的调用。

    某IT公司有多名员工,按员工负责的工作不同,进行了部门的划分(研发部员工.维护部员工).研发部根据所需研发的内容不同,又分为JavaEE工程师.Android工程师:维护部根据所需维护的内容不同,又分 ...

  8. C++之继承探究(十):抽象基类与纯虚函数

    前文:C++之继承探究(九):多态的代价 抽象基类与纯虚函数   ♠\spadesuit♠ 纯虚函数:虚函数只有声明,函数体=0,就是一个纯虚函数,纯虚函数没有函数体,不需要实现.在子类里实现纯虚函数 ...

  9. C++ day22 继承(二)基类指针数组通过虚方法实现智能的多态

    继承一共有三种: 公有继承 私有继承 保护继承 文章目录 公有继承 基类和派生类的关系 is-a(用公有继承表示"是一种"的关系) has-a uses-a is-like-a i ...

最新文章

  1. 3.实现串口功能及消息邮箱
  2. 3个CCIE对一个工程师的面试题(远去之路无比艰辛啊!)
  3. 为什么说 Java 中只有值传递?
  4. 天池实验室Python能力测验
  5. HDU - 3397 Sequence operation(线段树+区间合并)
  6. Javascript启动LINUX的x86模拟器
  7. 训练日志 2019.1.31
  8. Dubbo(十二)dubbo的服务版本配置以及本地存根使用介绍
  9. 亚马逊创始人贝佐斯离婚协议本周生效 前妻分得380亿美金
  10. 企业在信息化建设上乘之选:软件快速开发框架
  11. 数据化、信息化、数字化和智能化之间联系和区别解析(建设收藏)
  12. html网页特效代码笔记,一个js实现的网页鼠标点击特效代码
  13. 设置VS201X release模式下可单步调试
  14. 什么是JSX、是如何使用以及注意事项
  15. GoLang之取地址符、指针
  16. Zoho 企业邮箱不可用修复方案
  17. SocketInputStream.socketRead0 导致线程hangs的解决方案
  18. Linux文件类型与扩展名
  19. jenkins通过git拉取大项目出现拉取失败的情况Error fetching remote repo ‘origin’
  20. 人工智能1—K-means聚类算法

热门文章

  1. php 如何判断是否搜索出结果,搜索PHP - 如何调出搜索框没有结果
  2. gradient设置上下渐变_iOS 绘制渐变·实例篇
  3. 存储过程结果更改编码_Docker安装Minio存储服务器详解
  4. python简单小游戏实现_python基础--小游戏简单实现
  5. 8.QT的事件循环与事件发送相关类
  6. HALCON完全卸载重装
  7. 回调函数方法连续采集和发送软触发采集
  8. linux安装mysql5.6.26_linux mysql-5.6.26 安装
  9. Oracle别名大小写 -----解决方案
  10. PHP正则表达式规则及常用方法整理