1. 非虚成员函数指针(非静态)。
取一个非静态成员函数的地址,如果该函数是非虚函数,则得到的是它在内存中的真正地址,但是该地址并不完全,需要绑定与具体的类实例(对象)之上,借助对象的地址(this指针)才可以被调用,例如:一个成员函数指针
- double (Point::* pmf)();
- double (Point::*coord)() = &Point::getX;//或者这样初始化它:coord = &Point::getX;
- (orgin.*coord)();//或者这样(ptr->*coord)();
- (coord)(&origin);//或者(coord)(ptr);
2. 指向虚成员函数的指针。
当一个函数指针指向一个虚成员函数时,例如:
- float (Point::*pmvf)() = &Point::z;//z为虚函数
- Point *ptr = new Point3d;//Point3d为Point的子类
- (ptr->*pmvf)();//效果等同于ptr->z();
- class Point {
- public:
- virtual ~ Point();
- float x();
- float y();
- virtual float z();
- };
- (*ptr->vptr[(int)pvmf])(ptr);//调用Point3d::z()
由于多重继承(包括多重虚拟继承)涉及到,子类中可能存在多个虚表,this指针的可能需要调整偏移,书中举例了cfront的实现方法,引入一个结构体,在需要的时候保存上述内容,结构体如下:
- struct __mptr {
- int delta;//虚基类或者多重继承下的第二个以及之后基类的this指针偏移
- int index;//虚函数索引,非虚函数此值为-1
- union {
- ptrtofunc faddr;//非虚函数地址
- int v_offset;//虚基类或者多重继承下的第二个以及之后基类的虚表位置
- };
- };
- (ptr->*pmvf)();
- (pmvf.index < 0) ?
- (*pmvf.faddr)(ptr)//非虚函数
- : (*ptr->vptr[pmvf.index])(ptr);//虚函数
1. 对于单一表达式的多重调用:
对如下incline函数:
- inline Point operator+ (const Point& lhs, const Point& rhs)
- {
- Point new_pt;
- new_pt.x(lhs.x() + rhs.x());//x()函数为成员变量_x的get,set函数
- return new_pt;
- }
- new_pt.x = lhs._x + x__5PointFV(&rhs);
- new_pt.x(lhs._x + rhs._x);
有如下inline函数:
- inline int min(int i, int j)
- {
- return i < j ? i : j;
- }
- inline int bar()
- {
- int minVal;
- int val1 = 1024;
- int val2 = 2048;
- minVal = min(val1, val2);//case 1
- minVal = min(1024, 2048);//case 2
- minVal = min(foo(), bar() + 1);//case 3
- return minVal;
- }
- minVal = val1 < val2 ? val1 : val2;
- minVal = 1024;
- int t1;
- int t2;
- minVal = (t1 = foo()), (t2 = bar() + 1), t1 < t2 ? t1: t2;
改写上述min函数,引入一个局部变量:
- inline int min(int i, int j)
- {
- int minVal = i < j ? i : j;
- return minVal;
- }
- int minVal;
- int val1 = 1024;
- int val2 = 2048;
- minVal = min(val1, val2);
- int minVal;
- int val1 = 1024;
- int val2 = 2048;
- int __min_lv_minVal;//将inline函数局部变量mangling
- minVal = (__min_lv_minVal = val1 < val2 ? val1: val2), __min_lv_minVal;
再复杂一些的情况,例如局部变量加上有副作用的参数,会导致大量临时性对象的产生:
- minVal = min(val1, val2) + min(foo(), bar() + 1);
会被扩展成为,注意逗号表达式,由左至右计算各个分式,以最右端的分式值作为最终值传回:
- int __min_lv_minVal_00;
- int __min_lv_minVal_01;
- int t1;
- int t2;
- minVal = (__min_lv_minVal_00 = val1 < val2 ? val1 : val2, __min_lv_minVal_00) +
- (__min_lv_minVal_01 = (t1 = foo(), t2 = bar() + 1, t1 < t2 ? t1 : t2), __min_lv_minVal_01);