指向成员函数的指针

 

取一个非静态成员函数的地址,如果该函数是nonvirtual,则得到的结果是它在内存中真正的地址。然而这个值也不是完全的,它也需要被绑定于某个class object的地址上,才能够通过它调用该函数。所有的非静态成员函数都需要对象的地址(以参数this指出)。

一个指向成员函数的指针,其声明语法如下所示:

double      //return type

(Point::*  //class the function is member

pmf)        // name of pointer to member

();         // argument list

然后我们可以这样定义并初始化该指针:

double (Point::*coord)() = &Point::x;

也可以这样指定其值:

coord = &Point::y;

想调用它,可以这样做:

(origin.*coord)();或 (ptr->*coord)();

指向member function的指针的声明语法,以及指向“member selection运算符”的指针,其作用是作为this指针的空间保留者。这也就是为什么static member functions(没有this指针)的类型为“函数指针”,而不是“指向member function之指针”的原因。使用一个成员函数的指针,如果并不用于虚函数、多重继承、虚基类等情况的话,并不会比使用一个“nonmember function 指针”的成本更高。

 

支持“指向virtual member functions”的指针

注意下面的程序片段:

float (Point::*pmf)() = &Point::z;

Point *ptr = new Point3d;

pmf,一个指向成员函数的指针,被设置为Point::z()(一个虚函数)的地址。如果我们直接经由ptr调用z():

ptr->z();

则被调用的是Point3d::z()。但如果我们从pmf间接调用z()呢?

(ptr->*pmf)();

仍然是Point::z()被调用吗?也就是说,虚拟机制仍然能够在使用“指向成员函数的指针”的情况下正常运行吗?如何实现的呢?

面对一个虚函数,其地址在编译时期是未知的,所能知道的仅仅是虚函数在其相关的虚表中的索引值。也就是说,对一个虚成员函数取其地址,所能获得的只是一个索引值。假设我们有以下的Point声明:

Class Point{

public:

virtual ~Point();

float x();

float y();

virtual float z();

//…

}

然后取destructor的地址:

&Point::~Point;

得到的结果是1。取x()或y()的地址:

&Point::x();

&Point::y();

得到的是函数在内存中的地址,因为它们不是virtual。取z()的地址:

&Point::z();

得到的结果是2,通过pmf来调用z(),会被内部转化为一个编译时期的式子,一般形式如下:

( *ptr->vptr[(int)pmf] )( ptr );

 

对一个指向成员函数的指针评估求值,会因为该值有两种意义而复杂化,其调用操作也将有别于常规调用操作。pmf的内部定义,也就是:

float (Point::*pmf)();

必须允许该函数能够寻址出nonvirtual x()和virtual z()两个成员函数,这两个成员函数有着相同的原型,只不过其中一个代表内存地址,另外一个代表在对应虚表中的索引值。因此,编译器必须定义pmf使它能够(1)含有两种数值,(2)更重要的是其数值可以被区别代表内存地址还是虚表中的索引值。

在cfront2.0的非正式版本中,这两个值被内含在一个普通的指针内。它使用如下技巧:

(((int)pmf) & ~127)

? (*pmf)(ptr)                            //non-virtual invocation

: ( *ptr->vptr[(int)pmf] )( ptr );   //virtual invocation

这种实现技巧必须假设继承体系中最多只能够有128个虚函数。这并不是我们所希望的,但却证明是可行的。

 详见http://huz.china1sms.com/show-10-3417-1.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值