一、C++对象模式(The C++ Object Model)
- 在C++中,类有两种数据成员:静态数据成员和非静态数据成员,以及三种函数成员:静态成员函数、非静态成员函数和虚函数。
- 简单对象模型(A Simple Object Model):在这个简单模型中,一个object是一系列的slots,每一个slot指向一个成员,成员按照其声明顺序,各被指定一个slot。每一个数据成员和函数成员都有一个自己的slot。比如下面这个Point类
class Point
{
public:
Point(float xval);
virtual ~Point();
float x() const;
static int PointCount();
protected:
virtual ostream& print(ostream &os) const;
float x;
static int _point_count;
};
如果将其转化成简单对象模型,则模型如下: 而简单对象模型为了解决成员有不同的类型,因此需要不同的存储空间的问题,对象存储的实际是指向这些成员的指针(指针占用的内存空间大小固定,在64位计算机上是8字节),这种对象模型相对简单,编译器设计时不会很困难,但是会牺牲性能,这是C++所接受不了的。 3. 表格驱动对象模型(A Table-driven Object Model):顾名思义,这个对象模型维护两个表,一个表用于维护类中数据成员,表中维护数据本身,而另一个表用于维护类中的成员函数,表中维护指向这些函数的指针。 这个模型也没有用于C++编译器,但是成员函数表这个观念成为支持虚函数的一个有效方案。 4. C++对象模型(The C++ Object Model):Stroustrup当初设计的C++对象模型是从简单对象模型派生而来,并对内存空间和存取时间做了优化:
- 在此模型中,非静态数据成员被直接放在了每个对象之中,静态数据成员被存放在所有的对象之外;
- 静态和非静态成员函数被放在了所有的类对象之外;
- 虚函数所采取的策略称为虚函数表,每一个对象产生出一堆指向虚函数的指针,放在一个表格中维护,这个表被称为虚函数表(virtual table),每个对象被添加了一个指针,指向相关的虚函数表,通常这个指针被称为vptr,vptr的设定和重置都有每一个类的构造、虚构和拷贝赋值运算符自动完成,每个类所关联的type_info对象也存储在虚函数表中,一般是表头。
二、C++对象模型在继承上的使用
- C++支持单继承、多重继承和虚继承,在虚拟继承的情况下,基类不管在继承串链中被派生多少次,永远都存在一个实体(称为subobject),很古老的iostream继承自ostream和istrean,而ostream和istream继承于ios,但是因为iostream是虚继承,所以只有唯一的ios实例。
- 在简单对象模型中,每一个基类可以被派生类内的slot指出,该slot内含基类subobject的地址,这个体制的主要缺点在于,因为间接性而导致空间和存取时间上的额外负担,优点是派生类大小不会随着基类大小变化而变化。(因为派生类维护的其实是一个基类指针,指针占用大小不变)。
- 可以想象另外一种base table模型,这里说的base class table被产生出来时,表格每一个slot内含一个相关的base class地址,每个类对象内含一个bptr,它会被初始化,指向其base class table。这个策略主要缺点是由间接性导致的空间和存取时间上的额外负担,优点则是在每一个类对象中对于继承都有一致的表现形式,第二个优点是,修改base class table不需要改变class object本身。
- C++最初使用的继承模型并不运用任何间接性:父类的数据成员被直接放置在派生类对象中。当C++开始导入virtual base class,需要一些间接的基类表现方法。virtual base class的原始模型是在类对象中为每一个有关联的virtual base class加上一个指针。
|