C++ 对象模型

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

也即过程式编程语言的特质是:数据和函数各自分开声明,不支持数据和函数之间的关联性。

举个例子,我们声明一个 struct Point3d,像这样:

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

欲打印一个 Point3d,可能需要定义这样一个函数:

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

或者,如果要更有效率一点,就定义一个宏:

#define Point3d_print(pd)\
    printf("(%g, %g, %g)", (pd)->x, (pd)->y, (pd)->z);
                // (pd)->x
                // 是避免传递进来的是 &p;
                // -> 的优先级要高于 &

在 C++ 中,Point3d 可能采用独立的“抽象数据类型(Abstract Data Type, ADT)”来实现:

class Point3d
{
public:
    Point3d(float x = 0.0, float y = 0.0, float z = 0.0) :
        _x(x), _y(y), _z(z) {   }
    float x() const{ return _x; }
    float y() const{ return _y; }
    float z() const{ return _z; }
    void x(float x) { _x = x; }
    ...
private:
    float _x;
    float _y;
    float _z;
};

加上封装后的布局成本(Layout Costs for Adding Encapsulation)

将数据成员及对数据成员的存取函数置于一个类体之内,即为封装。

程序员看到 Point3d 转换到 C++ 之后,第一个可能的问题就是:加上封装之后,布局成本增加了多少?答案是,class Point3d 并没有增加成本。三个 data members 直接包含在每一个 class object 中,和 C struct 一样。而 member functions 虽然在 class 的声明之内,却不出现在 object 之中。每一个 non-inline member function 都会诞生一个函数实例

Point3d 支持封装性质,这一点并未给它带来任何空间或执行期的不良后果,你即将看到,C++ 在布局以及存取时间上主要的额外负担是由 virtual 引起的。

  • (1)virtual function 机制,用以支持一个有效的“执行期绑定(runtime binding)”
  • (2)virtual base class。

C++ 对象模型

C++ 中,

  • class data members:

    • static
    • non-static,
  • class member functions:

    • static
    • non-static
    • virtual

考虑如下的函数声明:

class Point
{
public:
    Point(float x);
    virtual ~Point();
    float x() const;
    static int PointCount();
protected:
    virtual std::ostream& print(std::ostream& os) const;
    float _x;
    static int _point_count;
};

这个 class Point 在机器中将会如何表现呢?也即,我们如何模塑(modeling)出各种 data members 和 function members 呢?

C++ 对象模型:

  • Non-static data members:每一个对象之内
  • static data members, static and nonstatic function members 都被放在个别的对象之外。

virtual functions 则以两个步骤支持:

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

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

此 C++ 对象模型的:

  • (1)优点:空间和存取时间的效率
  • (2)缺点:如果应用程序代码本身未曾改变,但所用到的 class objects 的 nonstatic data members 有所修改(增加、移除或更改),那么那些应用程序代码同样重新编译
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五道口纳什

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值