我们来看下面一段代码:

  class B1
{
public:
B1(int i) {cout<<"constructing B1 "<<i<<endl;}
};
class B2
{
public:
B2(int j) {cout<<"constructing B2 "<<j<<endl;}
};
class B3
{
public:
B3( ){cout<<"constructing B3 *"<<endl;}
};
class C: public B2, public B1, public B3
{
public:
C(int a, int b, int c, int d):B1(a),memberB2(d),memberB1(c),B2(b){}
private:
B1 memberB1;
B2 memberB2;
B3 memberB3;
};
void main( )
{ C obj(,,,); }

运行后的结果如下:
  constructing B2 2
  constructing B1 1
  constructing B3 *
  constructing B1 3
  constructing B2 4

constructing B3 *
  为什么会有以上的结果?
  众所周知构造函数的执行次序如下:
  调用基类构造函数,调用顺序按照他们的继承时声明的顺序。
  调用内嵌成员对象的构造函数,调用顺序按照他们在类中声明的顺序。
  派生类的构造函数体中的内容。
  析构函数的调用顺序相反。
  那么再来看以上的例子就很容易理解了。B2、B1、B3是C的基类,按照上述的顺序,我们先要构造基类,然后才是子对象,最后是其本身的构造函数所以先要执行这三个类的构造函数。在构造时按照他们在类中的顺序,首先调用B2的构造函数
  B2(int j) {cout<<"constructing B2 "<<j<<endl;}
  由于在默认参数列表
  C(int a, int b, int c, int d):B1(a),memberB2(d),memberB1(c),B2(b){}
  中,将b的值传给了B2的构造函数,b为2,故打印出:
  constructing B2 2
  接下来要构造的是B1了。显然在C的默认参数构造列表中将a的值传给了B1,
  所以打印出:
  constructing B1 1
  B3在构造时没有传递参数,调用B3( ){cout<<"constructing B3 *"<<endl;}
  打印出:
  cout<<"constructing B3 *
  这时基类的构造函数已经执行完毕,接着该处理内嵌成员对象的构造函数了。

我们看到C类有三个对象:B1 memberB1;B2 memberB2;B3 memberB3;,按照构造函数的调用顺序,我们需要按照他们在类中声明的顺序来分别构造memberB1、memberB2、 memberB3。在默认的参数列表中,用c来构造了memberB1,用d来构造memberB2,
  故打印出:
  constructing B1 3
  constructing B2 4
  constructing B3 *
  最后调用本身的构造函数,由于函数体为空,故什么也没有打印出来。
  总结下来,我们必须明确的是当一个类继承与基类,并且自身还包含有其他类的成员对象的时候,构造函数的调用顺序为:调用基类的构造函数->调用成员对象的构造函数->调用自身的构造函数。构造函数的调用次序完全不受构造函数初始化列表的表达式中的次序影响,与基类的声明次数和成员对象在函数中的声明次序有关。
再如:

#include<iostream.h>
class A
{
protected:
char c;
public:
A(char ch)
{
c=ch;
cout<<"c="<<c<<endl;
cout<<"类A构造函数被调用"<<endl;
}
~A()
{
cout<<"类A析构函数被调用"<<endl;
}
};
class B
{
protected:
int i; public:
B(int j)
{
i=j;
cout<<"i="<<i<<endl;
cout<<"类B构造函数被调用"<<endl;
}
~B()
{
cout<<"类B析构函数被调用"<<endl;
}
};
class C:public A,B
{
private:
int k;
public:
C(char ch,int ii,int kk):A(ch),B(ii),k(kk)
{
cout<<"k="<<k<<endl;
cout<<"类C构造函数被调用"<<endl; }
~C()
{
cout<<"类C析构函数被调用"<<endl;
}
};
void main()
{
C A('B',,);
}

输出结果:
c=B
类A构造函数被调用
i=10
类B构造函数被调用
k=15
类C构造函数被调用
类C析构函数被调用
类B析构函数被调用
类A析构函数被调用

