怎样将成员函数c指针强制类型转换转换成void

怎么实现类的成员函数作为回调函数
字体:[ ] 类型:转载 时间:
不使用成员函数,为了访问类的成员变量,可以使用友元操作符(friend),在C++中将该函数说明为类的友元即可
如果试图直接使用C++的成员函数作为回调函数将发生错误,甚至编译就不能通过。其错误是普通的C++成员函数都隐含了一个传递函数作为参数,亦即“this”指针,C++通过传递this指针给其成员函数从而实现程序函数可以访问C++的数据成员。这也可以理解为什么C++类的多个实例可以共享成员函数却-有不同的数据成员。由于this指针的作用,使得将一个CALL-BACK型的成员函数作为回调函数安装时就会因为隐含的this指针使得函数参数个数不匹配,从而导致回调函数安装失败。要解决这一问题的关键就是不让this指针起作用,通过采用以下两种典型技术可以解决在C++中使用回调函数所遇到的问题。这种方法具有通用性,适合于任何C++。  
1). 不使用成员函数,为了访问类的成员变量,可以使用友元操作符(friend),在C++中将该函数说明为类的友元即可。   
2). 使用静态成员函数,静态成员函数不使用this指针作为隐含参数,这样就可以作为回调函数了。静态成员函数具有两大特点:其一,可以在没有类实例的情况下使用;其二,只能访问静态成员变量和静态成员函数,不能访问非静态成员变量和非静态成员函数。由于在C++中使用类成员函数作为回调函数的目的就是为了访问所有的成员变量和成员函数,如果做不到这一点将不具有实际意义。解决的办法也很简单,就是使用一个静态类指针作为类成员,通过在类创建时初始化该静态指针,如pThis=this,然后在回调函数中通过该静态指针就可以访问所有成员变量和成员函数了。 这种处理办法适用于只有一个类实例的情况,因为多个类实例将共享静态类成员和静态成员函数,这就导致静态指针指向最后创建的类实例。为了避免这种情况,可以使用回调函数的一个参数来传递this指针,从而实现数据成员共享。这种方法稍稍麻烦,这里就不再赘述。
首先明白什么是回调函数:比如说被调函数void callbackf(int n){}要想作为回调函数的话,callbackf必须作为主调函数的形参出现,如void f(void (*p(int)),int n)形式才行!
例1: 代码如下:#include&iostream&class A{public:&friend void callback()& //友元函数作为回调函数 friend方式实现&{& cout&&"回调函数开始执行了!"&&&}};void f(void (*p)())&{& p();
&}int main(){&void (*p)();&p=&f(p);&return 0;}例2: 代码如下:#include&iostream&class A{public:&static void callback()& //类的成员函数作为回调函数 static方式实现&{& cout&&"回调函数开始执行了!"&&&}};void f(void (*p)())&{& p();
&}int main(){&void (*p)();&p=A::&f(p);&return 0;}还可以把f()函数设为类的成员函数: 代码如下:#include&iostream&class A{public:&static void callback()& //类的成员函数作为回调函数 static方式实现&{& cout&&"回调函数开始执行了!"&&&}&void f(void (*p)())&{& p();
int main(){&A&void (*p)();&p=A::&a.f(p);&return 0;}
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具非澹泊无以明志,非宁静无以致远
&&& 指针应该都是4个字节,指向32位的地址.可以寻访4GB的内存.如果是64位就再说.所以对函数指针来说这个应该就有了很大的好处.因为指针大家都是4个字节不论是什么种类的函数,它肯定都是4字节.这样赋值就没问题.在这里你也可以将指针直接看成是一个整数.这样会更明白些.而对于另外一个问题.函数参数和返回值,则完全由函数的定义来决定.嗯.这样就可以有很大的自由空间.来段代码.
&1#include&iostream&&2using&namespace&std&;&3&4typedef&void&(*pfn)&(void);&5union&msg&6{&7&&&&pfn&first&;&8&&&&int&(*&ifn)(int&a&,int&b&);&9&&&&void(*vfn)(int&,int&);<span style="COLOR: #};<span style="COLOR: #int&OnInt(int&a&,int&b&)<span style="COLOR: #{<span style="COLOR: #&&&&cout&&a&&"&&&&"&&b&&<span style="COLOR: #&&&&return&a&;<span style="COLOR: #}<span style="COLOR: #void&OnVoid(int&a&,int&b&)<span style="COLOR: #{<span style="COLOR: #&&&&cout&&a&&&"&&&&"&&b&&<span style="COLOR: #}<span style="COLOR: #int&main()<span style="COLOR: #{<span style="COLOR: #&&&&pfn&p=(pfn)(int&(*)(int&,int&))OnI<span style="COLOR: #&&&&msg&m;<span style="COLOR: #&&&&m.first=p;<span style="COLOR: #&&&&cout&&(m.ifn)(<span style="COLOR: #,<span style="COLOR: #)&&<span style="COLOR: #<span style="COLOR: #&&&&p=(pfn)(void&(*)(int,&int&))OnV<span style="COLOR: #&&&&m.first=p;<span style="COLOR: #&&&&m.vfn(<span style="COLOR: #,<span style="COLOR: #);<span style="COLOR: #&&&&return&<span style="COLOR: #;<span style="COLOR: #}
看了这段代码会让人想到什么呢?想到的应该是MFC中那些消息函数吧.不同的消息,参数不一样,返回值也不一样.而在定义的时候只是一个指针,可是在调用的时候却有各种各样的方式.另外这段代码最有意思的就是打破常规,就用了union同时只有一个变量在起作用,平时书上总是说其他变量都不能用,今天就用给你看看,用的还很牛...
评论排行榜
阅读排行榜天极传媒:天极网全国分站
您现在的位置:
& &&将成员函数转换成void*
将成员函数指针强制转换成void*指针论坛整理 07:00
  采用取成员函数指针的地址的方法,先把指向成员函数指针的指针强制转化为别的类型,如unsigned*,当然同样可以通过此转化后的指针经过相反的变换来调用成员函数。于是乎要转化为void*的问题也随之可解,如下示例:
