C++三大继承构造函数的执行顺序详解
写的挺好的,关于继承和构造函数的先后顺序问题。
转自: http://blog.csdn.net/daheiantian/archive/2011/02/18/6438782.aspx
一、单继承
核心:在构造子类之前一定要执行父类的一个构造函数。
1.构造函数(不包括复制构造函数)。
顺序:①直接父类;②自己
注意:若直接父类还有父类,那么“直接父类的父类”会在“直接父类” 之前 构造。 可以理解为这是一个递归的过程,知道出现一个没有父类的类才停止。
2.1 如果没有显式定义构造函数,则“合成的默认构造函数”会自动调用直接父类的“默认构造函数”,然后调用编译器为自己自动生成的“合成的默认构造函数”。
2.2 如果显式定义了自己的构造函数
2.2.1 如果没有显式调用直接父类的任意一个构造函数,那么和“合成的默认构造函数”一样,会先自动调用直接父类的 默认构造函数,然后调用自己的构造函数。
2.2.2 如果显式调用了直接父类的任意一个构造函数,那么会先调用直接父类相应的构造函数,然后调用自己的构造函数。
2. 复制构造函数
顺序:①直接父类;②自己
注意:和构造函数一样,若直接父类还有父类,那么“直接父类的父类”会在“直接父类” 之前 构造。 可以理解为这是一个递归的过程,知道出现一个没有父类的类才停止。
2.1 如果 没有显式定义复制构造函数,则“合成的复制构造函数”会自动调用直接父类的“复制构造函数”,然后调用编译器为自己自动生成的“合成的复制构造函数”(注意:不是默认构造函数)
2.2 如果显式定义了自己的复制构造函数 (和构造函数类似)
2.2.1 如果没有显式调用父类的任意一个构造函数,那么会先调用直接父类的 默认构造函数(注意:不是 复制构造函数)。
2.2.2 如果显式调用了直接父类的任意一个构造函数,那么会先调用直接父类相应的构造函数。
3.赋值操作符重载
3.1 如果没有显式定义,会自动调用直接父类的赋值操作符。(注意:不是 默认构造函数)
3.2 如果显式定义了,就只执行自己定义的版本,不再自动调用直接父类的赋值操作符,只执行自己的赋值操作符。
注意:如有需要对父类子部分进行赋值,应该在自己编写的代码中,显式调用父类的赋值操作符。
4. 析构函数
与构造函数 顺序相反。
二、多继承
和单继承的差别就是:需要考虑到多个直接父类。其它的都相同
1.构造函数(不包括复制构造函数)。
顺序:①所有直接父类;(按照基类继承列表中声明的顺序)②自己
注意:若直接父类还有父类,那么“直接父类的父类”会在“直接父类” 之前 构造。 可以理解为这是一个递归的过程,知道出现一个没有父类的类才停止。
2.1 如果 没有 显式定义构造函数,则“合成的默认构造函数”会自动依次调用所有直接父类的“默认构造函数”,然后调用编译器为自己自动生成的“合成的默认构造函数”。
2.2 如果显式定义了自己的构造函数
2.2.1 如果没有显式调用父类的任意一个构造函数,那么和“合成的默认构造函数”一样,会自动依次调用所有直接父类的 默认构造函数,然后调用自己的构造函数。
2.2.2 如果显式调用了父类的任意一个构造函数,那么按照基类列表的顺序,对于每一个父类依次判断:若显式调用了构造函数,那么会调用该父类相应的构造函数;如果没有显式调用,就调用默认构造函数。最后调用自己的构造函数。
2. 复制构造函数
顺序:①所有直接父类;(按照基类继承列表中声明的顺序)②自己
注意:和构造函数一样,若直接父类还有父类,那么“直接父类的父类”会在“直接父类” 之前 构造。 可以理解为这是一个递归的过程,知道出现一个没有父类的类才停止。
2.1 如果 没有显式定义复制构造函数,则“合成的复制构造函数”会自动依次调用所有直接父类的“复制构造函数”,然后调用编译器为自己自动生成的“合成的复制构造函数”(注意:不是默认构造函数)
2.2 如果显式定义了自己的复制构造函数 (和构造函数类似)
2.2.1 如果没有显式调用父类的任意一个构造函数,那么会先自动依次调用直接父类的 默认构造函数(注意:不是 复制构造函数)。
2.2.2 如果显式调用了直接父类的任意一个构造函数,那么按照基类列表的顺序,对于每一个父类依次判断:若显式调用了构造函数,那么会调用该父类相应的构造函数;如果没有显式调用,就调用默认构造函数。最后调用自己的复制构造函数。
3.赋值操作符重载
3.1 如果没有显式定义,会自动依次调用直接父类的赋值操作符。(注意:不是 默认构造函数)
3.2 如果显式定义了,就只执行自己定义的版本,不再自动调用直接父类的赋值操作符,只执行自己的赋值操作符。
注意:如有需要对父类子部分进行赋值,应该在自己编写的代码中,显式调用所有直接父类的赋值操作符。
4. 析构函数
与 构造函数 顺序相反。
三、虚继承
和多继承的差别就是:要考虑到虚基类,其它的都相同。(虚基类的初始化要早于非虚基类,并且只能由子类对其进行初始化)
1.构造函数(不包括复制构造函数)。
顺序:①所有虚基类(按照基类继承列表中声明的顺序进行查找);②所有直接父类;(按照基类继承列表中声明的顺序)③自己
注意:若虚基类或者直接父类还有父类,那么“直接父类的父类”会在“直接父类” 之前 构造,“虚基类的父类”也会在“虚基类”之前构造。 可以理解为这是一个递归的过程,知道出现一个没有父类的类才停止。
2.1 如果 没有 显式定义构造函数,则“合成的默认构造函数”会先依次调用所有虚基类的默认构造函数,然后再自动依次调用所有直接父类的“默认构造函数”,最后调用编译器为自己自动生成的“合成的默认构造函数”。
2.2 如果显式定义了自己的构造函数 2.2.1 如果没有显式调用父类的任意一个构造函数,那么和“合成的默认构造函数”一样,会先依次调用所有虚基类的默认构造函数,然后再自动依次调用所有直接父类的 默认构造函数,最后调用自己的构造函数。
2.2.2 如果显式调用了父类的任意一个构造函数,那么按照基类列表的顺序,先初始化所有虚基类,再初始化所有直接父类。对于每一个父类依次判断:若显式调用了构造函数,那么会调用该父类相应的构造函数;如果没有显式调用,就调用默认构造函数。最后调用自己的构造函数。
2. 复制构造函数
顺序:①所有虚基类(按照基类继承列表中声明的顺序进行查找);②所有直接父类;(按照基类继承列表中声明的顺序)③自己
注意:和构造函数一样,若虚基类或者直接父类还有父类,那么“直接父类的父类”会在“直接父类” 之前 构造,“虚基类的父类”也会在“虚基类”之前构造。 可以理解为这是一个递归的过程,知道出现一个没有父类的类才停止。
2.1 如果 没有显式定义复制构造函数,则“合成的复制构造函数”会自动依次调用所有直接父类的“复制构造函数”,然后调用编译器为自己自动生成的“合成的复制构造函数”(注意:不是默认构造函数)
2.2 如果显式定义了自己的复制构造函数 (和构造函数类似)
2.2.1 如果没有显式调用父类的任意一个构造函数,那么会先依次调用所有虚基类的默认构造函数,然后再依次调用所有直接父类的 默认构造函数(注意:不是 复制构造函数)。
2.2.2 如果显式调用了直接父类的任意一个构造函数,那么按照基类列表的顺序,先初始化所有虚基类,再初始化所有直接父类。对于每一个父类依次判断:若显式调用了构造函数,那么会调用该父类相应的构造函数;如果没有显式调用,就调用默认构造函数。
3.赋值操作符重载
3.1 如果没有显式定义,会自动依次调用所有虚基类和所有直接父类的赋值操作符。(注意:不是 默认构造函数)
3.2 如果显式定义了,就只执行自己定义的版本,不再自动调用直接父类的赋值操作符,只执行自己的赋值操作符。
注意:如有需要对父类子部分进行赋值,应该在自己编写的代码中,显式调用所有虚基类和所有直接父类的赋值操作符。
4. 析构函数
与 构造函数 顺序相反。
四、总结:
1. 整体顺序:虚基类 --> 直接父类 -->自己
2. 在任何显式定义的构造函数中,如果没有显式调用父类的构造函数,那么就会调用父类的默认构造函数。
3. 合成的复制构造函数、合成的赋值操作符,(当没有显式定义时,编译器自动提供),会自动调用的是虚基类和直接父类的复制构造函数和赋值操作符,而不是默认构造函数;
4. 自己显式定义的复制构造函数,除非在初始化列表中显示调用,否则只会调用虚基类和父类的默认构造函数。
5. 自己显式定义的赋值操作符,除非显式调用,否则只执行自己的代码。
6. 析构函数的执行顺序与 构造函数 相反。
C++三大继承构造函数的执行顺序详解相关推荐
- unity 继承会调用start吗_Unity 继承MonoBehaviour脚本 执行顺序 详解
先看结果 Awake ->OnEnable-> Start ->-> FixedUpdate-> Update -> LateUpdate ->OnGUI ...
- 【异步系列二】Promise原理及执行顺序详解
前言 Promise 是 javascript 中非常重要的一环,熟悉它是必须的,而且在面试中也常常会问到相关面试题. 在了解 Promise 之前,需要了解什么是异步编程,可以参考我的一篇文章:Ja ...
- JS 中关于Promise的用法,状态,执行顺序详解,面试可用(原创)
前言 在实际项目中我们常会去用已经封装好的promise如axios,或者也会自己去封装promise,甚至在面试中,关于promise的面试题也层出不穷,promise的重要性不言而喻,故写该文章记 ...
- java try、catch、finally及finally执行顺序详解
1.为什么要用finally 先看一个没有finally的异常处理try-catch语句: 假设count为要使用到的资源,并且用完要求释放此资源.那么我们可以把释放资源的语句放到try-catch后 ...
- Python装饰器执行顺序详解
探究多个装饰器执行顺序 装饰器是Python用于封装函数或代码的工具,网上可以搜到很多文章可以学习,我在这里要讨论的是多个装饰器执行顺序的一个迷思. 疑问 大部分涉及多个装饰器装饰的函数调用顺序时都会 ...
- javascript运行机制之执行顺序详解
JavaScript是一种描述型脚本语言,它不同于java或C#等编译性语言,它不需要进行编译成中间语言,而是由浏览器进行动态地解析与执行.那么JavaScript是怎么来进行解析的吗?它的执行顺序又 ...
- python两个装饰器执行顺序_python中多个装饰器的执行顺序详解
装饰器是程序开发中经常会用到的一个功能,也是python语言开发的基础知识,如果能够在程序中合理的使用装饰器,不仅可以提高开发效率,而且可以让写的代码看上去显的高大上^_^ 使用场景 可以用到装饰器的 ...
- python装饰器的顺序_python中多个装饰器的执行顺序详解
装饰器是程序开发中经常会用到的一个功能,也是python语言开发的基础知识,如果能够在程序中合理的使用装饰器,不仅可以提高开发效率,而且可以让写的代码看上去显的高大上^_^ 使用场景 可以用到装饰器的 ...
- Java 中 finally 与 return 的执行顺序详解
java方法是在栈幀中执行,栈幀是线程私有栈的单位,执行方法的线程会为每一个方法分配一小块栈空间来作为该方法执行时的内存空间,栈幀分为三个区域: 1 . 操作数栈,用来保存正在执行的表达式中的操作数, ...
最新文章
- 计算机应用基础 网上教学设计方案,《计算机应用基础》(本)教学设计方案.doc...
- Linux系统介绍(二)文件系统结构
- C# 系统应用之注册表使用详解
- python爬取股票大单历史记录_利用bs4爬取股票的历史交易数据
- python3模块: requests
- UESTC学位论文latex模板下载
- bootstrap搜索框:click下拉展开改hover展开(两种代码)
- 与素数有关的一些性质及证明(一)
- python强制声明变量类型_python声明变量类型吗
- 只知道人工智能远远不够 下一件大事将是边缘计算!
- CCD/CMOS的成像原理
- S3存储服务间数据同步工具Rclone介绍
- 《SEM长尾搜索营销策略解密》一一2.8 长尾虽好,但核心不可或缺
- 学生综合素质评价系统c语言,学生综合素质评价表自我评价范文(2)
- Unity打包篇:Unity 导出 Gradle 工程出现release builds have to be signed when using Gradle解决办法
- 2022浙江大学计算机考研超强攻略
- html表格的多个下拉菜单,表格设置下拉多个选项
- 停止线程 暂停线程
- android 手势放缩_手把手教你打造支持手势放大缩小的ImageView
- 电商项目:拼团活动设计及表结构设计