深入探索C++对象模型之五 --- 析构、构造、拷贝语意学
2017-06-06 01:36
531 查看
深入探索C++对象模型之五 — 析构、构造、拷贝语意学
一般而言,class的data member应该被初始化,并且只在constructor中或是在class的其它member functions中指定初值,其它任何操作都将破坏封装性质,使class的维护和修改更加困难。纯虚函数
我们可以定义和调用一个pure virtual function:不过它只能被静态的调用,不能经由虚拟机制调用。而对于pure virtual destructor,class设计者必须定义它。因为每一个derived class destructor都会被编译器加以扩展,以静态调用的方式调用其“每一个virtual base class”以及“上一层base class”的destructor。如果缺少任何一个base class destructor的定义,都会导致链接失败。
因此最好不要把virtual destructor声明为pure。
无继承情况下的对象构造
在C之中,全局性的定义被视为一个“临时性的定义”,因为它没有明确的初始化操作。一个“临时性的定义”可以在程序中发生多次,那些实例会被链接器折叠起来,只留下一个单独实体,被放在data segment中的BSS段中。而C++不支持“临时性定义”,C++中所有全局对象都被当作“初始化过的数据”来对待。如果要对class中的所有成员都设定常量初值,那么给予一个explicit initialization list会比较高效。
Explicit Initialization list 带来三项缺点:
1. 只有当class members都是public时,此法才有效。
2. 只能指定常量,因此它们在编译时期就可以被评估求值。
3. 由于编译器没有自动施行,所以初始化行为的失败可能性会比较高一些。
继承体系下的对象构造
编译器会扩充每一个constructor,一般而言扩充操作如下:在memeber initialization list中的data members初始化操作会被放进constructor的函数里面,以member声明顺序为顺序。
如果有member没有出现在member initialization list当中,而这个member有一个default constructor的话那么该default constructor也必须被调用。
在那之前,如果class object有virtual table pointers,那么必须设定vptr的初值以指向正确的virtual tables
在那之前,所有上一层的base class constructor必须被调用,以base class的声明顺序为顺序。
在那之前,所有的virtual base class constructors必须被调用,从左到右,从最深到最浅。
虚拟继承
虚拟继承中因为“base class subobject”共享性之故,那么在继承体系中间层面的class一定不能调用virtual base class的constructor,取而代之的是,作为最底层的class来负责完成“被共享之virtual base subobject”的构造。那么编译器是如何实现上述行为的呢?我们注意到,“virtual base calss constructor被调用”有着明确的定义,即只有当一个完整的class object被定义出来的时候,它才会被调用;如果object只是某个完整object的subobject的话那么它就不会被调用
vptr的初始化
在一个class的constructor中,经由构造中的对象来调用一个virtual function,其函数实体应该是在此class中有作用的那个。为了能够找到正确的virtual function, 必须在合适的时机来初始化vptr的内容。通常constructor的执行算法如下:
在derived class constructor中,“所有virtual base classes”以及“上一层base class”的constructor会被调用
对象vptr会被初始化,指向相关的virtual tables
如果有member initialization list的话,将在constructor中扩展开来,这必须在vptr被设定之后,以免又一个virtual member function被调用。
最后执行程序员所提供的代码
对象复制语意学
当以一个class object 指定另一个class object的时候,如果class没有表现出bitwise copy的话,那么编译器就自动合成一个copy asssignment operator。class在以下情况不会表现出bitwise语意:
当class内带一个member object,而其class有一个copy assignment operator时。
当一个class的base class有一个copy assignment operator时。
当一个class生命了任何virtual functions(这种情况下我们不能直接拷贝右端的object的vptr,因为后者可能是一个derived class object)
当class继承自一个virtual base class时。
析构语意学
如果class没有定义destructor,那么只有在class内袋的member object或者自己的base class拥有destructor的情况下,编译器才会自动合成一个出来。编译器通过合成一个destructor,来保证调用base class destructor,如果class的设计者定义了一个destructor,那么编译器也会扩展它。扩展方式和constructor被扩展的方式顺序相反:
destructor函数本体先被执行,也就是说vptr会在程序员的代码执行前被重设。
如果class拥有member class objects, 而后者拥有destructors, 那么它们会以其声明顺序的相反顺序被调用。
如果object内带一个vptr,那么首先重设相关的virtual table。
如果有任何直接的nonvirtual base classes拥有destructor,他们会以声明顺序的相反顺序被调用。
如果有任何virtual base classes拥有destructor,而当前讨论的这个class时最尾端(most-derived)的class,那么它们会以原来构造顺序的相反顺序被调用。
相关文章推荐
- 【C++】深度探索C++对象模型之构造、析构、拷贝语意学
- 深度探索C++对象模型复习和学习 第五章:构造、析构、拷贝、语意学
- 深度探索C++对象模型 第五章 构造、析构、拷贝语意学
- [读书笔记] 深入探索C++对象模型-第五章-构造、析构、拷贝语义学(中)
- [读书笔记] 深入探索C++对象模型-第五章-构造、析构、拷贝语义学(上)
- [读书笔记] 深入探索C++对象模型-第五章-构造、析构、拷贝语义学(下)
- 深度探索C++对象模型:5.构造、析构、拷贝语意学
- C++对象模型 第五章 构造、析构、拷贝语意学
- 深入探索C++对象模型--详解深拷贝与浅拷贝以及拷贝构造的建构
- 深入探索C++对象模型 第二章 构造函数语意学
- C++对象模型——构造,解构,拷贝语意学(第五章)
- 《深入探索C++对象模型》第四章:Function语意学
- 【C++对象模型】第五章 构造、解构、拷贝 语意学
- 深入探索C++对象模型->2.1 Default Constructor的构造操作
- 深入探索C++对象模型:第三章 DATA语意学
- 深入探索c++对象模型->2.2 Copy Constructor的构造操作
- 深入探索C++对象模型笔记之三 —— 构造函数语意学 (Default Constructor的建构操作)
- 深入探索C++对象模型之二 --- 构造函数语意学
- 深入探索C++对象模型笔记之六 —— Data语意学
- 《深入探索C++对象模型》第三章:Data语意学