1.多重继承的构造次序:基类构造函数按照基类构造函数在类派生列表中的出现次序调用,构造函数调用次序既不受构造函数初始化列表中出现的基类的影响,也不受基类在构造函数初始化列表中的出现次序的影响。

2.在单个基类情况下,派生类的指针或引用可以自动转换为基类的指针或引用,对于多重继承也是如此,派生类的指针或引用可以转换为其任意基类的指针或引用。

3.多重继承像单继承一样,用基类的指针或引用只能访问基类中定义(或继承)的成员,不能访问派生类中引入的成员。
   当一个类继承于多个基类的时候,那些基类之间没有隐含的关系,不允许使用一个基类的指针访问其他基类的成员。

4.如果用户自己定义了派生类自己的复制构造函数或赋值操作符,则用户要负责复制(赋值)所有的基类子部分。而对于编译器默认合成的派生类的复制构造函数或赋值操作符会自动复制或赋值基类部分。

5.在多重继承下,通常成员函数中使用的名字的查找首先在函数本身进行,如果不能在本地找到名字,就继续在成员的类中查找,然后依次查找每个基类。注意名字查找总是按照两个步骤进行的:(1)首先编译器找到一个匹配的声明(与参数、返回值、公有私有均没有关系,只与名字有关) (2)然后,编译器才确定所找到的声明是否合法。

6.虚继承是一种机制,类通过虚继承指出它希望共享其虚基类的状态。在虚继承下,对给定虚基类,无论该类在派生类层次中作为虚基类出现多少次,只继承一个共享的基类子对象。共享的基类子对象称为虚基类。
例如:

class istream: public virtual ios{ /*....*/ };
class ostream: virtual public ios{ /*....*/ };

7.通过用关键字virtual修改声明,将基类指定为通过虚继承派生:

class istream: public virtual ios{ /*....*/ };
class ostream: virtual public ios{ /*....*/ };

指定虚派生只影响从指定了虚基类的类派生的类。除了影响派生类自己的之外,它也是关于派生类与自己的未来派生类的关系的一个陈述。virtual说明符陈述了在后代派生类中共享指定基类的单个实例的愿望。
 
8.每个类只初始化自己的直接类。在应用于虚基类的时候,这个初始化策略会失败。如果使用常规规则,就可能会多次初始化虚基类。为了解决这个重复初始化问题,从具有虚基类的类继承的类对初始化进行特殊处理。在虚派生中,由最低层派生类的构造函数初始化虚基类。
      虽然由最低层派生类初始化虚基类,但是任何直接或间接继承虚基类的类一般也必须为该基类提供自己的初始化式。只要可以创建虚基类派生类类型的独立对象,该类就必须初始化自己的虚基类,这些初始化式只在创建中间类型的对象时使用。

例如:

在我们的层次中,可以有Bear、Raccoon或Panda类型的对象。创建Panda对象的时候,它是最低层派生类并控制共享的ZooAnimal基类的初始化;创建Bear对象(或Raccoon对象)的时候,不涉及更低层的派生类型。在这种情况下,Bear(或Raccoon)构造函数像平常一样直接初始化它们的ZooAnimal基类:

 Bear::Bear(std::string name,bool onExhibit):ZooAnimal(name,onExhibit,"Bear") { }
Raccoon::Raccoon(std::string name,bool onExhibit):ZooAnimal(name,onExhibit,"Raccoon") { }

虽然ZooAnimal不是Panda的直接基类,但是Panda构造函数也初始化ZooAnimal基类:

Panda::Panda(std::string name,bool onExhibit):ZooAnimal(name,onExhibit,"Panda"),Bear(name,onExhibit),Raccoon(name,onExhibit),Endangered(Endangered::critical),sleeping_flag(false) { }

当创建Panda对象的时候:
(1)首先使用构造函数初始化列表中指定的初始化式构造ZooAnimal部分。
(2)接下来,构造Bear部分。忽略Bear的用于ZooAnimal构造函数初始化列表的初始化式。
(3)然后,构造Raccoon部分。再次忽略ZooAnimal初始化式。
(4)最后,构造Panda部分。
如果Panda构造函数不显式初始化ZooAnimal基类,就使用ZooAnimal默认构造函数;如果ZooAnimal没有默认构造函数,则代码出错。

9.无论虚基类出现在继承层次中任何地方,总是在构造非基类之前构造虚基类:

class Character{ /*....*/ };
class BookCharacter: public Character{ /*....*/ };
class ToyAnimal{ /*...*/ };
class TeddyBear: public BookChatacter,public Bear,public virtual ToyAnimal{ /*...*/ };

按声明次序检查直接基类,确定是否在虚基类。例中,首先检查BookChatacter的继承子树,然后检查Bear的继承子树,最后检查ToyAnimal的继承子树。按从根类开始向下倒最低层派生类的次序检查每个子树。
    TeddyBear的虚基类的构造次序是先ZooAnimal再ToyAnimal。一旦构造了虚基类,就按声明次序调用非虚基类的构造函数:首先是BookChatacter,它导致调用Character的构造函数,然后是Bear。因此,为了创建TeddyBear对象,按下面次序调用构造函数:

 ZooAnimal();
ToyAnimal();
Character();
BookChatacter();
Bear();
TeddyBear();

在这里,由最低层派生类TeddyBear指定用于ZooAnimal和ToyAnimal的初始化式。
     在合成复制构造函数中使用同样的构造次序,在合成赋值操作符中也是按这个次序给基类赋值。保证调用基类的析构函数的次序与构造函数的调用次序相反。

