C++对象模型——关于对象(第一章)

58 篇文章 0 订阅

第一章    关于对象

在C语言中,"数据"和"处理数据的操作(函数)"是分开声明的,也就是说,语言本身并没有支持"数据和函数"之间的关联性.我们把这种程序方法成为程序性,由一组"分布在各个以功能为导向的函数中"的算法所驱动,它们处理的是共同的外部数据.举个例子,如果声明一个struct Point3d,像这样:
typedef struct point3d
{
    float x;
    float y;
    float z;
} Point3d;
欲打印一个Point3d,可能就得定义一个像这样的函数:
void Point3d_print (const Point3d *pd) {
    printf("(%g, %g, %g)", pd->x, pd->y, pd->z);
}
或者,如果要想更有效率一些,就定义一个宏:
#define Point3d_print(pd) \
    printf("(%g, %g, %g)", pd->x, pd->y, pd->z);
也可直接在程序中完成其操作
在C++中,Point3d有可能用独立的"抽象数据类型(abstract data type)来实现:
class Point3d
{
public:
    Point3d(float xval = 0.0, float yval = 0.0, float zval = 0.0)
        : x(xval), y(yval), z(zval) {}
    float getX() { return x; }
    float getY() { return y; }
    float getZ() { return z; }
    void setX(float xval) { x = xval; }
private:
    float x;
    float y;
    float z;
};
inline ostream & operator << (ostream &os, const Point3d &pt) {
    os << "(" << pt.getX() << ", " << pt.getY() << ", " << pt.getZ() << ")";
}
更进一步来说,不管哪一种形式,它们都可以被参数化,可以是坐标类型的参数化.
template <class type>
Point3d(type xval = 0.0, type yval = 0.0, zval = 0.0);
也可以是坐标类型和坐标数目两者都参数化:
template <class type, int dim>
Point(type coords[dim]);
很明显,不只是程序风格上有截然的不同,在程序的思考上也有明显的差异, 从软件工程的眼光来看"一个ADT或者class hierarchy的数据封装"比"在C程序中程序性使用全局数据"好.,但是这被那些"被要求快速让一个应用程序上马应战,并且执行起来又快又有效率"的程序员所忽略,毕竟C的吸引力就在于它的精瘦和简易.
加上封装后的布局成本(Layout Costs for Adding Encapsulation)
程序员看到Point3d转换成C++之后,第一个可能会问的问题就是: 加上了封装之后,布局成本增加了多少?答案是class Point3d 并没有增加成本,三个data member直接内含在每一个class object之中,就像C struct的情况一样,而member functions虽然含在class的声明内,却不出现在object中,每一个non-inline member function只会诞生一个函数实体,至于每一个"拥有零个或者一个定义"的inline function则会在其每一个使用者(模块)身上产生一个函数实体.Point3d支持封装性质,这一点并未带给它任何空间或执行期的不良效应. C++在布局以及存取时间上主要的额外负担是由virtual引起,包括:
virtual function机制    用于支持一个有效率的"执行器绑定"(runtime binding)
virtual base class        用以实现"多次出现在继承体系中的base class,有一个单一而被共享的实体"
此外,还有一些多重继承下的额外负担,发生在"一个derived class和其第二或者后继之base class的转换"之间.然而,一般言之,并理由说C++程序一定比C庞大或者迟缓.

1.1    C++对象模式(The C++ Object Model)

    在C++中,有两种class data members:static 和 nonstatic,以及三种class member functions:static,nonstatic和virtual,已知下面这个class Point声明:
class Point {
public:
    Point(float xval);
    virtual ~Point();

    float getX() const;
    static int PointCount();
protected:
    virtual ostream& print(ostream &os) const;
    float x;
    static int point_count;
};
这个class Point在机器中会被怎样表现呢?也就是说,如何模拟(modeling)出各种data members和function members呢?

1.1.1    简单对象模型 (A Simple Object Model)

    第一个模型非常简单,它可能是为了尽量降低C++编译器的设计复杂度而开发出来的,缺点则是空间和执行期的效率低下.在这个简单模型中, 一个object是一系列的slot(槽),每一个slot指向一个member.Members按照声明次序,各自被指定一个slot.每一个data member或function member都有自己的一个slot.
在这个简单模型中,members本身并不被放在object之中,只有"指向member的指针"才被放在object内,这么做可以避免"members有不同的类型,因而需要不同的存储空间"所导致的问题.Object中的members是以slot的索引值来寻址,本例中x的索引值是6,point_count的索引值为7.一个class object的大小很容易计算出来:"指针大小,乘以class中声明的members数目".
    虽然这个模型并没有被应用于实际产品上,不过关于索引或slot数目的观念,倒是被应用到C++的"指向成员的指针"(point-to-member)观念之中.

1.1.2    表格驱动对象类型 (A Table-driven Object Model)

    为了对所有classes的所有objects都有一致的表达方式,另一种对象模型是 把所有与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的一个有效方案.

1.1.3    C++对象模型 (The C++ Object Model)

    Stroustrup当初设计(当前仍占有优势)的C++对象模型是从简单对象模型派生而来的,并对内存空间和存取时间做了优化.在此模型中, Nonstatic 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也经由virtual table被指出来,通常是放在表格的第一个slot处.
    C++对象模型的 主要优点在于它空间和存取时间的效率主要缺点是,如果应用程序代码本身并未改变,但所用的class object的nonstatic data members有所修改(可能是增加、移除或修改),那么那些应用程序代码同样得重新编译。关于这点,前面的的表格驱动模型就提供了较大的弹性,因为它多提供了一层间接性,不过它也因此付出空间和执行效率两方面的代价。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值