C++派生类构造函数调用顺序(详解)的更多相关文章

  1. 3.7 C++派生类构造函数调用规则

    参考:http://www.weixueyuan.net/view/6364.html 总结: 派生类构造函数可以自动调用基类的默认构造函数而无需显式调用. 生类构造函数可以自动调用基类的默认构造函数 ...

  2. Java基础-DButils工具类(QueryRunner)详解

    Java基础-DButils工具类(QueryRunner)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 如果只使用JDBC进行开发,我们会发现冗余代码过多,为了简化JDBC ...

  3. java初始化构造函数调用顺序

    类初始化时构造函数调用顺序: (1)初始化对象的存储空间为零或null值:  (2)调用父类构造函数:  (3)按顺序分别调用类成员变量和实例成员变量的初始化表达式:  (4)调用本身构造函数. 例子 ...

  4. Delphi中TStringList类常用属性方法详解

    TStrings是一个抽象类,在实际开发中,是除了基本类型外,应用得最多的. 常规的用法大家都知道,现在来讨论它的一些高级的用法. 先把要讨论的几个属性列出来: 1.CommaText 2.Delim ...

  5. vxWorks/BootROM Imageq启动顺序详解

    vxWorks/BootROM Imageq启动顺序详解 VxWorks image     分为在ROM中运行和在RAM中运行两种,两者启动顺序的区别在于sysInit()函数的调用,该函数在RAM ...

  6. Python的Django框架中forms表单类的使用方法详解

    用户表单是Web端的一项基本功能,大而全的Django框架中自然带有现成的基础form对象,本文就Python的Django框架中forms表单类的使用方法详解. Form表单的功能 自动生成HTML ...

  7. Kotlin——中级篇(一):类(class)详解

    在任何一门面向对象编程的语言里,类(class)是非常基础.但也是非常重要的一项组成,通俗的说就是万般皆对象,而所说的对象就是我们生成的类.Kotlin也是如此,下面详细为大家介绍Kotlin中的类的 ...

  8. Java AtomicInteger类的使用方法详解_java - JAVA

    文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 首先看两段代码,一段是Integer的,一段是AtomicInteger的,为以下: public class Samp ...

  9. Tomcat5的web应用启动顺序详解

    Tomcat5的web应用启动顺序详解 [收藏此页] [打印]   作者:佚名  2007-07-17 内容导航: 第1页   [IT168技术文档]摘要: 应用Tomcat对于我们来讲实在是司空见惯 ...

随机推荐

  1. spark练习——影评案例

    第一次写博客,新人上路,欢迎大家多多指教!!! ---------------------------------------------------------------------分割线---- ...

  2. 20155306 白皎 《网络攻防》 Exp2 后门原理与实践

    20155306 白皎 <网络攻防> Exp2 后门原理与实践 一.实践基础 后门程序又称特洛伊木马,其用途在于潜伏在电脑中,从事搜集信息或便于黑客进入的动作.后程序和电脑病毒最大的差别, ...

  3. Codeforces VK Cup 2018 Div.2

    总题面传送门 这次考试只过了3题,前三题题目难度并不大,但是第三题的代码细节卡了我两个半小时(基本上整场考试),所以以后要合理把握时间,注意把握代码细节,并更加完善我的代码风格,使其更加简练.(赛外话 ...

  4. 解读Web应用程序安全性问题的本质

    转自 http://blog.csdn.net/iwebsecurity/article/details/1688304 相信大家都或多或少的听过关于各种Web应用安全漏洞,诸如:跨site脚本攻击( ...

  5. 09 ORM 多表操作,创建表,添加记录

    1.数据库表关系 1.一对多 为什么需要,重复字段太多 一对多关系表 Book id title price publish_id 1 python 100 1 2 php 200 2 3 go 10 ...

  6. 团队合作开发git冲突解决方案 Intellij IDEA

    https://blog.csdn.net/antony9118/article/details/52524873 注:因为我使用的是 idea 2018.1.2的版本,所以在操作上有些变化 将某些操 ...

  7. springmvc pager-taglib 分页,bootstrap样式

    注意: 嵌入到项目中时必须以带参形式访问: http://localhost:8081/DETECT-X/showConnLogsByPager.action?pageSize=5&pager ...

  8. Ansible详解(一)基础安装和配置

    ansible 是一款轻量级自动化运维工具,由的 Python 语言开发,结合了多种自动化运维工具的特性,实现了批量系统配置,批量程序部署,批量命令执行等功能; ansible 是基于模块化实现批量操 ...

  9. html5新特性data_*自定义属性使用

    HTML5规范里增加了一个自定义data属性. 这个自定义data属性的用法非常的简单, 就是你可以往HTML标签上添加任意以 "data-"开头的属性, 这些属性页面上是不显示的 ...

  10. 13-调试Dockerfile

    包括 Dockerfile 在内的任何脚本和程序都会出错.有错并不可怕,但必须有办法排查,所以本节讨论如何 debug Dockerfile. 先回顾一下通过 Dockerfile 构建镜像的过程: ...