C++ Primer 有感(多重继承与虚继承)的更多相关文章

  1. C++ Primer 笔记——多重继承与虚继承

    1.在多重继承中,基类的构造顺序与派生类列表中基类的出现顺序保持一致,与初始值列表中的顺序无关. 2.在C++11新标准中,允许派生类从它的一个或几个基类中继承构造函数.但是如果从多个基类中继承了相同 ...

  2. C++ Primer 学习笔记_95_用于大型程序的工具 --多重继承与虚继承

    用于大型程序的工具 --多重继承与虚继承 引言: 大多数应用程序使用单个基类的公用继承,可是,在某些情况下,单继承是不够用的,由于可能无法为问题域建模,或者会对模型带来不必要的复杂性. 在这些情况下, ...

  3. C++中的多重继承与虚继承的问题

    1.C++支持多重继承,但是一般情况下,建议使用单一继承. 类D继承自B类和C类,而B类和C类都继承自类A,因此出现下图所示情况: A          A \          / B     C ...

  4. 多重继承,虚继承,MI继承中虚继承中构造函数的调用情况

    先来测试一些普通的多重继承.其实这个是显而易见的. 测试代码: //测试多重继承中派生类的构造函数的调用顺序何时调用 //Fedora20 gcc version=4.8.2 #include < ...

  5. 【c++】多重继承与虚继承

    派生类的构造函数初始化列表将实参分别传递给每个直接基类,其中基类的构造顺序与派生列表中基类的出现顺序保持一致,而与派生类构造函数初始化列表中基类的顺序无关. 类型转换与多个基类 编译器不会在派生类向基 ...

  6. C++学习之多重继承与虚继承

    一.多重继承 我们知道,在单继承中,派生类的对象中包含了基类部分 和 派生类自定义部分.同样的,在多重继承(multiple inheritance)关系中,派生类的对象包含了每个基类的子对象和自定义 ...

  7. C++继承,多重继承,虚继承的构造函数以及析构函数的调用顺序问题

    #include <iostream> using namespace std; class A{ int data_a; public: A(){ data_a = ; cout < ...

  8. Linux Debugging(四): 使用GDB来理解C++ 对象的内存布局(多重继承,虚继承)

    前一段时间再次拜读<Inside the C++ Object Model> 深入探索C++对象模型,有了进一步的理解,因此我也写了四篇博文算是读书笔记: Program Transfor ...

  9. C++虚继承作用

    C++虚继承可以防止多重继承产生的二义性问题. 虚继承,就是在被继承的类前面加上virtual关键字,这时被继承的类称为虚基类,如下面代码中的base类.虚继承在多重继承的时可以防止二义性. clas ...

随机推荐

  1. 【ASP.NET Core】给中间件传参数的方法

    最近博客更新频率慢了些,原因有三: 其一,最近老周每星期六都录 ASP.NET Core 的直播,有些内容在视频里讲过,就不太想在博客里面重复.有兴趣的话可以去老周的微博看,或者去一直播,直播帐号与微 ...

  2. 谷歌刚发布的求梯度的工具包-Tangent

    安装很简单sudo pip install tangent. 我机器上,终端上用python,tangent报错,但在终端上用ipython,tangent不报错. 我检验是否可用tangent的方法 ...

  3. 服务器&阵列卡&组raid 5

    清除raid信息后,机器将会读不到系统, 后面若进一步操作处理, raid信息有可能会被初始化掉,那么硬盘数据就有可能会被清空, 导致数据丢失, 否则如果只是清除raid信息,重做raid是可以还原系 ...

  4. Unity中使用射线查询MeshCollider背面的方法

    之前遇到一个问题要从MeshCollider背面方向发出射线,直至检测到该射线与MeshCollider的相交点为止. 后来我用双面MeshCollider的方法解决了http://www.cnblo ...

  5. Node.js 字符串解码器

    稳定性: 3 - 稳定 通过 require('string_decoder') ,可以使用这个模块.字符串解码器(StringDecoder)将缓存(buffer)解码为字符串.这是 buffer. ...

  6. PHP 字符串变量

    PHP 字符串变量 字符串变量用于存储并处理文本. PHP 中的字符串变量 字符串变量用于包含有字符的值. 在创建字符串之后,我们就可以对它进行操作了.您可以直接在函数中使用字符串,或者把它存储在变量 ...

  7. 安卓高级3 RecyclerView 和cardView使用案例

    cardView: 添加依赖:在Studio搜索cardview即可 在V7包中 或者直接在gradle中添加 compile 'com.android.support:cardview-v7:24. ...

  8. Programming In Scala笔记-第四章、类和对象

    类似于Java,Scala中也有类和对象的概念. 一.类.属性和方法 1.类 类是对一类事物的抽象,当一个类被定义后,就可以以该定义为模板,定义该类的一系列对象.比如说有以下一个模板 人类: 有姓名: ...

  9. app控件唯一相对Xpath自动生成(增强版uiautomatorviewer)

    作者:cryanimal QQ:164166060 工具由来 前面的一篇博文较详细地介绍了uiautomatorviewer:扫描和分析Android应用程序的UI控件的工具. 熟悉控件获取的同学都知 ...

  10. PHP学习(1)——我为什么要学PHP

    PHP简介 PHP是一种服务器端的脚本语言,特别适合做web开发.高效.灵活.实用是PHP的特点.PHP最开始是Personal Home Page的缩写,后来正式更名为了"PHP:Hype ...