原文地址:https://www.cnblogs.com/lawlietfans/p/5861769.html

规范的派生类构造函数有3个要点:

1.首先创建基类对象。

2.应通过成员初始化列表,创建基类对象。

3.应初始化本派生类新增成员变量。

第一种:不显示调用基类构造函数

C继承B1和B2

#include "iostream"
using namespace std
class B1
{public:B1(){cout<<"B1"<<endl;}
};
class B2
{public:B2(){cout<<"B2"<<endl;}
}
class C:public B1,publc B2
{public:C(){cout<<"C"<<endl;}
}
int main()
{C obj;return 0;
}
/*output:
B1
B2
C
*/

其中,冒号指出C的基类是B1和B2,public限定符指出B1和B2都是公有基类,我们称之为公有派生。

公有派生中,基类的公有成员(成员变量、成员方法)变成了派生类的公有成员。基类的私有成员变成了派生类的私有成员,但是不能直接访问,只能借助基类的public和protected方法访问。

这时,程序将使用基类默认构造函数。
也就是说C的写法相当于在成员初始化列表调用基类的默认构造函数:

C():B1(),B2(){cout<<"C"<<endl;}
  • B1和B2的构造顺序只和继承的顺序有关,和成员初始化列表中的顺序无关.
  • 调整继承顺序  class C:public B2,public B1。输出顺序为B2,B1。而修改成员初始化列表中的顺序没有效果。

第二种:显示调用基类构造函数

同样的,B1和B2的构造顺序只和继承的顺序有关,和成员初始化列表中的顺序无关

class B1
{B1(){cout<<"B1"<<endl;}B1(int i){cout<<"B1:"<<i<<endl;}
};
class B2
{B2(){cout<<"B2"<<endl;}B2(int i){cout<<"B2:"<<i<<endl;}
}
class C:public B2,public B1
{C():B1(10),B2(20){cout<<"C"<<endl;};
}
int main()
{C obj;return 0;
}
/*output:B2:20B1:10C
*/

更进一步可以把C中构造函数参数作为实参传递给基类构造函数:

C(int x, int y):B2(x),B1(y){cout<<"C"<<endl;}

第三种:封闭类

有成员对象的类称为封闭类,这是对象组合的一种实现方式。

class C:public B2,public B1
{private:int x;B1 memberb1;B2 memberb2;public:C():B1(10),B2(20){cout<<"C"<<endl;}
}
/*output:B2:20B1:10B1B2C
*/

构造子类实例过程中,依次进行如下构造:

  • 构造基类(即B2 B1)
  • 构造当前派生类的成员对象(即memberb1 memberb2)
  • 构造当前派生类(执行自己的构造函数)(即C)

第三种:对当前对象属性使用初始化成员列表

当前对象属性就是  成员对象

class C:public B2, public B1
{private:int x;B1 memberb1;B2 memberb2;public:C(int x,int y):B1(10),B2(20),memberb1(1),memberb2(2){cout<<"C"<<lenl;}
}
/*output:B2:20B1:10B1:1B2:2C
*/

和基类很相似。

  • 在成员初始化列表,如果不显式调用成员对象的构造函数,程序就会调用默认构造函数。显式调用,程序就会调用你指定的构造函数。
  • 成员对象之间的构造顺序之和声明顺序有关,和在Member Initialization List中的顺序无关。
  • 当然,也可以不指定初始化列表,在构造函数中再进行成员对象的赋值,这会导致成员对象被构造多次。 更重要的是,因为常量类型、引用类型的成员不接受赋值,它们只能在初始化列表中进行初始化。

第四种:虚基类

#include "iostream.h"
class OBJ1
{public:OBJ1(){cout<<"OBJ"<<endl;}
}
class OBJ2
{public:OBJ2(){cout<<"OBJ2"<<endl;}
}
class BASE1
{public:BASE1(){cout<<"BASE1"<<endl;}
}
class BASE2
{public:BASE2(){cout<<"BASE2"<<endl;}
}
class BASE3
{public:BASE3(){cout<<"BASE3"<<endl;}
}class BASE4
{public:BASE4(){cout<<"BASE4"<<endl;}
}
class DERIVER :public BASE1,vitural public BASE2public BASE3,virtual public BASE4
{public:DERIVER():BASE4(),BASE3(),BASE2(),BASE1(),obj2(),obj1(){cout<<"DERIVER"<<endl;}protect:OBJ1 obj1;OBJ2 obj2;
}
/*outputBASE2BASE4BASE1BASE3OBJ1OBJ2DRIVER
*/
  • DERIVER的虚基类BASE2和BASE4最先构造,所以先输出了BASE2和BASE4,尽管它们在DERIVER类中的顺序不在最前面。
  • 然后在构造DERIVER的非虚基类,虽然它们排在前面,但是要优先构造虚基类,所以放在了虚基类后面。
  • 再构造DERIVER的对象obj1和obj2.它们以类定义时,数据成员排在前面的先构造;
  • 最后构造DERIVER本身。

