您的位置:首页 > 编程语言 > C语言/C++

《深度探索C++对象模型》——C++与C程序风格对比

2015-01-13 23:20 169 查看
在C语言中,“数据”和“处理数据的操作(函数)”是分开来声明的。由一组“分布在各个以功能为导向的函数中”的算法所驱动,处理共同的外部数据。

先看一个例子:

如果我们声明一个struct Point3d,

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


欲打印一个Point3d,可能就得定义一个像这样的函数:

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


或者,定义这样的宏:

#define Point3d_print( pd ) \
printf("(%g, %g, %g)\n", pd.x, pd.y, pd.z);


或者,直接在程序调用处完成其操作:

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


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

Poind3d  pt;
pt.x = 0.0;


或者,

#define X( p, xval ) (p.x) = (xval);
…
X( pt, 0.0);


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

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

inline ostream&
operator<<(ostream &os, const Point3d &pt)
{
os << "(" << pt.x << "," << pt.y << "," << pt.z << ")";
};


或者,

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 : 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 : 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;
};


或者,坐标类型参数化:

template < class type >
class Point3d
{
public:
Point3d( type x = 0.0, type y = 0.0, type z = 0.0 ):
_x(x), _y(y), _z(z){}
~Point3d(){}
type x(){ return _x;}
type y(){ return _y;}
type z(){ return _z;}
void x( type xval ){ _x = xval;}
//...etc..
private:
type _x;
type _y;
type _z;
};


或者,坐标类型和坐标数目均参数化:

template< class type, int dim>
class Point
{
~Point(){};
Point( type coords[dim] ){
for( int index = 0; index < dim; index++ )
__coords[index] = coords[index];
}
type& operator[]( int index ){
assert(index < dim && index >= 0);
return __coords[index];
}
//...etc...
private:
type __coords[dim];
};

inline
template< class type, int dim>
ostream&
operator<<( ostream &os, const Point< type, dim> &pt )
{
os << "(";
for ( int ix = 0; ix < dim - 1; ix++)
{
os << pt[ix] << ", ";
}
os << pt[dim - 1];
os << ")";
};


根据上面的例子,很明显的看出,C 程序和 C++ 程序风格上有截然不同,在程序的思考上也有明显的差异。大家看到 Point3d 转到 C++ 之后,是不是反而更加复杂?布局成本是不是增加更多了?答案是 class Point3d 并没有增加成本。三个 data member 直接内含在每一个 class object 之中,就像 C struct 的情况一样。而 member function 虽然含在 class 的声明之内,却不出现在 object 之中。每一个 non-line member function 只会诞生一个函数实体,而不是 inline function 在每一个模块使用者身上产生一个函数实体。事实上,C++ 在布局以及存取时间上主要的额外负担是由 virtual 引起的,包括:

virtual function 机制 用以支持一个有效率的“执行期绑定”(running binding)

virtual base class 用以实现“多次出现在继承体系中的base class ,有一个单一而被共享的实体”。

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

至此,你也许会问,你咋知道 C++ 的布局成本没有增加成本?C++ 布局又是咋样的?这里面说的 virtual又是怎么给 C++ 在布局以及存取时间上引起额外的负担?敬请关注下一篇博客《C++对象模型》。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: