4.1 Member 的各种调用方式
Nonstatic Member Functions
编译器内部已将“member函数实例”转换为对等的“nonmember函数实例”
例如
float Point3d::magnitude() const
{
return sqrt(_x*_x + _y*_y + _z*_z);
}
会被转换为
float magnitude3d(const Point3d * _this)
{
return sqrt(_this->_x * _this->_x +
_this->_y * _this->_y +
_this->_z * _this->_z );
}
成员函数到非成员函数的转换过程
- 改写函数的 signature 安插一个 this 指针。
- 将每一个“对 nonstatic data member 的存取操作”改为经由 this 指针来存取。
- 将 member function 重新写成一个外部函数。将函数名称经过“mangling”处理,使它在程序中成为独一无二的词汇。
Static Member Functions
如果 Point3d::normalize() 是一个 static member function,以下两个调用操作:
obj.normalize();
ptr->normalize();
将被转换为一般的 nonmember 函数调用,像这样:
//obj.normalize();
normalize_7Point3dSFv();
//ptr->normalize();
normalize_7Point3dSFv();
由cfront 2.0 所引入的 static member functions。Staic member functions 的主要特征就是它没有 this 指针。以下的次要特征统统根源于其主要特征:
- 它不能够直接存取其 class 中的 nonstatic members。
- 它不能够被声明为 const、valatile 或 virtual。
- 它不需要经由 class object 才被调用—-虽然大部分时候它是这样被调用的~
4.2 Virtual Member Functions
一个 class 只会有一个 virtual table。每一个 table 内含其对应之 class object 中所有 active virtual functions 函数实例的地址。这些 active virtual functions 包括:
- 这一 class 所定义的函数实例。它会改写(overrideing)一个可能存在的 base class virtual function 函数实例。
- 继承自 base class 的函数实例。这是在 derived class 决定不改写 virtual function 时才会出现的情况。
- 一个pure_virtual_called()函数实例,它既可以扮演 pure virtual function 的空间保护者角色,也可以当做执行期异常处理函数(有时会用到)。
class Point
{
public:
virtual ~Point();
virtual Point& mult( float ) = 0;
//... 其他操作
float x() const { return _x; }
virtual float y() const { return 0; }
virtual float z() const { return 0; }
// ...
protected:
Point( float x = 0.0 );
float _x;
};
virtual destructor 被指派 slot 1,而 mult() 被指派 slot 2。此例并没有 mult() 的函数定义,所以 pure_virtual_called() 的函数地址会被放在 slot 2 中。如果该函数意外地被调用,通常的操作是结束掉这个程序。y()被指派 slot 3 而 z() 被指派 slot 4。x()的 slot 是多少?答案是没有,因为x()并非virtual function。
一般
ptr->z();
这样的式子会在编译期间
- 经由ptr可以存取到该对象的 virtual table。
- 每一个z()函数地址都被放在了 slot4 中。
编译器将该调用转化为:
( *ptr->vptr[4] )( ptr );
在这一转化中,vptr 表示编译器所安插的指针,指向 virtual table;4表示 z()被指派的 slot 编号(关系到Point 体系的 virtual table)。唯一一个在执行期才能知道的东西是:slot 4 所指的到底是哪一个z()函数实例?
多重继承下的Virtual Functions
在多重继承之下,一个 derived class 内含 n-1 个额外的 virtual tables,n表示其上一层 base classes 的个数。对于本例的 Derived 而言,会有两个 virtual tables 被编译器产生出来:
- 一个主要实例,与 Base1(最左端 base class)共享。
- 一个次要实例,与Base2(第二个 base class)有关。
针对每一个 virtual tables,Derived 对象中有对应的 vptr。通过指针调用各个方法,主要是通过调整this指针,上下移动来调用。
虚拟继承下的 Virtual Functions
不要在一个 virtual base class 中声明 nonstatic data members。