Chapter 4. The Semantics of Function: Function 语意学
4.1 Member 函数的各种调用方式
1. Nonstatic Member Function(非静态成员函数)
要做如下的转换:
(1) 改写函数的原形, 安插一个参数到member function中, 用于提供一个存取管道, 使class object 得以调用该函数, 这个额外的指针称之为: this指针.
如:
Point3d::magnitude() 会转换为: Point3d::magnitude(Point3d *const this)
(2) 对函数内每一个针对nostatic data member的存取操作改经由this指针来存取.
如:
return sqrt(
this->_x * this->_x + this->y * this->_y + this->_z * this->_z;
(3) 将对member function 重写一个外部函数, 对函数名称进行"mangling"处理, 使它生成一个独一无二的名称
2. Virtual Member Function(虚拟成员函数)
例如:
ptr->normalize();
它将被转化为如下的调用:
( * ptr->vptr[ 1 ])( ptr );
这里有几点说明:
i. vptr是由编译器生成的指针,指向virtual table
ii. 1 这里是virtual table slot 的索引值,它关联到nomalize这个函数
iii. 第二个ptr表示this指针
3. Static Member Function(静态成员函数)
如果Point3d::normalize()是一个static member function的话,这两个调用会转化为一般的操作:
obj.normalize();
ptr->normalize();
转化为:
// obj.normalize();
normalize__7Point3dSFv();
// ptr->normalize();
normalize__7Point3dSfv();
4.2 Virtual Member Functions(虚拟成员函数)
1. 单一继承下的Virtual Functions
一个多态的class object 身上增加两个members:
I. 一个字符串或数字, 表示class的类型
II. 一个指针,指向某个表格,表格中带有程序的virtual function的执行时期地址
对于一个active virtual function包括下面三个内容:
I. 这个class 所定义的函数实体, 它会改写一个可能存在的base class virtual function 函数实体.
II. 继承自基类的实体, 这是在derived class 决定不改写virtual function 时才会出现的情况
III. 一个pure_virtual_called()函数实体,它既可以扮演pur virtual function的空间保卫者角色, 也可以当做执行期异常函数.
2. 多重继承下的Virtual Functions
这种继承涉及到要调整this指针,并且要求不止一个vtbl和vptr,同时要好几个这种虚表和指针
3. 虚拟继承下的Virtual Functions
4.3 函数的效能
4.4 指向Member Functions的指针(Pointer-to-Member Functions)
1. 指向一般成员函数的指针(Nostatic member and novirtual member function)
取一个nostatic member function的地址, 如果该函数是novirtual, 则得到的结果是它在内存中真正的地址, 然而这个地址也不是完全的, 它也需要绑定到某个class object的地址上, 才能够调用该函数. 所有的nostatic member functions都要对象的地址(用this指出).
例如:
double (Point::*pmf)(); // 定义一个成员函数指针
pfm = &Point::y; // 初始化这个指针为
(ptr->*pfm)() ; // 调用为, 编译器转化为: (pfm)(ptr)
2. 支持"指向Virtual Member Functions"的指针
对于virtual function, 其地址在编译时期是未知的, 所能知道的仅是virtual function在相关的vitual table 中的索引值. 也就是说对于一个virtual member function取其地址, 所能获得的只是一个索引值.
所以如果:
pmf = &Point::z(); // 获得的是索引值, 调用时:
(ptr.->pmf)() // 会转化为: (* ptr->vptr[(int)pfm] (ptr)
3. 在多重继承下,指向Member Functions的指针
比较复杂, 定义了一个结构支持这们的操作
4. 指向 Member Functions 指针的效率
4.4 Inline Functions
1. inline functions的生成条件
2. 对形式参数的处理(Formal Arguments)
例如:
1 inline int min( int i, int j )
2 {
3 return i < j ? i : j;
4 }
5 and the following three invocations of the inline function:
6
7 inline int bar()
8 {
9 int minval;
10 int val1 = 1024;
11 int val2 = 2048;
12
13 /*(1)*/minval = min( val1, val2 );
14 /*(2)*/minval = min( 1024, 2048 );
15 /*(3)*/minval = min( foo(), bar()+1 );
16
17 return minval;
18 }
用下面的方式进行处理:
(1) 直接的参数替换
//(1) simple argument substitution
minval = val1 < val2 ? val1 : val2;
(2) 如果实际参数是一个常量表达式(const expression), 我们就可以在替换前完成对它的求值操作.
//(2) constant folding following substitution
minval = 1024;
(3) 带有副作用的实际参数, 引入临时性的对象
//(3) side-effects and introduction of temporary
int t1;
int t2;
minval = ( t1 = foo() ), ( t2 = bar() + 1 ), t1 < t2 ? t1 : t2;
3. 对inline函数带有局部变量的处理(Local Variables)
如:
inline int min( int i, int j )
{
int minval = i < j ? i : j;
return minval;
}
对于如下的调用:
{
int local_var;
int minval;
// ...
minval = min( val1, val2 );
}
转换可能的结果是:
1 {
2 int local_var;
3 int minval;
4 // mangled inline local variable
5 int __min_lv_minval;
6
7 minval = ( __min_lv_minval = val1 < val2 ? val1 : val2 ), __min_lv_minval;
8 }