继承关系中构造函数、析构函数的调用顺序详解

构造函数:

在c++中,当声明一个派生类的对象时,派生类中包含所有父类的数据成员以及自己添加的数据成员均已被分配了内存,只是尚未进行初始化配置(但实际上基本数据类型的变量已经被赋予随机默认值)。

构造函数的执行顺序:

继承关系中构造函数、析构函数的调用顺序详解_第1张图片当使用某一个类进行实例化对象时,往往需要传递参数, 该类在该类的所有父类构造完成后,首先调用内嵌对象的无参的默认构造函数,之后通过该类的构造函数体处理一些更具体地操作,比如给基本类型数据赋初值,至此该对象就通过传入的参数将所有数据都进行初始化。

而在整个构造过程中,存在两个不同方向的信息流和控制流:

  1. 当前类将参数传递给其父类构造函数,为了初始化父类中相对其祖先新增的数据成员或对内嵌对象进行赋值操作。此参数信息由于数量不同,可以向上传递到祖先的构造函数体,或者停留在中间某类的构造函数中。
  2. 参数信息流向祖先传递,最远可达最顶层父类的构造函数体。无论参数传递到哪个位置,构造的顺序不会变:从最顶层类调用内嵌对象的默认构造函数开始,接着调用最顶层类的构造函数体(根据参数有无、多少可以动态多态),至此结束最顶层的构造->控制流返回下一层,同样调用该层类内嵌对象的默认无参构造函数,然后进入该类的构造函数体初始化本类新增的数据成员...一直反复,直到控制流返回到最底层构造对象的类中,当该类的构造函数体执行完后,即认为该对象初始化完毕。(某些类中的成员变量没有在构造函数中初始化也不要紧,在该全过程中,无论是类的构造函数体,还是内嵌对象的无参默认构造函数,只要存在一处显式声明了的构造函数,即使函数体为空,什么也不做,此时编译器仍然认为对象已经被初始化;反之,所有过程中,构造函数都是凭借编译器生成的默认合成的构造函数,此时编译器认为该对象尚未被初始化,即使内部数据实际上还是有随机值的,仍会编译报错)

总结:

构造函数:

当构造一个对象时,从最顶层的父类到最底层的类,先调用自身内嵌对象的默认构造函数,再调用自身构造函数体,依次构造,从父类到最底层的类,先组件,后整体,逐步将欲构建的对象从最基本的父类数据成员一步步拓展到最终类的成员并初始化。值得注意的是,c++中内置类型(int、double、char等)或者复合型(指针,数组)在编译器自动生成的合成的默认构造函数中是不会进行初始化的;

无论是在类的内嵌对象中还是父类中,只要其显式地说明了构造函数,即使函数体为空,也能够成功访问到成员变量属性;反之,如果都没有明显的声明构造函数,则无法访问类的成员变量,提示使用了该类的未初始化的对象;

即:上图中类的构造函数体和内嵌对象的构造函数体都没有显式声明,而是由编译器默认创建,则将提示未初始化对象;

析构函数:

在构造函数中,先执行成员的初始化,且按照它们在类中出现的顺序进行初始化,然后执行函数体中的内容。在析构函数中,首先执行的是函数体,然后销毁成员。成员按初始化顺序的逆序进行销毁。所以你要认识到,析构函数体自身并不直接销毁成员,成员是在析构函数体之后隐含的析构阶段中被销毁的。在整个对象销毁过程中,析构函数体是作为成员销毁步骤之外的另一部分进行的。

参考资料:
C++中的析构函数和delete的关系

【C++要笑着学】类的默认成员函数详解 | 构造函数 | 析构函数 | 构造拷贝函数

你可能感兴趣的:(笔记,c++,c++)