快速业务通道

《深度探索C++对象模型》读书笔记(5)

作者 佚名技术 来源 程序设计 浏览 发布时间 2012-06-30

***纯虚拟函数***

在设计抽象基类时,需要注意以下几点:

(1)不要将destructor 声明为pure virtual function;

如果将destructor声明为pure virtual function,则设计者一 定得定义它。因为每一个derived class destructor会被编译器加以扩展,以静态调用得方式调用其 “每一个virtual base class”以及“上一层base class”的 destructor.

(2)不要将那些函数定义内容并不与类型有关的函数设计为virtual function,因 为其几乎不会被后继的derived class改写。

(3)对于其derived class可能修改某一个data member的函数,不应被声明为const.

***“无继承”情况下的对象构造***

先 定义class Point:

class Point {
public:
Point(float x = 0.0, float y = 0.0) : _x(x),_y(y) {}
virtual float z();
protected:
float _x,_y;
};

你可不能小看z()这个virtual function给class Point带来的巨大变化。virtual function的引入促使每一个class Point拥有一个vtpr,这样一来,编译器在constructor中添加了对 vptr进行初始化的代码,而copy constructor和copy assignment operator也会对vptr进行设定,而不 再是原先简单的bitwise操作了。

请看以下的代码:

Point foobar()
{
Point local;
Point *heap = new Point;
*heap = local;
delete heap;
return local;
}

将被内部转化为:

Point foobar(Point &_result)
{
Point local;
local.Point::Point();
Point *heap = _new (sizeof(Point));
if(heap != 0)
heap->Point::Point();
*heap = local;
_result.Point::Point(local);  // copy constructor的应用
local.Point::~Point();
return;
}

从以上代码的转化可以看出:一般而言,如果你的设计之中有很多函 数都需要以传值方式(by value)传回一个local class object,那么提供一个copy constructor就比 较合理。

***继承体系下的对象构造***

假设class Point3d虚拟继承于class Point,但 由于class Point仅存在一份实体,因而class Point3d的constructor需要注意一个问题。

请看下面的继承关系图:

class Point3d : virtual public Point { ... };
class Vertex : virtual public Point { ... };
class Vertex3d : public Point3d, public Vertex { ... };

通常来说,class Point3d和class Vertex的constructor均需调用Point的 constructor,然而,当Point3d和Vertex同为Vertex3d的subobject时,它们对Point constructor的调 用操作一定不可以发生,而是交由Vertex3d来完成。

那么如何做到这一点呢?其实只需在 constructor中添加一个参数就可以了。例如,class Vertex3d在调用Point3d和Vertex的constructor之 前,总是会把参数_most_derived设为false,于是就压制了两个constructors中对Point constructor的 调用操作。

// 在virtual base class情况下的constructor扩充内容
Vertex3d* Vertex3d::Vertex3d(Vertex3d *this, bool _most_derived, float x, float y, float z)
{
if(_most_derived != false)
this->Point::Point(x,y);

// 在调用上一层 base classes的constructor之前设定_most_derived为false
this->Point3d::Point3d (false,x,y,z);
this->Vertex::Vertex(false,x,y,z);

// 设定vptr
// 安 插user code

return this;
}

为了控制一个class中有所作用的函数, 编译器只要简单地控制住vptr的初始化和设定操作即可。

vptr初始化操作应该如何处理?实际情 况是:应该在base class constructors(具体来说,是所有的virtual base classes和上一层的base classes)调用操作之后,但是在程序员供应的码或是“member initialization list中所列的 members初

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号