类的普通成员函数的指针

很 多朋友都知道虚函数有虚函数指针,并且存放在对象的虚函数表中,它和普通成员变量一样与对象相关,因此虚函数的指针是和对象级的。一个类的普通成员函数是 类级的,因此普通成员函数的指针也是类级的。一个类的普通成员函数的指针,少有文献提及,因为很少需要用到普通成员函数的指针。尽管如此,在一些特殊的场 合,还是有可能需要用到的。

1) 成员函数简介

C++ 中,成员函数的指针是个比较特殊的东西。对普通的函数指针来说,可以视为一个地址 , 在需要的时候可以任意转换并直接调用。但对成员函数来说,常规类型转换是通不过编译的,调用的时候也必须采用特殊的语法。 C++ 专门为成员指针准备了三个运算符 : "::*" 用于指针的声明,而 "->*" ".*" 用来调用指针指向的函数。比如 :

#include <iostream>

using namespace std;

 

class Foo

{       

public:               

         double virtual One( long inVal );               

         double virtual Two( long inVal );

};

 

double Foo::One(long inVal)

{

         return inVal;

}

 

double Foo::Two(long inVal)

{

         return inVal;

}

 

// 定义一个指向成员函数的指针类型,这些成员函数的返回值类型应该是 double ,并且有一个 long 类型的参数。

typedef double (Foo::*PMF)(long);

 

// 定义一个以对象调用函数指针的方法,其中: obj :调用成员函数指针的对象; pointer :成员函数的指针。

// 注意:因为 ".*" 优先级较低,所以该符号的两端,均需加上括号

#define callmemfun(obj, pointer) ((obj).*(pointer))

 

// 定义一个以对象指针调用函数指针的方法,其中: pobj :调用成员函数指针的对象指针; pointer :成员函数的指针。

// 注意:因为 "->*" 优先级较低,所以该符号的两端,均需加上括号

#define pcallmemfun(pobj, pointer) ((pobj)->*(pointer))

 

int main(void)

{       

         Foo aFoo;

         // 注意:获取一个成员函数指针的语法要求很严格

         // 1. 不能使用括号,比如 PMF pmf = &(Foo::Two) 是错误的

         // 2. 必须有类限定符,如 PMF pmf = &Two 是错误的, 即使是在类定义的内部也须加上类限定符, PMF pmf = &Foot::Two

         // 3. 必须使用取址符号:比如 PMF pmf = Foo::Two 是错误的,虽然普通函数指针可以这样 ( 其实对以成员函数指针,某些编

//   译器也是允许这样,但最好还是加上取址符号 ) ,应该写成 PMF pmf = &Foot::Two

         PMF pmf = &Foo::Two;                                             // 取成员函数指针

        

         double result = callmemfun(aFoo, pmf)(2);

         cout << result << endl;

 

         result = pcallmemfun(&aFoo, pmf)(3);

         cout << result << endl;

 

         return 0;

}

 

无 法将成员函数类型转换为其它任何稍有不同的类型,简单的说,每个成员函数指针都是一个独有的类型,无法转换到任何其它类型。即使两个类的定义完全相同也不 能在其对应成员函数指针之间做转换。这有点类似于结构体的类型,每个结构体都是唯一的类型,但不同的是,结构体指针的类型是可以强制转换的。有了这些特殊 的用法和严格的限制之后,类成员函数的指针实际上是变得没什么用了。这就是我们平常基本看不到代码里有 "::*", ".*" "->*" 的原因。

 

2) 使用成员函数指针访问类的私有成员函数

#include <iostream>

using namespace std;

 

class Foo;

typedef double (Foo::*PMF)(long);

 

#define callmemfun(obj, pointer) ((obj).*(obj.pointer))

#define pcallmemfun(pobj, pointer) ((pobj)->*(pobj->pointer))

 

class Foo

{

public:

         PMF pmf;

         Foo()

         {

                   pmf = &Foo::Three;                                // 取得私有成员函数的指针

         }

public:               

         inline double One(long inVal)

         {

                   return inVal;

         }

         inline double Two(long inVal)

         {

                   return 2 * inVal;

         }

private:

         inline double Three(long inVal)

         {

                   cout << "this is in Three..." << endl;

                   return 3 * inVal;

         }

};

 

int main(void)

{       

         Foo aFoo;

         Foo* bFoo = new Foo;

         // 通过公有成员变量 pmf ,很轻松地调用了私有成员函数 Three

         callmemfun(aFoo, aFoo.pmf)(3);

         pcallmemfun(bFoo, bFoo->pmf)(4);

 

         ((aFoo).*(aFoo.pmf))(3);

         return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值