深度探索C++对象模型:4.Function语意学(一)

2014-11-24 07:41:42 · 作者: · 浏览: 0

第四章: Function语意学
Nonstatic Member Functions(非静态成员函数)

Point3d obj;

Point3d *ptr = &obj;

Point3d Point3d::normalize() const{

register float mag =magnitude();

Point3d normal;

normal._x = _x/mag;

normal._y = _y/mag;

normal._z = _z/mag;

return normal;

}

Point3d::magnitude() const {

return sqrt(_x*_x+_y*_y+_z*_z);

}
C++的设计准则之一就是:nonstaticmember function至少必须和一般的nonmember function有相同的效率。这是因为编译器内部已将“member函数实例”转换为对等的“nonmember函数实例”。

举个例子,下面是magnitude()的一个nonmember定义:

float magnitude3d(constPoint3d *_this)const {

return sqrt(_this->_x *_this->_x +

_this->_y*_this->_y +

_this->_z*_this->_z );

}

而我们的member function版本将按如下步骤转换:

1. 改写函数的signature以安插一个额外参数(this指针)到member function中,结果如下:

Point3d Point3d::magnitude(const Point3d * constthis)

之所以有两个const,是因为第一个const表示magnitude函数具有const性质,第二个const表示this是const指针。

2. 将每一个对nonstatic data member的存取操作改为由this指针存取,结果如下

{

return sqrt(this->_x*this->_x +

this->_y *this->_y+

this->_z *this->_z);

}

3. 将member function重新写成一个外部函数,并将函数名称经过magling(所谓的Name Mangling是指在member的名称上加上class名称以及member function的signature)处理,使它成为在程序中独一无二的语汇:

extern magnitude_7Point3dFv(

register Point3d* constthis);

现在这个函数已经村换号,而其每一个调用也都必须转换,如下:

obj. magnitude ()变为magnitude_7Point3dFv(&obj);

ptr-> magnitude()变为 magnitude_7Point3dFv(ptr);

normalize()函数将会被转换为一下形式,其中假设NRV可行:

void normalize_7Point3dFv(registerconst Point3d*constthis, Point3d *_result){

register float mag = this->magnitude();

_result.Point3d::Point3d();

_result._x = this->_x/mag;

_result._y = this->_y/mag;

_result._z = this->_z/mag;

return;

}

Virtue Member Function(虚拟成员函数)

如果normalize()是一个虚拟成员函数,那么下面的调用

ptr->normalize();

将会被内部转化为

( * ptr->vptr[ 1 ])( ptr );

其中:

Vptr表示右边一起产生的指针,指向virtual table。

1是virtual table slot的索引值,关联到normalize();

第二个ptr表示this指针。

但对于以下调用:

Obj.normalize();

上述调用的函数实例只可以是Point3d::normalize(),所以编译器会将它转化如下:

Normalize_7Point3dFv( &obj );

像上面经由一个class object调用一个虚函数,这种操作应该总是被编译器对待一般的nonstaticmember function一样加以决议。

Static Member Function(静态成员函数)

如果Point3d::normalize()是一个static memberfunction,一下两个调用:

obj.normalize();

ptr->normalize();

将被转换为一般的nonmember函数调用,像这样:

normalize_7Point3dSFv();

normalize_7Point3dSFv();

独立于class object之外的存取class object的static data member操作主要有两种方法:如下

1. 程序上的解决之道是将0强制转换为一个class指针,因而提供一个this指针实例,如下面这个例子:

class Point3d{

public:

int object_count(){

cout<< x << endl;

return x;

}

private:

static intconst x = 5;

};

int main(){

((Point3d*)0 )->object_count();

return 0;

}

结果输出5.

2. 语言层面上的解决之道,引入static member function。Static member function的主要特性就是它没有this指针。以下次要特性统统根源于主要特性:

1) 他不能够直接存取其class中的nonstaticmembers

2) 他不能够被声明为const、volatile或virtual

3) 它不需要经由class object才被调用---虽然大部分时候它是这样被调用的

取一个static member function的地址,获得的将是其在内存中的位置,也就是其地址。由于static member function没有this指针,所以其地址的类型是一个nonmember函数指针,并不是指向class member function的指针。

Static member function由于缺乏this指针,因此差不多等同于nonmember function。

4.2 virtual member functions虚拟成员函数

Virtual function的一般实现模型(无继承):每一个class有一个virtual table,内含class之中有作用的virtual function的地址,然后每个object有一个vptr,指向virtual table的存在。这一节会讨论单一继承,多重继承和虚拟继承这三种情况。

单一继承:

在编译时期:会准备好虚函数的地址值存放在虚函数表中,并且表中的这组地址是固定不变的,表本身的大小也不会改变;为了找到表格会为每个class object安插一个指针指向该表格。

执行期要做的是在特定的virtual table slot中激活virtual function。

在单一