前言
最初的C with classes只支持nonstatic member functions。Virtual function在80年代中期被加入,static member function是1987年被最后加入。
Nonstatic Member Functions
C++的一大设计准则是:nonstatic member function至少需要与一般的nonmember function具备同样的效率。也就是说,假定现在有两个函数如下:1
2float magnitude3d(const Point3d *_this) {...}
float Point3d::magnitude3d() const {...}
这两个函数至少保证具备一致的调用效率,事实上,编译器总是会把member function转为对应的nonmember形式。
假设nonmember function定义式如下:1
2
3
4
5float magnitude3d(const Point3d *_this){
return sqrt(_this->_x*_this->_x+
_this->_y*_this->_y+
_this->_z*_this->_z);
}
member function的转化步骤
改写函数signature
具体来说,则是增加一个额外参数*this,保证class object得以调用。1
float Point3d::magnitude(Point3d* const this);
如果member function具备const属性,则函数被转化为
1
float Point3d::magnitude(const Point3d* const this);
将data member的存取操作改为通过this指针完成:
1
2
3return sqrt(_this->_x*_this->_x+
_this->_y*_this->_y+
_this->_z*_this->_z);将转化后的member function重写为一个外部函数,并对它执行名变化处理。
1
extern magnitude_7Point3dFv(register Point3d *const this);//独一无二的名称
现该函数已被转化完成,相对应的调用操作也需要执行转化:1
2
3
4
5
6//转化前
obj.magnitude();
ptr->magnitude();
//转化后
magnitude_7Point3dFv(&obj);
magnitude_7Point3dFv(ptr);
名变换
一般来说,member的名称前面需要加上class名称,形成独一无二的命名。举例而言:1
class Bar {public:int ival;...};
其中的ival
可能被名变换为ival_3Bar
,编译器为什么需要对每一个member在名变换时考虑其class?
考虑下面的派生操作:1
class Foo:public Bar {public:int ival;...};
在经过名变换后,Foo的内部描述如下所示:1
2
3
4
5
6class Foo{
public:
int ival_3Bar;
int ival_3Foo;
...
};
这样保证了在名变换后可以清楚地指出任何一个值。
Member functions可以被重载,因此其需要更广泛地名变换手法,例如:1
2
3
4
5
6
7
8
9
10
11
12
13
14//名变换前
class Point{
public:
void x(float newX);
float x();
...
}
//名变换后
class Point{
public:
void x_5PointFf(float newX);
float x_5PointFv();
...
}
这种将参数与函数名结合的名变换(函数名称+参数数目+参数类型)保证了:函数如果出现了错误的声明或调用形式,则无法发生正确的连接。但显然,它无法判断返回类型声明错误这种情况。
Virtual Member Functions
如果normalize()是一个virtual member function,那么以下的调用:1
ptr->normalize();
将会被内部转化为:1
(*ptr->vptr[1])(ptr);
Static Member Functions
nonstatic member functions之所以需要this指针,是因为其对某个具体的member进行存取。Static member function不需要存取具体的member,因此它也无需使用this指针。
Static member function具备三大特性:
- 不能够直接存取nonstatic member
- 不能被声明为const、volatile或virtual
- 无需经由class object被调用
由于缺乏this指针,static member function在内存布局中与nonmember function即为类似。