Chapter 5. Semantics of Construction, Destruction, and Copy
5.1 “无继承” 情况下的对象构造
1. 普通类型(和C相同)
2. 抽相数据类型
3. 为继承作准备
5.2 继承体系下对象的构造
1. 通用继承构造规则
(1) 在成员初始化列表中的data members初始化操作会被放进constructor的函数本身,并以members的声明顺序为顺序。
(2) 如果有一个member没有出现在初始化列表中,但它有一个default constructor,那么default constructor会被调用。
(3) 如果class object 有virtual table pointer(s), 它(们)必须被设定初始值,指向适当的virtual table(s)。
(4) 在那之前,所有的上一层的base class constructors必须被调用, 以base class的声明顺序为顺序
(5) 在那之前,所有的virtual base class constructors必须被调用,从左到右,从最深到最浅。
2. 虚拟继承(virtual Inheritance)
如对于下面的类:
1 class Point3d : public virtual Point
2 {
3 public:
4 Point3d( float x = 0.0, float y = 0.0, float z = 0.0 )
5 : Point( x, y ), _z( z ) {}
6 Point3d( const Point3d& rhs )
7 : Point( rhs ), _z( rhs._z ) {}
8 ~Point3d();
9 Point3d& operator=( const Point3d& );
10
11 virtual float z(){ return _z; }
12 //
13 protected:
14 float _z;
15 };
可能的转换是这样的:
1 // Psuedo C++ Code:
2 // Constructor Augmentation with Virtual Base class
3 Point3d* Point3d::Point3d( Point3d *this, bool __most_derived, float x, float y, float z )
4 {
5 if ( __most_derived != false )
6 this->Point::Point( x, y);
7
8 this->__vptr__Point3d = __vtbl__Point3d;
9 this->__vptr__Point3d__Point = __vtbl__Point3d__Point;
10
11 this->_z = rhs._z;
12 return this;
13 }
//
对于如下的继承层次:
class Vertex : virtual public Point { ... };
class Vertex3d : public Point3d, public Vertex { ... };
class PVertex : public Vertex3d { ... };
类Point3d的构造可能是:
1 // Psuedo C++ Code:
2 // Constructor Augmentation with Virtual Base class
3 Point3d* Point3d::Point3d( Point3d *this, bool __most_derived, float x, float y, float z )
4 {
5 if ( __most_derived != false )
6 this->Point::Point( x, y);
7
8 this->__vptr__Point3d = __vtbl__Point3d;
9 this->__vptr__Point3d__Point = __vtbl__Point3d__Point;
10
11 this->_z = rhs._z;
12 return this;
13 }
//
对于Vertex3d的构造可能是如下:
1 // Psuedo C++ Code:
2 // Constructor Augmentation with Virtual Base class
3 Vertex3d* Vertex3d::Vertex3d( Vertex3d *this, bool __most_derived, float x, float y, float z )
4 {
5 if ( __most_derived != false )
6 this->Point::Point( x, y);
7
8 // invoke immediate base classes,
9 // setting __most_derived to false
10
11 this->Point3d::Point3d( false, x, y, z );
12 this->Vertex::Vertex( false, x, y );
13
14 // set vptrs
15 // insert user code
16
17 return this;
18 }
3. vptr初始化语意学(The Semantics of the vptr Initialization)
(1) 构造函数执行算法
I. 在derived class constructor 中, 所有的"virtual base classes" 及 "上一层base class"的constructors会被调用.
II. 上述完成之后, 对象的vptr(s)会被初始化, 指向相关的virtual talbe(s).
III. 如果有成员初始化列表的话, 将在constructor体内扩展开来. 这必须在vptr被设定之后才能进行,以免有一个virtual member function被调用
IV. 最后, 执行程序所提供的代码.
(2) 示例:
For example, given the following user-defined PVertex constructor:
1 PVertex::PVertex( float x, float y, float z )
2 : _next( 0 ), Vertex3d( x, y, z )
3 , Point( x, y )
4 {
5 if ( spyOn )
6 cerr << "within Point3d::Point3d()" << " size: " << size() << endl;
7 }
可能一个扩展如下:
1 // Pseudo C++ Code
2 // expansion of PVertex constructor
3 PVertex* PVertex::PVertex( Pvertex* this, bool __most_derived, float x, float y, float z )
4 {
5 // conditionally invoke the virtual base constructor
6 if ( __most_derived != false )
7 this->Point::Point( x, y );
8 // unconditional invocation of immediate base
9 this->Vertex3d::Vertex3d( x, y, z );
10
11 // initialize associated vptrs
12
13 this->__vptr__PVertex = __vtbl__PVertex;
14 this->__vptr__Point__PVertex = __vtbl__Point__PVertex;
15
16 // explicit user code
17 if ( spyOn )
18 cerr << "within Point3d::Point3d()"
19 << " size: " << (*this->__vptr__PVertex[ 3 ].faddr)(this)
20 << endl;
21
22 // return constructed object
23 return this;
24 }
5.3 对象的复制(Object Copy Sematics)
1. Copy constructor operator 在以下几种情况下不会表现出: bitwisecopy
(1) class 内带有一个member object, 而其类有一个copy constructor operator时。
(2) 当一个 class 的base 有一个copy assignment operator时。
(3) 当类声明了任何一个virtual functions时。
(4) 当class继承自一个virtual base class时
2. 合成示例
1 // Pseudo C++ Code: synthesized copy assignment operator
2 inline Point3d& Point3d::operator=( Point3d *const this, const Point3d &p )
3 {
4 // invoke the base class instance
5 this->Point::operator=( p );
6
7 // memberwise copy the derived class members
8 _z = p._z;
9 return *this;
10 }
5.4 对象的功能
5.5 析构语意学(Semantics of Destruction)
1. 析构函数生成原则:
如果类没有定义destructor, 那么只有在class内带的member object(或是class自己的base class)拥有destructor的情况下,编译器才会自动的合成一个来。否则,destructor会被视为不需要,也就不需要被合成(当然更不需要被调用)
2. 析构调用过程
(1) destructor的函数本身首先被执行。
(2) 如果class拥有member class objects, 而后者拥有destructors, 那么它会以其声明顺序的相反顺序被调用.
(3) 如果object内带一个vptr, 则现在被重新设定,指向适当的base class的virtual table.
(4) 如果任何直接的(上一层)novirtual base classes 拥有destructor,那么它会以其声明顺序相反的顺序调用
(5) 如果有任何的virtual base classes 拥有destructor, 而当前讨论的这个class是最末端的class, 那么它们会以其原来的构造顺序相反的顺序被调用.