将类成员函数用做 C 回调函数
提出问题:
回调函数是基于 C 编程的 Windows SDK 的技术,不是针对 C++的,程序员可以将一个
C 函数直接作为回调函数,但是如果试图直接使用 C++的成员函数作为回调函数将发生错
误,甚至编译就不能通过。
分析原因:
普通的 C++成员函数都隐含了一个传递函数作为参数,亦即“this”指针,C++通过传递
一个指向自身的指针给其成员函数从而实现程序函数可以访问 C++的数据成员。这也可
以理解为什么 C++类的多个实例可以共享成员函数但是确有不同的数据成员。由于 this
指针的作用,使得将一个 CALLBACK 型的成员函数作为回调函数安装时就会因为隐含的
this 指针使得函数参数个数不匹配,从而导致回调函数安装失败
解决方案:
一,不使用成员函数,直接使用普通 C 函数,为了实现在 C 函数中可以访问类的成员变量,
可以使用友元操作符(friend),在 C++中将该 C 函数说明为类的友元即可。这种处理机制
与普通的 C 编程中使用回调函数一样。
二,使用静态成员函数,静态成员函数不使用 this 指针作为隐含参数,这样就可以作为回调
函数了。静态成员函数具有两大特点:其一,可以在没有类实例的情况下使用;其二,只
能访问静态成员变量和静态成员函数,不能访问非静态成员变量和非静态成员函数。由于
在 C++中使用类成员函数作为回调函数的目的就是为了访问所有的成员变量和成员函数,
如果作不到这一点将不具有实际意义。我们通过使用静态成员函数对非静态成员函数包装
的办法来解决问题。类实例可以通过附加参数或全局变量的方式的方式传递到静态成员函
数中。分别举例如下:
1,参数传递的方式
#include <iostream.h>
class TClassA
{
public:
void Display(const char* text) { cout << text << endl; };
static void Wrapper_To_Call_Display(void* pt2Object, char* text);
// more....
};
// 静态包装函数,能够调用成员函数 Display(),本身做为回调函数来使用
void TClassA::Wrapper_To_Call_Display(void* pt2Object, char* string)
{
// 显式类型转换
TClassA* mySelf = (TClassA*) pt2Object;
// 调用普通成员函数
mySelf->Display(string);
}