Member的各种调用方式
Nonstatic Member Functions
由于C++的一个设计标准就是使得nonstatic member function要有和一般的nonmember function有相同的效率;
这就带来了一个变化,就是编译器内部会将nonstatic member function转换为等价的nonmember function实体;
转化步骤:
- 改写函数的原型,安插一个新的参数,即this指针;
- 将每一个对nontatic data member的存取操作改写为通过this指针的操作;
- 将member function改写成一个外部函数,修改函数名称;
例如一个这样的函数:
1 | Point3d Point3d::normalize() const |
将可能会改写成:
1 | void normalize_7Point3dFv(register const Point3d *const this, Point3d &__result) |
特别的,编译器内部会对名称进行mangling处理,虽然目前处理方式没有统一的标准,但一般来说会在member名称前面加上类名,甚至为了保证重载的操作,会加上函数参数的类型,当然如果声明了extern C,就会抑制了这种效果,这也是extern关键字的一个重要功能。
有时我们看到的编译器报错,显示了非常奇怪的函数名称报错,往往就是因为name mangling的原因。
Virtual member functions
如果normalize()是一个虚函数,那么以下调用会转化为:
1 | ptr->normalize(); |
1就是virtual function slot的索引值,关联到normalize()函数。
而如果里面的magnitude()函数也是虚函数,那么由于normalize会先调用,决定了object的类型,所以编译器会使用更加明确的调用方式,而不是(*ptr->vptr[2])(ptr);例如:
1 | register float mag = Point3d::magnitude(); |
Static Member Functions
如果normalize是一个静态函数,那么这两种调用会变为:
1 | obj.normalize(); |
由于static member function没有this指针,所以:
- 不能直接存取其中class的nonstatic members;
- 不能被声明为const, volatile或者virtual;
- 不需要经由对象调用(但是如果static member是一个private,就很可能要依赖于对象);
如果要取一个static member function的地址,那么其类型会是:unsigned int (*)();