以下是引用片段:  /*&VS2003下编译运行&*/   class&AbstractMethod   {   public:   virtual&void&show(){}&//&=&0;&//&可以是纯虚函数,这里为了测试方便不使用纯虚函数!   void&fun()   {   cout&&&&"I&was&called!"&&&&   }   void&fun1()   {   cout&&&&"I&was&called!"&&&&   }   };   int&main()   {   //&定义成员函数指针类型   typedef&void&(AbstractMethod::*MFP)(void);   //&转化函数指针为别的指针   MFP&mfp1&=&&AbstractMethod::   unsigned*&tmp&=&(unsigned*)&mfp1;   cout&&&&hex&&&&*tmp&&&&   MFP&mfp2&=&&AbstractMethod::   tmp&=&(unsigned*)&mfp2;   cout&&&&hex&&&&*tmp&&&&   MFP&mfp3&=&&AbstractMethod::fun1;   tmp&=&(unsigned*)&mfp3;   cout&&&&hex&&&&*tmp&&&&   //&通过转化后的指针调用成员函数   AbstractMethod&   MFP*&addr&=&(MFP*)   (am.*mfp3)();   (am.*(*addr))();   return&0;   }
  验证上述方法取得的成员函数地址是否正确:
  1. 在调试是查看临时变量函数指针的值和输出的是否一样。
  2. 可以根据调试时的反汇编进行结果验证。
  3. 最好的办法就是如上例子通过转化后的指针来调用成员函数。&&阅读关于
的全部文章
(作者:liulj责任编辑:卢林嘉)
欢迎在新浪微博上关注我们
办公软件IT新闻整机为什么成员函数指针不能转换为void*?void *pVoid = (void*)(&CTest::SomeFun);error C2440: “类型转换”: 无法从“bool (__thiscall CTest::* )(void)”转换为“void *”编译器为什么禁止这样的转换?我的环境是VC2008。上网找了一下,看到一个链接——里面的楼主提到一句话:“成员函数指针与void*指针长度可能不同,不能随意转。”真的是这样么?我的理解,Win32系统里,所有的指针都是4个字节长吧?成员函数指针不能转换为void*的真正原因是什么呢?
回答1:有时间去看看 c++必知必会 关于成员函数指针那个专题吧。你就知道为什么了。
javakaoshi
回答2:有一个东西叫boost,function+bind库。
回答3:可以转换的,只是编译器限制不许你转换而已看这个template &typename to,typename from&void cvt_ptr(from f,to& t){ union&
_t; } ut._f = t = ut._t;}这段代码用于winproc jmp 至成员函数处理。win32或者wow64运行正常. 64位编译可能需要修改机器码和指针长度  C/C++ code  LPBYTE
pAsm=(LPBYTE)VirtualAlloc(NULL,128,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
assert(pAsm);
pAsm[0]=0xb9;
*(LPDWORD)(pAsm+1)=(DWORD)(LPVOID)
pAsm[5]=0xb8;
cvt_ptr(&GWindow::WinProc,*(LPDWORD)(pAsm+6));
pAsm[10]=0
pAsm[11]=0xe0;
pWinProc=pA
LZ既然想保存类的函数指针就要定义一个类函数指针类型template&class T&struct MemFunc{ typedef void (T::*FuncType)(); T * FuncType memF unsigned int nE};class NULLTYPE{};typedef MemFunc&NULLTYPE& BaseFstruct MemFuncInfo{ BaseFunc* pF};static UINT_PTR AddNewFunc(unsigned int nElapse, T *pObj, void (T::*memFunc)()){ if (pObj == NULL || memFunc == NULL)
return 0; MemFunc&T& *newCallFunc = new MemFunc&T&; newCallFunc-&memFunc = memF newCallFunc-&obj = pO newCallFunc-&nElapse = nE MemFuncInfo baseFuncI baseFuncInfo.pFunc = (BaseFunc*)newCallF//NULLTYPE类型指针让编译器通过,不然编译器无法知道是什么类型的实例化指针,编译布恩那个通过 m_callFuncList.push_back(baseFuncInfo); return timerID;}static std::vector&MemFuncInfo& m_callFuncL//不存不同类对象的函数指针实际调用过程如下:AddNewFunc(10, this, &CNetWork::RunOnce);//从代码层次来讲这样非常简洁了,编译器能自己推出什么T
回答5:探讨地址是能取到的C/C++ codetypedef bool (CTest::*FUNCPTR)(const CString&);FUNCPTR ptr = &CTest::MsgB // ptr == 0x004ee2ce
CTest有虚函数
javakaoshi

我要回帖

更多关于 指针强制转换 的文章

 

随机推荐