C++对象模型
1、概念
》语言中直接支持面向对象程序设计的部分
》》一种“不变量”,类似于C++ class的完整virtual functions在编译时期就固定了,程序员后期无法在执行期间增加和取代其中的某一个
》》虚拟调用可以快速派送(dispatch),付出的代价是执行期的弹性
》对于各种支持的底层实现机制
2、C与C++的对比
1、C语言程序性的procedural
》数据和处理数据的操作分开来声明
》》由一组“分布在各个以功能为导向的函数中”的算法所驱动,处理的是共同的外部数据
2、C++封装
》C++封装并没有增加成本
》C++在布局以及存取时间增加的额外负担由virtual引起
》》virtual function机制
》》》用以支持一个有效率的执行期绑定(runtime binding)
》》virtual base class
》》》用以实践多次出现在进程体系中的base class,有一个单一而被共享的实体
》此外还要一些多重继承下的额外负担。
C语言
//申明一个struct Point3d
typedef struct Point3d
{
float x;
float y;
float z;
}
//打印一个Point3d,定义的函数
void Point3d_print(const Point3d *pd)
{
printf("%f, %f, %f",pd->x, pd->y, pd->z);
}
//定义一个宏更有效率
#define Point3d_print(pd) printf("%f, %f, %f",pd->x, pd->y, pd->z);
//程序中直接完成操作
void my_foo()
{
Point3d *pd = get_a_point();
...
//直接打印point
printf("%f, %f, %f",pd->x, pd->y, pd->z);
}
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(){return _x;}
float y(){return _x;}
float z(){return _x;}
void x(float xval){_x = xval;}
private:
float _x;
float _y;
float _z;
};
inline ostream&operator<<(ostream &os, const Point3d &pt)
{
os << "{" << pt.x() << ","<< pt.y() << ","<< pt.z() << "}"
};
一个双层或者三层的class体系完成
class Point
{
public:
point(float x = 0.0) : _x(x){}
float x() {return _x;}
void x(float xval){_x = xval;}
protected:
float _x;
};
class Point2d : public Point
{
public:
Point2d(float x = 0.0, float y = 0.0):Point(x), _y(y){}
float y(){return _y;}
void y(float yval){_y = yval;}
protected:
float _y;
};
class Point3d : public Point2d
{
public:
Point3d(float x = 0.0, float y = 0.0, float z= 0.0) : Point2d(x,y), _z(z){}
float z(){return _z;}
void z(float zval){_z = zval;}
protected:
float _z;
};
C++对象模式
1、简单对象模型
》一个object是一系列的slots,每一个slot指向一个members,Members按其声明次序,各被指定一个slots,每一个data member或function member都有自己一个slot
》应用在C++的”指向成员的指针“观念中
2、表格驱动对象模型
》为了对所有class的所有objects都有一致的表达方式
》所有与members相关的信息抽出来,放在一个data member table和一个member function table之中,class object本身则内涵指向这两个表格的指针,member function table是一系列的slots,每一个slot指向一个member function,data member table则直接含有data本身
3、C++对象模型
》由简单对象模型派生,对内存空间和存取时间走了优化
》Nonstatic data member 被配置于每一个class objects之内,static和Nonstatic function member也被放在所有的classobjects之外,Virture functions则以两个步骤支持
》》每一个class产生出一堆指向virtual functions的指针,放在表格之中,这个表格被称为virtual table(vtbl)
》》每一个class object被添加了一个指针,指向相关的virtual table,通常这个指针被称为vptr,vptr的设定(setting)和重置(resetting)都由每一个class的construcator、destructor和copy assignment运算符自动完成,每一个class所关联的type_info objects(支持runtime type identification,RTTI),也经由virtual table被指出来,通过是放在表格的第一个slot处。
》》缺点:当应用程序代码本身未曾改变,class objects的nonstatic data members有改变(增加,修改,更改),应用程序也要重新编译。
继承
1、单一继承
2、多重继承
》虚拟继承:base class不管在继承串链中派生多少次,永远只会存在一个实体(subobject)
》间接性的级数会因为继承的深度而增加
//单一继承
class library_materials{...};
class Book:public library_materials{};
class Rental_book :public book{...};
//多重继承
//早期的iostream实现方式
class iostream:
public istream,
public ostream{...};
//继承关系可以指定为虚拟的(virtual)
class istream : virtual public ios {...}
对象模型如何影响程序
不同的对象模型,会导致现有的程序代码必须修改以及必须加入新的程序代码
X foobar()
{
X xx;
X *px = new X;
//foo()是一个virtual function
xx.foo();
px->foo();
delete px;
return xx;
}
//上面这个函数在内部可能会被转化成
//虚拟C++码
void foobar(X &_result)
{
//构造_result
//_result来取代local xx..
_result.x::X();
px = _new(sizeof(X));
if(px != 0)
px->x::X();
//扩展下xx.foo()各不使用virtual机制
//以_result取代xx
foo($_result);
//使用virtual机制扩展px->foo();
(*px->vtb1[2])(px);
//扩展delete px;
if(px != 0)
{
{*pt->vtb1[1]}(px);
_delete(px);
}
return;
}