深度探索c++对象模型

系列文章目录

第一章关于对象(Object Lessons)

第二章构造函数语意学

第三章data语意学

第四章function语意学

第五章构造、析构、拷贝语义学

第六章执行期语意学

第七章站在对象模型的尖端



第一章关于对象

在C语言中,数据和处理数据的操作(函数)是分开声明的,也就是说,语言本身并没有支持“数据和函数”之间的关联性。我们把这种方法称为程序性的,由一组“分布在各个以功能为导向的函数中”的算法所驱动,他们处理的是共同的外部数据。举个例子,如果我们声明一个struct point3d像这样:

typedef struct point3d
{
    float x;
    float y;
    float z;
}Point3d;

想要打印一个Pint3d,肯定就得定义一个这样的函数:

void Point3d_print(const Point3d* pd)
{
    printf("%g,%g,%g", pd->x, pd->y, pd->z);
}

或者要效率更好一些,就定义一个宏:

#define Point3d_printf(pd)\
     printf("%g,%g,%g", pd->x, pd->y, pd->z);

亦或是直接在程序中完成操作

void my_foo()
{
    Point3d* pd = get_a_point();
    ...
    /*直接打印出point*/
    printf("%g,%g,%g", pd->x, pd->y, pd->z);
}

同样的道理,某个点的特定坐标值可以直接存取

Point3d pt;

pt.x=0.0;

也可以经由一个前置处理宏来完成:

#define         X(p,xval)        (p.x)=(xval)

...

X(pt,0.0)

在c++中,Point3d有可能采用独立的“抽象数据类型”来实习:

class Point3d
{
public:
    Point3d(float x=0.0,float y=0.0,float z=0.0):_x(x),_y(y),_z(z){}

    float x() { return _x; }
    float y() { return _y; }
    float z() { return _z; }

    void x(float xval) { _x = xval; }
    //...etc...
private:
    float _x;
    float _y;
    float _z;
};

或者是一个双层或者三层的class结构,更进一步来说,不管是哪一种形式,他们都可以被参数化。可以是坐标参数化也可以是坐标类型和坐标个数两者都参数化。

在c++中实现3D坐标点,比在c复杂,尤其是在使用template的情况下。但这并不意味这c++更好用。

加上封装后的布局成本

Point3d加上封装后,布局成本没有增加。c++在布局以及存取时间上主要的额外负担是由virtual(虚拟)引起的,包括

  • virtual function机制 用以支持一个有效率的“执行期绑定”
  • virtual base class 用以实现“多次出现在集成体关系中的base class”,有一个单一而被共享的实例。

此外还有一些多重继承下的额外负担,发生在“一个derived class和其第二或后继之base class的转换”之间。

1.1c++对象模式(the c++ Obiect Model)

在c++中,有两种类数据成员(class data members):static和nonstatic,以及三种类成员函数(class member functions):static、nonstatic和virtual。如下

class Point {
public:
    Point(float xval);                //构造
    virtual ~Point();                //析构

    float x()const;                   //非静态
    static int PoitCount();        //静态

protected:
    virtual ostream&;                //虚拟
    printf(ostream& os)const;   

    float _x;                                //非静态
    static int _point_count;        //静态
};

 简单对象模型

这个模型是为了尽量减低c++编译器的设计复杂度而开发出来的,赔上的则是空间和执行期的效率。在这个简单模型中,一个object(对象)是一系列的slots(元素),每一个slot指向一个members,Mermbers按其声明顺序,各被指定一个slot。每一个data member或function member都有自己的一个slot。

 编辑过后的版本

 在这个简单模型下,members本身并不放在obiect之中。只有“指向member的指针”才放在obiect内。这么做可以避免“members有不同的类型,因而需要不同的存储”所招致的问题。Obiect中的members是以slot的索引来寻址的,本例之中_x的索引是6,_point_count的索引是7,一个class object的大小很容易计算出来:“指针大小,乘以class中所声明的members个数”便是。

虽然这个模型并没有被应用于实际产品上,不过关于索引或slot个数的观念,倒是被应用到到c++的“指向成员的指针”观念之中。

表格驱动对象模型

这种对象模型是把所有与members相关的信息抽出来,放在一个data member table和一个member function table之中,class object本身则内含指向这两个表格的指针。Member function table是一系列的slots,每一个slot指出一个member function:Data member table则是直接持有data本身。

 虽然这个模型也没有实际应用于真正的c++编译器上,但member function table这个观念却成为支持virtual functions的一个有效方案;

c++对象模型

当初设计的c++对象模型是从简单对象模型吧派生而来的,并对内存空间和存取时间做了优化。在此模型中,Nonstactic data members被配置于每一个class object之内,static data members则被存放在个别的class object之外。Static 和nonstatic function members 也被放在个别的class object之外。Virtual functions则以两个步骤支持之:

1.每一个class产生出一堆指向virtual functions的指针,放在表格之中。这个表格被称为virtual table(vtbl)。

2.每一个class object被安插一个指针,指向相关的virtual table。通常这个指针被称为vptr。vptr的设定和重置都由每一个class的constructor、destructor和copy assignment运算符自动完成。每一个class所关联的type_info object(用来支持runtime type identification,RTTI)也经由virtual table被指出来,通常放在表格的第一个slot。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值