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. SpringMVC注解@Component、@Repository、@Service、@Controller区别

    SpringMVC中四个基本注解: @Component.@Repository   @Service.@Controller 看字面含义,很容易却别出其中三个: @Controller   控制层, ...

  2. Oracle中rownum原理介绍

    rownum原理如下:1.执行查询操作2.将第一行的row num置为13.将得到的行的row num与条件相比较,如果不匹配,则抛弃行,如果匹配,则返回行4.oracle获取下一行,然后将rownu ...

  3. 用tensorflow迁移学习猫狗分类

    笔者这几天在跟着莫烦学习TensorFlow,正好到迁移学习(至于什么是迁移学习,看这篇),莫烦老师做的是预测猫和老虎尺寸大小的学习.作为一个有为的学生,笔者当然不能再预测猫啊狗啊的大小啦,正好之前正 ...

  4. MySQL 数学函数

    MySQL 数学函数 所有的数学函数在发生错误的情况下,均返回 NULL. -元减.改变参数的符号 mysql> SELECT - 2; -> -2 注意,如果这个操作符被用于一个 BIG ...

  5. 实验与作业(Python)-02 Python函数入门与温度转换程序

    截止日期 实验目标 学会定义函数,使用函数.学会导入在某个文件中定义的函数. input获得值,然后通过eval或者int.float将其转换为相应的类型. 学会使用列表:访问列表.append.遍历 ...

  6. SQL Server 虚拟化(1)——虚拟化简介

    本文属于SQL Server虚拟化系列 前言: 现代系统中,虚拟化越来越普遍,如果缺乏对虚拟化工作原理的理解,那么DBA在解决性能问题比如降低资源争用.提高备份还原速度等操作时就会出现盲点.所以基于本 ...

  7. Markdown语法及SublimeText下使用技巧

    Markdown语法及SublimeText下使用技巧 0.缘起 最近因为一直在学习Sublime Text,所以也就顺便试用了一下ST对Markdown的支持.正好CSDN正在大力宣传新上线的Mar ...

  8. android 自定义ViewGroup之浪漫求婚

    *本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 1.最终效果 有木有发现还是很小清新的感觉 2.看整体效果这是一个scrollView,滑动时每个子view都有一个或多个动画效果 ...

  9. Playground中格式注释语法

    类似于Ruby的ruby document,Xcode的Playground自身也提供一些嵌入文档中的格式注释的语法. 我们先定义一个简单的类: class A{ } 按住opt点击class A,你 ...

  10. PHP+MySQL 分页那点事

    分页技术随处可见,这可以算得上是最为基础的网站功能了.于是今天尝试着用PHP来实现一个分页的小例子. 准备工作 环境准备 Apache MySQL PHP 工作环境 数据库准备 建库 建表 预存数据 ...