一、纯虚函数的存在
可以定义和调用一个pure virtual function, 不过只能被静态调用(invoked statitcally),不能经由虚拟机制调用
Abstract_base::interface();如上述,Abstract_base是一个虚基类。这只取决于类设计者要不要这么做。
但是对于pure virtual destrcutor, 类设计者一定要定义它,因为每个drived class destructor会被编译器加以扩张,然后以静态方式进行调用"每一个virtual base class”以及“上一层base class”的destructor。
所以一般比较好的处理方式,不要把virtual destructor声明为pure。
二、“无继承”情况下的对象构造
有三种对象产生的方式:global内存控制,local内存配置和heap内存配置。
两种初始化方式
Point local1 = {1.0, 1.0, 1.0};
Point local2;
local2._x = 1.0;
local2._y = 1.0;
local2._z = 1.0;local1对应是explicit initialization list,这比local2声明有效的多。因为当函数的activation record放进程序堆栈时,上述的initialization list中的常量就被放进local内存中了。 并且,explicit initialization list只有当类数据成员声明为public时才有效。
三、为继承做准备
当一个类声明多了virtual function,也就是可以进行操作的动态决议时,会有如下变化:
- 每个class object多负担一个vptr
- 所定义的contructor将发生膨胀,被附加一些代码以便将vptr进行初始化
- 合成一个copy constructor和copy assignment operator,主要是由于vptr的存在,bitwise copy可能会发生问题。
Point foobar()
{
Point local;
// ...
return local;
}会被转化为如下:Point foobar( Point &_result )
{
Point local;
// ...stuff...
_result.Point::Point(local); //调用copy constructor
local.Point::~Point();
return;
}如果设计的类中,函数需要以传值方式(by value)传回一个local class object,最好提供一个copy construtor。四、继承体系下的对象构造
T object;编译器会扩充每一个constructor,扩充程度视class T的继承体系而定。大致扩充如下:- 记录在member initialization list中的data members初始化操作会被放进constructor的函数本体,并以members的声明顺序为顺序。
- 如果member没有出现在initialization list中,但有一个default constructor,那么default constructor必须背调用。
- 如果class object有vptr,则必须设定初值指向适当的virtual table。
- 所有的上层base class constructors必须被调用,以base class的声明顺序为顺序。
- 如果base class被列于member initialization list中,那么任何显示指定的参数都需要被传递过去
- 如果没有列于上述,则调用defualt constructor或default memberwise copy constructor。
- 如果base class是多重继承下的第二或后继的base class,那么this指针需要有所调整
- 所有的virtual base class constructor必须被调用,从左至右,从深到浅。
- 1. 如4(1)
- class的每一个virtual base class subobject的偏移位置必须在执行期可被存取。
- 支持最底层的constructor的某种调用机制需要放进来。
Line b = a;被写出来时,implicit Line copy constructor会被合成出来,成为一个inline public membera = b;被写出来时,implicit copy assignment operator 会被合成出来,成为一个inline public member。五、虚拟继承
Point3d::size();同时,如果size中需要调用其他函数实例,这个时候急需要经由virtual机制决定其动态。- 在derived class constructor中,所有的“virtual base classes”及“上一层base class”的constructors会被调用。
- 上述完成之后,对象的vptr(s)被初始化,指向相关的virtual table(s);
- 如果有member initialization list的话,将在constructor体内扩展出来。这必须在vptr设定之后才这么做,以确保有一个virtual member function被调用。
- 执行程序猿的代码。
六、对象复制语意学
- 当一个class内含一个member object,而其class有一个copy assignment operator
- 当一个class的base class有一个copy assignment operator
- 当一个class声明了任何virtual function(因为不能拷贝右端的vptr)
- 当一个class继承自一个virtual base class。
inline Point3d&
Point3d::operator=( const Point3d &p3d ) : Point( p3d ), z ( p3d._z ) {}
inline Vertex3d &
Vertex3d::operator=( const Vertex3d &v )
{
this->Point3d::operator=(v);
this->Vertex::operator=(v);
this->Point::operator=(v);
}七、析构语意学
- 如果object内含一个vptr,那么首先重设相关的virtual table 3
- destructor的函数本体现在被执行,也就是说vptr会在程序员的代码执行前被重设 1
- 如果class拥有member class objects,而后者拥有destructor,那么它们会以其声明的相反顺序被调用 2
- 如果有任何直接的nonvirtual base classes 拥有 destructor,它们会以其声明的顺序的相反顺序被调用 4
- 如果有任何virtual base classes拥有destructor,而目前这讨论的这个class是最尾端(most derived)的class,那么她们会以其相反的构造顺序的相反顺序被调用。 5
参考:
284




被折叠的 条评论
为什么被折叠?