C++继承中构造顺序相关推荐

  1. C++继承中构造和析构顺序

    C++继承中构造和析构顺序 继承中构造和析构顺序 问题:父类和子类的构造和析构顺序是谁先谁后? 示例 继承中构造和析构顺序 子类继承父类后,当创建子类对象,也会调用父类的构造函数 问题:父类和子类的构 ...

  2. 菱形继承中构造函数调用问题

    菱形继承中构造函数调用问题 在某一个虚基类的任何一个派生类的构造函数中,都要将该虚基类的构造函数显示列出来. 包含虚基类的派生类对象的构造函数的调用顺序如下: 虚基类的构造函数在非虚基类之前调用. 若 ...

  3. 继承中构造和析构顺序

    1.子类继承父类后,当创建子类对象,也会调用父类的构造函数 2.继承中先调用父类构造函数,再调用子类构造函数,析构顺序与构造相反 #include<iostream> using name ...

  4. 虚继承c语言例子,C/C++ 多继承{虚基类,虚继承,构造顺序,析构顺序}

    C/C++:一个基类继承和多个基类继承的区别 1.对多个基类继承会出现类之间嵌套时出现的同名问题,如果同名变量或者函数出现不在同一层次,则底层派生隐藏外层比如继承基类的同名变量和函数,不会出现二义性, ...

  5. c++继承中的构造和析构

    c++继承中的构造和析构 类型兼容性原则 类型兼容规则中所指的替代包括以下情况: 继承中的对象模型 继承中构造和析构 继承中的构造析构调用原则 继承与组合混搭情况下,构造和析构调用原则 继承中的同名成 ...

  6. C++继承机制(二)——继承中的构造和析构顺序、继承同名成员的处理方式

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

  7. 在一个类型的继承体系中,成员的构造顺序

    先看代码,写出结果 class A      {           public A()            {                 PrintFields();            ...

  8. C++继承中的构造与析构

    文章目录 1 C++继承中的构造 1.1 子类对象初始化父类成员的方式 1.2 子类对象的构造 2 C++继承中的析构 2.1 子类对象的析构 1 C++继承中的构造 1.1 子类对象初始化父类成员的 ...

  9. python中的单继承,多继承和mro顺序

    python作为一门动态语言,是和c++一样支持面向对象编程的.相对对象编程有三大特性,分别是继承,封装和多态.今天我们重点讲解的是,python语言中的单继承和多继承. 继承概念: 如果一个类继承了 ...

最新文章

  1. Facebook失误泄露反恐审查员信息 生命或受威胁
  2. 永远的Macromedia, Macromedia Forever
  3. PIL图像处理:旋转图像
  4. 程序员致富的若干方法探讨
  5. java实现计算机图形学中点画线算法
  6. python模块编程教程_python进阶教程之模块(module)介绍
  7. c++派生类的访问控制
  8. 阿波罗登月51周年,程序员用DAIN技术还原阿波罗登月高清影像,效果震撼
  9. 速度一半永远追不上_您将永远不会知道自己应该怎么做的一半-没关系。
  10. ubunt11 安装mysql_ubuntu 11.10安装mysql
  11. VUe3 @cli(axios)跨域访问
  12. 基于uniapp开发DiscuzQ社区的ios和安卓、小程序H5源码
  13. MATLAB 2017b 安装教程,这一篇文章就够了。强烈推荐!!!!!
  14. MCSA 70-740 windows存储相关的基本概念
  15. 使用Java打印三角形
  16. linux手动连接网络打印机驱动_中兴新支点Linux操作系统添加网络打印机的方法...
  17. volatile关键字
  18. USB设备运行不正常,windows无法识别的问题
  19. 【java】黑白图像
  20. SSL协议原理(Secure Socket Layer)【转载】

热门文章

  1. 2-(4-呋喃)[4,5f][1,10]邻菲啰啉|CAS:938063-70-8齐岳生物
  2. 【SystemVerilog基础】$sformatf()/$sformat() 快速上手指南
  3. 【shell脚本】常用工具的学习grep、sed、awk、cut
  4. php学生信息管理:增删改查
  5. LTE射频拉远单元数字中频方案(十)
  6. 推荐!国外程序员整理的 PHP 资源大全
  7. 推荐系统笔记(九):SGL --利用自监督对比学习缓解推荐系统长尾效应
  8. RPMForge安装
  9. IDEA查看Java源码技巧(快捷方式)
  10. TensorFlow Estimator 官方文档之----Feature column