⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 subject_56230.htm

📁 vc
💻 HTM
字号:
<p>
序号:56230 发表者:xiongli 发表日期:2003-10-16 11:50:04
<br>主题:成员函数指针
<br>内容:#include &#34;stdio.h&#34;<BR>class A<BR>{<BR>&nbsp;&nbsp;public:<BR>&nbsp;&nbsp;&nbsp;&nbsp; virtual void t(){<BR>&nbsp;&nbsp;&nbsp;&nbsp; printf(&#34;base\n&#34;);<BR>&nbsp;&nbsp;&nbsp;&nbsp; };<BR>&nbsp;&nbsp;&nbsp;&nbsp; virtual void t2()<BR>&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp; };<BR>&nbsp;&nbsp;&nbsp;&nbsp; int rt()<BR>&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf(&#34;non virtual func\n&#34;);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 1;<BR>&nbsp;&nbsp;&nbsp;&nbsp; };<BR><BR>};&nbsp;&nbsp;&nbsp;&nbsp; <BR>class B:public A<BR>{<BR>public:<BR>&nbsp;&nbsp;&nbsp;&nbsp;virtual void t(){<BR>&nbsp;&nbsp;&nbsp;&nbsp;printf(&#34;derive\n&#34;);<BR>&nbsp;&nbsp;&nbsp;&nbsp;};<BR>&nbsp;&nbsp;&nbsp;&nbsp;virtual void t2(){};<BR>};<BR>void justfun()<BR>{<BR>int a;<BR>a=0;<BR>};<BR> <BR>int&nbsp;&nbsp;main()<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A *p;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; B&nbsp;&nbsp;O;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p=&amp;O;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int(*cast)();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void(*nof)();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void(A::*pmf)();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int(A::*rpmf)();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nof=&amp;justfun;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rpmf=&amp;A::rt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pmf=&amp;A::t2;<BR>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cast=(int * ())(rpmf);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; __asm<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; push eax<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov eax,rpmf<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov cast,eax<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pop eax<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf(&#34;%x&nbsp;&nbsp;&nbsp;&nbsp;%x&nbsp;&nbsp;&nbsp;&nbsp;%x\n&#34;,nof,pmf,rpmf);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (*cast)();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(*nof)();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (p-&gt;*rpmf)();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (O.*pmf)();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (p-&gt;*pmf)();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pmf=&amp;A::t;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (p-&gt;*pmf)();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p-&gt;t2();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<BR>}<BR>今天早上看到一个朋友的留言,关于通过成员函数指针调用成员函数的问题。<BR>成员函数指针调用跟普通函数指针调用不同。<BR>因为成员函数有虚函数和非虚函数的差别,调用的时候,跟普通非成员函数调用有不同。<BR>对于非成员函数,取函数名的地址,得到的就是该函数内存中的起始地址,然后直接调用就可以。在汇编层面上,就是直接call addr.<BR>对于非虚成员函数,取得的地址其实也就是完整的函数地址。可以直接调用。但是因为类型的原因,不能把成员函数的地址直接给一个普通的函数指针。成员函数指针的类型是classname::ptr的形式,而且是thiscall,thiscall是c++保留关键字,所以无法直接给一个普通的函数指针,用强制转换也不行。因为c++不允许对函数指针类型做强制转换,所以我在上面的代码中用嵌入汇编,完成强制转换,通过调用,发现上面的理解是正确的。<BR>对于虚成员函数就比较麻烦。如果不用指针调用,编译器就直接把object的地址放到ecx中,其实也就是vtable的地址,然后在这个vtable上就可以找到正确的函数。如果通过指针调用,编译器无法保证这个指针以后会不会发生变化,也就是说这个指针变量,以后可能会指向这个class的其他成员函数,所以编译器一旦检测到这种&amp;classname::funcname的时候,就会生成一个vcall,然后把vcall的地址作为&amp;classname::funcname的结果返回。vcall其实指向的是一组代码,大概如下形式:<BR>mov eax,[ecx]<BR>call [eax+n]<BR>其中n是根据不同funcname在vtable中不同偏移决定的。前面说过,如果不通过指针调用,编译器可以根据函数名字找到偏移,但是通过指针,编译器就找不到名字了,找到的是一个地址,所以必须在地址上强制生成这个n.所以代码的作用就是在vtable,也就是[ecx]中,找到正确的函数。<BR>上面的结论是我调试出来的,大家可以在中间放断点,通过alt+8查看汇编代码,得到结论。<BR>同时c++标准没有规定编译器实现细节,上面的东西只对vc6 debug模式下有说明作用。
<br><a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p>
<hr size=1>
<blockquote><p>
<font color=red>答案被接受</font><br>回复者:紫君 回复日期:2003-10-16 19:05:19
<br>内容:可以领分吗?
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:xiongli 回复日期:2003-10-16 21:24:27
<br>内容:当然<BR>分从哪里来,偶就送到那里去
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:紫君 回复日期:2003-10-17 08:48:09
<br>内容:&lt;BLOCKQUOTE&gt;引用“第2楼”所言<BR>&lt;Q&gt;当然&nbsp;&nbsp;分从哪里来,偶就送到那里去&lt;/Q&gt;&lt;/BLOCKQUOTE&gt;<BR>赫赫.......礼尚往来,分会送还给你的<BR>
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:紫君 回复日期:2003-10-17 08:54:23
<br>内容:http://www.vchelp.net/cndevforum/subject_view.asp?subject_id=55521&amp;forum_id=
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:coolleo 回复日期:2003-10-17 08:56:30
<br>内容:赫赫有名的xiongli大侠好大方啊!!!!^_^
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:紫君 回复日期:2003-10-17 08:59:05
<br>内容:俺也很大方地,虽然俺不是大虾
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:市长先生 回复日期:2003-10-17 16:47:22
<br>内容:成员函数指针的类型是classname::ptr的形式,而且是thiscall,thiscall是c++保留关键字,所以无法直接给一个普通的函数指针,用强制转换也不行。<BR>我抗议:<BR>&nbsp;&nbsp; 可以用强转换赋值给普通指针。<BR><BR>class A<BR>{public:<BR>A(int t):_a(t){}<BR>const int _a;<BR>};<BR>int main()<BR>{<BR>A* pa=new A(5);<BR>int* pi;<BR>pi=reinterpret_cast&lt;int*&gt;(pa);<BR>*pi=7;<BR>cout&lt;&lt;pa-&gt;_a&lt;&lt;endl;<BR>}<BR>没有意外的话,输出为7,不仅把pa给了pi,而且把pa的常量成员_a也修改了.<BR>
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:xiongli 回复日期:2003-10-17 17:06:20
<br>内容:我没有试reinterpret_cast<BR>不知道可不可以。现在在实习,没有vc<BR>不过楼上的转换的不是函数指针
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:紫君 回复日期:2003-10-17 18:30:41
<br>内容:试了一下,结果输出为7<BR><BR>悄悄地问:xiongli,你在什么公司实习呀,做什么开发<BR>2003-10-17 18:35:40

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -