类成员函数指针
向函数的指针变量
- 中文名
- 类成员函数指针
- 外文名
- member function pointer
- 学 科
- 编程语言
- 定 义
- 一类指针数据类型
- 有关术语
- 函数指针
- 用 途
- 将数据与相关代码结合
类成员函数指针是一类指针数据类型,C++的语法之一,主要用途是把数据与相关代码结合在一起。这与委托(delegate)、函子(functor)、闭包(closure)等概念很像。虽然C++对此支持的并不太好。MFC类体系中,Windows消息传递处理机制是基于CCmdTarget类及其派生类的静态数据成员与静态成员函数GetThisMessageMap()。用户所写的类中的Windows消息处理函数(例如OnCommand)必须转换为CCmdTarget::*的成员函数指针类型AFX_PMSG,保存在该用户类的_messageEntries静态数组中。
|
1
|
typedef void (CCmdTarget::*AFX_PMSG)(void); |
调用用户类中该消息处理函数时,根据该函数保存在_messageEntries中的signature(一个无符号整型表示的函数的形参类型列表与返回值类型),把类型为void (CCmdTarget::*AFX_PMSG)(void)的成员函数指针强制转为其它类型的CCmdTarget成员函数指针(例如void (AFX_MSG_CALL CWnd::*pfn_v_i_i)(int, int),在union MessageMapFunctions中列出了近百种CCmdTarget成员函数指针),然后调用转换后的成员函数指针。这是基于Visual C++编译器把单继承的成员函数指针编译为只保存了函数的内存起始地址,因此可以在同一个单继承类中把一种类型的成员函数指针强制转换为另一种成员函数指针,或者把单继承派生类的成员函数指针强制转换为基类成员函数指针。这是打破了C++标准的违例办法。例如,对于CWnd::OnCommand函数,转换过程是:
|
1
|
BOOL (CWnd::*)(WPARAM, LPARAM lParam) => void (CWnd::*)() => void (CCmdTarget::*)() |
使用::*声明一个成员指针类型,或者定义一个成员指针变量。使用.*或者->*调用类成员函数指针所指向的函数,这时必须绑定(binding)于成员指针所属类的一个实例的地址。例如:
|
1
2
3
4
5
6
7
8
9
10
11
|
struct X { void f(int){ }; int a;};void (X::* pmf)(int); //一个类成员函数指针变量pmf的定义pmf = &X::f; //类成员函数指针变量pmf被赋值 X ins, *p;p=&ins;(ins.*pmf)(101); //对实例ins,调用成员函数指针变量pmf所指的函数(p->*pmf)(102); //对p所指的实例,调用成员函数指针变量pmf所指的函数 |
由于C++运算符优先级列表中,函数调用运算符()的优先级高于.*与->*,因此成员函数指针所指的函数被调用时,必须把实例对象或实例指针、.*或->*运算符、成员函数指针用括号括起来,如上例所示。
C++标准规定,非静态成员函数不是左值,因此非静态成员函数不存在表达式中从函数左值到指针右值的隐式转换,非静态成员函数指针必须通过&运算符显式获得。所以上例中,pmf = X::f; 将编译报错。
浙公网安备 33010602011771号