﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-不过是用Ms Tools的一个民工..-文章分类-Mfc</title><link>http://www.cppblog.com/IssacAsimoy/category/7465.html</link><description>人恒过，然后能改。困于心，衡于虑，而后作。</description><language>zh-cn</language><lastBuildDate>Wed, 13 Aug 2008 12:59:51 GMT</lastBuildDate><pubDate>Wed, 13 Aug 2008 12:59:51 GMT</pubDate><ttl>60</ttl><item><title>回调函数</title><link>http://www.cppblog.com/IssacAsimoy/articles/58760.html</link><dc:creator>IssAc</dc:creator><author>IssAc</author><pubDate>Wed, 13 Aug 2008 12:26:00 GMT</pubDate><guid>http://www.cppblog.com/IssacAsimoy/articles/58760.html</guid><wfw:comment>http://www.cppblog.com/IssacAsimoy/comments/58760.html</wfw:comment><comments>http://www.cppblog.com/IssacAsimoy/articles/58760.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/IssacAsimoy/comments/commentRss/58760.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/IssacAsimoy/services/trackbacks/58760.html</trackback:ping><description><![CDATA[<p>[转载内容,地址不详]<strong><br>简介<br><br></strong>　　对于很多初学者来说，往往觉得回调函数很神秘，很想知道回调函数的工作原理。本文将要解释什么是回调函数、它们有什么好处、为什么要使用它们等等问题，在开始之前，假设你已经熟知了函数指针。 <br><br>　　<strong>什么是回调函数？</strong><br><br>　　简而言之，回调函数就是一个通过函数指针调用的函数。如果你把函数的指针（地址）作为参数传递给另一个函数，当这个指针被用为调用它所指向的函数时，我们就说这是回调函数。<br><br>　　<strong>为什么要使用回调函数？</strong><br><br>　　因为可以把调用者与被调用者分开。调用者不关心谁是被调用者，所有它需知道的，只是存在一个具有某种特定原型、某些限制条件（如返回值为int）的被调用函数。<br><br>　　如果想知道回调函数在实际中有什么作用，先假设有这样一种情况，我们要编写一个库，它提供了某些排序算法的实现，如冒泡排序、快速排序、shell排序、shake排序等等，但为使库更加通用，不想在函数中嵌入排序逻辑，而让使用者来实现相应的逻辑；或者，想让库可用于多种数据类型（int、float、string），此时，该怎么办呢？可以使用函数指针，并进行回调。<br><br>　　回调可用于通知机制，例如，有时要在程序中设置一个计时器，每到一定时间，程序会得到相应的通知，但通知机制的实现者对我们的程序一无所知。而此时，就需有一个特定原型的函数指针，用这个指针来进行回调，来通知我们的程序事件已经发生。实际上，SetTimer() API使用了一个回调函数来通知计时器，而且，万一没有提供回调函数，它还会把一个消息发往程序的消息队列。<br><br>　　另一个使用回调机制的API函数是EnumWindow()，它枚举屏幕上所有的顶层窗口，为每个窗口调用一个程序提供的函数，并传递窗口的处理程序。如果被调用者返回一个值，就继续进行迭代，否则，退出。EnumWindow()并不关心被调用者在何处，也不关心被调用者用它传递的处理程序做了什么，它只关心返回值，因为基于返回值，它将继续执行或退出。<br><br>　　不管怎么说，回调函数是继续自C语言的，因而，在C++中，应只在与C代码建立接口，或与已有的回调接口打交道时，才使用回调函数。除了上述情况，在C++中应使用虚拟方法或函数符（functor），而不是回调函数。<br><br>　　<strong>一个简单的回调函数实现</strong><br><br>　　下面创建了一个sort.dll的动态链接库，它导出了一个名为CompareFunction的类型--typedef int (__stdcall *CompareFunction)(const byte*, const byte*)，它就是回调函数的类型。另外，它也导出了两个方法：Bubblesort()和Quicksort()，这两个方法原型相同，但实现了不同的排序算法。<br><br>
<table borderColor=#cccccc width="90%" align=center bgColor=#e7e9e9 border=1>
    <tbody>
        <tr>
            <td>void DLLDIR __stdcall Bubblesort(byte* array,int size,int elem_size,CompareFunction cmpFunc);<br><br>void DLLDIR __stdcall Quicksort(byte* array,int size,int elem_size,CompareFunction cmpFunc);</td>
        </tr>
    </tbody>
</table>
<br>　　这两个函数接受以下参数：<br><br>　　&#183;byte * array：指向元素数组的指针（任意类型）。<br><br>　　&#183;int size：数组中元素的个数。<br><br>　　&#183;int elem_size：数组中一个元素的大小，以字节为单位。<br><br>　　&#183;CompareFunction cmpFunc：带有上述原型的指向回调函数的指针。<br><br>　　这两个函数的会对数组进行某种排序，但每次都需决定两个元素哪个排在前面，而函数中有一个回调函数，其地址是作为一个参数传递进来的。对编写者来说，不必介意函数在何处实现，或它怎样被实现的，所需在意的只是两个用于比较的元素的地址，并返回以下的某个值（库的编写者和使用者都必须遵守这个约定）：<br><br>　　&#183;-1：如果第一个元素较小，那它在已排序好的数组中，应该排在第二个元素前面。<br><br>　　&#183;0：如果两个元素相等，那么它们的相对位置并不重要，在已排序好的数组中，谁在前面都无所谓。 <br><br>　　&#183;1：如果第一个元素较大，那在已排序好的数组中，它应该排第二个元素后面。<br><br>　　基于以上约定，函数Bubblesort()的实现如下，Quicksort()就稍微复杂一点：<br><br>
<table borderColor=#cccccc width="90%" align=center bgColor=#e7e9e9 border=1>
    <tbody>
        <tr>
            <td>void DLLDIR __stdcall Bubblesort(byte* array,int size,int elem_size,CompareFunction cmpFunc)<br>{<br>　for(int i=0; i &lt; size; i++)<br>　{<br>　　for(int j=0; j &lt; size-1; j++)<br>　　{<br>　　　//回调比较函数<br>　　　if(1 == (*cmpFunc)(array+j*elem_size,array+(j+1)*elem_size))<br>　　　{<br>　　　　//两个相比较的元素相交换<br>　　　　byte* temp = new byte[elem_size];<br>　　　　memcpy(temp, array+j*elem_size, elem_size);<br>　　　　memcpy(array+j*elem_size,array+(j+1)*elem_size,elem_size);<br>　　　　memcpy(array+(j+1)*elem_size, temp, elem_size);<br>　　　　delete [] temp;<br>　　　}<br>　　}<br>　}<br>}</td>
        </tr>
    </tbody>
</table>
<br>　　注意：因为实现中使用了memcpy()，所以函数在使用的数据类型方面，会有所局限。<br><br>　　对使用者来说，必须有一个回调函数，其地址要传递给Bubblesort()函数。下面有二个简单的示例，一个比较两个整数，而另一个比较两个字符串：<br><br>
<table borderColor=#cccccc width="90%" align=center bgColor=#e7e9e9 border=1>
    <tbody>
        <tr>
            <td>int __stdcall CompareInts(const byte* velem1, const byte* velem2)<br>{<br>　int elem1 = *(int*)velem1;<br>　int elem2 = *(int*)velem2;<br><br>　if(elem1 &lt; elem2)<br>　　return -1;<br>　if(elem1 &gt; elem2)<br>　　return 1;<br><br>　return 0;<br>}<br><br>int __stdcall CompareStrings(const byte* velem1, const byte* velem2)<br>{<br>　const char* elem1 = (char*)velem1;<br>　const char* elem2 = (char*)velem2;<br>　return strcmp(elem1, elem2);<br>}</td>
        </tr>
    </tbody>
</table>
<br>　　下面另有一个程序，用于测试以上所有的代码，它传递了一个有5个元素的数组给Bubblesort()和Quicksort()，同时还传递了一个指向回调函数的指针。<br><br>
<table borderColor=#cccccc width="90%" align=center bgColor=#e7e9e9 border=1>
    <tbody>
        <tr>
            <td>int main(int argc, char* argv[])<br>{<br>　int i;<br>　int array[] = {5432, 4321, 3210, 2109, 1098};<br><br>　cout &lt;&lt; "Before sorting ints with Bubblesort\n";<br>　for(i=0; i &lt; 5; i++)<br>　　cout &lt;&lt; array[i] &lt;&lt; '\n';<br><br>　Bubblesort((byte*)array, 5, sizeof(array[0]), &amp;CompareInts);<br><br>　cout &lt;&lt; "After the sorting\n";<br>　for(i=0; i &lt; 5; i++)<br>　　cout &lt;&lt; array[i] &lt;&lt; '\n';<br><br>　const char str[5][10] = {"estella","danielle","crissy","bo","angie"};<br><br>　cout &lt;&lt; "Before sorting strings with Quicksort\n";<br>　for(i=0; i &lt; 5; i++)<br>　　cout &lt;&lt; str[i] &lt;&lt; '\n';<br><br>　Quicksort((byte*)str, 5, 10, &amp;CompareStrings);<br><br>　cout &lt;&lt; "After the sorting\n";<br>　for(i=0; i &lt; 5; i++)<br>　　cout &lt;&lt; str[i] &lt;&lt; '\n';<br><br>　return 0;<br>}</td>
        </tr>
    </tbody>
</table>
<br>　　如果想进行降序排序（大元素在先），就只需修改回调函数的代码，或使用另一个回调函数，这样编程起来灵活性就比较大了。</p>
<p><strong>调用约定<br><br></strong>　　上面的代码中，可在函数原型中找到__stdcall，因为它以双下划线打头，所以它是一个特定于编译器的扩展，说到底也就是微软的实现。任何支持开发基于Win32的程序都必须支持这个扩展或其等价物。以__stdcall标识的函数使用了标准调用约定，为什么叫标准约定呢，因为所有的Win32 API（除了个别接受可变参数的除外）都使用它。标准调用约定的函数在它们返回到调用者之前，都会从堆栈中移除掉参数，这也是Pascal的标准约定。但在C/C++中，调用约定是调用者负责清理堆栈，而不是被调用函数；为强制函数使用C/C++调用约定，可使用__cdecl。另外，可变参数函数也使用C/C++调用约定。<br><br>　　Windows操作系统采用了标准调用约定（Pascal约定），因为其可减小代码的体积。这点对早期的Windows来说非常重要，因为那时它运行在只有640KB内存的电脑上。<br><br>　　如果你不喜欢__stdcall，还可以使用CALLBACK宏，它定义在windef.h中：<br><br>
<table borderColor=#cccccc width="90%" align=center bgColor=#e7e9e9 border=1>
    <tbody>
        <tr>
            <td>#define CALLBACK __stdcallor<br><br>#define CALLBACK PASCAL //而PASCAL在此被#defined成__stdcall</td>
        </tr>
    </tbody>
</table>
<br>　　<strong>作为回调函数的C++方法</strong><br><br>　　因为平时很可能会使用到C++编写代码，也许会想到把回调函数写成类中的一个方法，但先来看看以下的代码：<br><br>
<table borderColor=#cccccc width="90%" align=center bgColor=#e7e9e9 border=1>
    <tbody>
        <tr>
            <td>class CCallbackTester<br>{<br>　public:<br>　int CALLBACK CompareInts(const byte* velem1, const byte* velem2);<br>};<br><br>Bubblesort((byte*)array, 5, sizeof(array[0]),<br>&amp;CCallbackTester::CompareInts);</td>
        </tr>
    </tbody>
</table>
<br>　　如果使用微软的编译器，将会得到下面这个编译错误：<br><br>
<table borderColor=#cccccc width="90%" align=center bgColor=#e7e9e9 border=1>
    <tbody>
        <tr>
            <td>error C2664: 'Bubblesort' : cannot convert parameter 4 from 'int (__stdcall CCallbackTester::*)(const unsigned char *,const unsigned char *)' to 'int (__stdcall *)(const unsigned char *,const unsigned char *)' There is no context in which this conversion is possible</td>
        </tr>
    </tbody>
</table>
<br>　　这是因为非静态成员函数有一个额外的参数：this指针，这将迫使你在成员函数前面加上static。当然，还有几种方法可以解决这个问题，但限于篇幅，就不再论述了。<br><br><br>----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------<br></p>
<div class=postTitle><a class=postTitle2 id=viewpost1_TitleUrl href="http://www.cppblog.com/yuanyajie/archive/2007/03/30/20945.html"><u><font color=#800080>将类成员函数用做C回调函数</font></u></a> </div>
<p><font color=#0000ff>提出问题：</font> <br>回调函数是基于C编程的Windows SDK的技术，不是针对C++的，程序员可以将一个C函数直接作为回调函数，但是如果试图直接使用C++的成员函数作为回调函数将发生错误，甚至编译就不能通过。<br><font color=#0000ff>分析原因：</font><br>普通的C++成员函数都隐含了一个传递函数作为参数，亦即&#8220;this&#8221;指针，C++通过传递一个指向自身的指针给其成员函数从而实现程序函数可以访问C++的数据成员。这也可以理解为什么C++类的多个实例可以共享成员函数但是确有不同的数据成员。由于this指针的作用，使得将一个CALLBACK型的成员函数作为回调函数安装时就会因为隐含的this指针使得函数参数个数不匹配，从而导致回调函数安装失败<br><font color=#0000ff>解决方案：</font><br>一,不使用成员函数，直接使用<font color=#ff1493>普通C函数</font>，为了实现在C函数中可以访问类的成员变量，可以使用友元操作符(friend)，在C++中将该C函数说明为<font color=#ff1493>类的</font><font color=#ff1493>友元</font>即可。这种处理机制与普通的C编程中使用回调函数一样。<br>二,使用<font color=#ff1493>静态成员函数</font>，静态成员函数不使用this指针作为隐含参数，这样就可以作为回调函数了。静态成员函数具有两大特点：其一，可以在没有类实例的情况下使用；其二，只能访问静态成员变量和静态成员函数，不能访问非静态成员变量和非静态成员函数。由于在C++中使用类成员函数作为回调函数的目的就是为了访问所有的成员变量和成员函数，如果作不到这一点将不具有实际意义。我们通过使用静态成员函数对非静态成员函数<font color=#ff1493>包装</font>的办法来解决问题。类实例可以通过<font color=#ff1493>附加参数</font>或<font color=#ff1493>全局变量</font>的方式的方式传递到静态成员函数中。分别举例如下：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">1</span><span style="COLOR: #000000">，参数传递的方式<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;TClassA<br><img id=Codehighlighter1_58_229_Open_Image onclick="this.style.display='none'; Codehighlighter1_58_229_Open_Text.style.display='none'; Codehighlighter1_58_229_Closed_Image.style.display='inline'; Codehighlighter1_58_229_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_58_229_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_58_229_Closed_Text.style.display='none'; Codehighlighter1_58_229_Open_Image.style.display='inline'; Codehighlighter1_58_229_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_58_229_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_58_229_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_109_133_Open_Image onclick="this.style.display='none'; Codehighlighter1_109_133_Open_Text.style.display='none'; Codehighlighter1_109_133_Closed_Image.style.display='inline'; Codehighlighter1_109_133_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_109_133_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_109_133_Closed_Text.style.display='none'; Codehighlighter1_109_133_Open_Image.style.display='inline'; Codehighlighter1_109_133_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Display(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;text)&nbsp;</span><span id=Codehighlighter1_109_133_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_109_133_Open_Text><span style="COLOR: #000000">{&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;text&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;&nbsp;}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Wrapper_To_Call_Display(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;pt2Object,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;text);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;more<img src="http://www.cppblog.com/Images/dot.gif">.</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;静态包装函数，能够调用成员函数Display(),本身做为回调函数来使用</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;TClassA::Wrapper_To_Call_Display(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;pt2Object,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_351_472_Open_Image onclick="this.style.display='none'; Codehighlighter1_351_472_Open_Text.style.display='none'; Codehighlighter1_351_472_Closed_Image.style.display='inline'; Codehighlighter1_351_472_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_351_472_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_351_472_Closed_Text.style.display='none'; Codehighlighter1_351_472_Open_Image.style.display='inline'; Codehighlighter1_351_472_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_351_472_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_351_472_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;显式类型转换</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TClassA</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;mySelf&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(TClassA</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)&nbsp;pt2Object;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;调用普通成员函数</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mySelf</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">Display(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;回调函数的宿主,在这里回调用函数被使用</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;DoItA(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;pt2Object,&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pt2Function)(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;pt2Object,&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;text))<br><img id=Codehighlighter1_585_683_Open_Image onclick="this.style.display='none'; Codehighlighter1_585_683_Open_Text.style.display='none'; Codehighlighter1_585_683_Closed_Image.style.display='inline'; Codehighlighter1_585_683_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_585_683_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_585_683_Closed_Text.style.display='none'; Codehighlighter1_585_683_Open_Image.style.display='inline'; Codehighlighter1_585_683_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_585_683_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_585_683_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;使用回调函数</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pt2Function(pt2Object,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">hi,&nbsp;i'm&nbsp;calling&nbsp;back&nbsp;using&nbsp;a&nbsp;argument&nbsp;;-)</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;执行示例</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Callback_Using_Argument()<br><img id=Codehighlighter1_734_821_Open_Image onclick="this.style.display='none'; Codehighlighter1_734_821_Open_Text.style.display='none'; Codehighlighter1_734_821_Closed_Image.style.display='inline'; Codehighlighter1_734_821_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_734_821_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_734_821_Closed_Text.style.display='none'; Codehighlighter1_734_821_Open_Image.style.display='inline'; Codehighlighter1_734_821_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_734_821_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_734_821_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TClassA&nbsp;objA;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DoItA((</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">objA,&nbsp;TClassA::Wrapper_To_Call_Display);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">2</span><span style="COLOR: #000000">，全局变量的方式<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;pt2Object;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;全局变量,可以指向任意对象</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;TClassB<br><img id=Codehighlighter1_102_239_Open_Image onclick="this.style.display='none'; Codehighlighter1_102_239_Open_Text.style.display='none'; Codehighlighter1_102_239_Closed_Image.style.display='inline'; Codehighlighter1_102_239_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_102_239_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_102_239_Closed_Text.style.display='none'; Codehighlighter1_102_239_Open_Image.style.display='inline'; Codehighlighter1_102_239_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_102_239_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_102_239_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_153_177_Open_Image onclick="this.style.display='none'; Codehighlighter1_153_177_Open_Text.style.display='none'; Codehighlighter1_153_177_Closed_Image.style.display='inline'; Codehighlighter1_153_177_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_153_177_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_153_177_Closed_Text.style.display='none'; Codehighlighter1_153_177_Open_Image.style.display='inline'; Codehighlighter1_153_177_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Display(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;text)&nbsp;</span><span id=Codehighlighter1_153_177_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_153_177_Open_Text><span style="COLOR: #000000">{&nbsp;cout&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;text&nbsp;</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">&nbsp;endl;&nbsp;}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Wrapper_To_Call_Display(</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;text);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;静态的包装函数</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;TClassB::Wrapper_To_Call_Display(</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_315_422_Open_Image onclick="this.style.display='none'; Codehighlighter1_315_422_Open_Text.style.display='none'; Codehighlighter1_315_422_Closed_Image.style.display='inline'; Codehighlighter1_315_422_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_315_422_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_315_422_Closed_Text.style.display='none'; Codehighlighter1_315_422_Open_Image.style.display='inline'; Codehighlighter1_315_422_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_315_422_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_315_422_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">需要保证全局变量值的正确性</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TClassB</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;mySelf&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(TClassB</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)&nbsp;pt2Object;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mySelf</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">Display(</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;回调用函数的宿主,在这里回调用函数被使用</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;DoItB(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">pt2Function)(</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;text))<br><img id=Codehighlighter1_502_592_Open_Image onclick="this.style.display='none'; Codehighlighter1_502_592_Open_Text.style.display='none'; Codehighlighter1_502_592_Closed_Image.style.display='inline'; Codehighlighter1_502_592_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_502_592_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_502_592_Closed_Text.style.display='none'; Codehighlighter1_502_592_Open_Image.style.display='inline'; Codehighlighter1_502_592_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_502_592_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_502_592_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pt2Function(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">hi,&nbsp;i'm&nbsp;calling&nbsp;back&nbsp;using&nbsp;a&nbsp;global&nbsp;;-)</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;make&nbsp;callback</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;执行示例</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Callback_Using_Global()<br><img id=Codehighlighter1_641_748_Open_Image onclick="this.style.display='none'; Codehighlighter1_641_748_Open_Text.style.display='none'; Codehighlighter1_641_748_Closed_Image.style.display='inline'; Codehighlighter1_641_748_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_641_748_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_641_748_Closed_Text.style.display='none'; Codehighlighter1_641_748_Open_Image.style.display='inline'; Codehighlighter1_641_748_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_641_748_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_641_748_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TClassB&nbsp;objB;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pt2Object&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">)&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">objB;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DoItB(TClassB::Wrapper_To_Call_Display);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p>&nbsp;</p>
<p>注意：通过上面两种方法的比较可以看出，第2种方法中静态包装函数可以和普通成员函数保持签名一致，当回调函数的宿主<font color=#ff1493>接口不能改变</font>时，这种方法<font color=#ff1493>特别有用</font>。但因为使用了全局变量，也不是一个好的设计。</p>
<img src ="http://www.cppblog.com/IssacAsimoy/aggbug/58760.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/IssacAsimoy/" target="_blank">IssAc</a> 2008-08-13 20:26 <a href="http://www.cppblog.com/IssacAsimoy/articles/58760.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>__cdecl __fastcall与 __stdcall </title><link>http://www.cppblog.com/IssacAsimoy/articles/58757.html</link><dc:creator>IssAc</dc:creator><author>IssAc</author><pubDate>Wed, 13 Aug 2008 11:41:00 GMT</pubDate><guid>http://www.cppblog.com/IssacAsimoy/articles/58757.html</guid><wfw:comment>http://www.cppblog.com/IssacAsimoy/comments/58757.html</wfw:comment><comments>http://www.cppblog.com/IssacAsimoy/articles/58757.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/IssacAsimoy/comments/commentRss/58757.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/IssacAsimoy/services/trackbacks/58757.html</trackback:ping><description><![CDATA[<p>[转载内容,地址不详] <br>Visual C++ Compiler Options可以指定的Calling Convention有 3种：<br>　　/Gd /Gr /Gz<br>　　这三个参数决定了：<br>　　1.函数参数以何种顺序入栈，右到左还是左到右。<br>　　2.在函数运行完后，是调用函数还是被调用函数清理入栈的参数。<br>　　3.在编译时函数名字是如何转换的。</p>
<p>　　下面我们分别详细介绍：<br>　　1./Gd<br>　　这是编译器默认的转换模式，对一般函数使用 C的函数调用转换方式__cdecl，但是对于C++ 成员函数和前面修饰了__stdcall __fastcall的函数除外。<br>　　2./Gr<br>　　对于一般函数使用__fastcall函数调用转换方式，所有使用__fastcall的函数必须要有函数原形。但对于C++ 成员函数和前面修饰了__cdecl __stdcall 的函数除外。<br>　　3./Gz<br>　　对于所有 C函数使用__stdcall函数调用转换方式，但对于可变参数的 C函数以及用__cdecl __fastcall修饰过的函数和C++ 成员函数除外。所有用__stdcall修饰的函数必须有函数原形。<br>　　事实上，对于x86系统，C++ 成员函数的调用方式有点特别，将成员函数的this<br>指针放入ECX，所有函数参数从右向左入栈，被调用的成员函数负责清理入栈的<br>参数。对于可变参数的成员函数，始终使用__cdecl的转换方式。<br>　　下面该进入主题，分别讲一下这三种函数调用转换方式有什么区别：<br>　　1.__cdecl<br>　　这是编译器默认的函数调用转换方式，它可以处理可变参数的函数调用。参数的入栈顺序是从右向左。在函数运行结束后，由调用函数负责清理入栈的参数。在编译时，在每个函数前面加上下划线(_)，没有函数名大小写的转换。即_functionname<br>　　每一个调用它的函数都包含清空堆栈的代码，所以产生的可执行文件大小会比调用_stdcall函数的大。函数采用从右到左的压栈方式。注意：对于可变参数的成员函数，始终使用__cdecl的转换方式。 <br>　　2.__fastcall<br>　　有一些函数调用的参数被放入ECX，EDX中，而其它参数从右向左入栈。被调用函数在它将要返回时负责清理入栈的参数。在内嵌汇编语言的时候，需要注意寄存器的使用，以免与编译器使用的产生冲突。函数名字的转换是：@functionname@number没有函数名大小写的转换，number表示函数参数的字节数。由于有一些参数不&nbsp;需要入栈，所以这种转换方式会在一定程度上提高函数调用的速度。<br>　　3.__stdcall<br>　　函数参数从右向左入栈，被调用函数负责入栈参数的清理工作。函数名转换格式如下：<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#95;&#102;&#117;&#110;&#99;&#116;&#105;&#111;&#110;&#110;&#97;&#109;&#101;&#64;&#110;&#117;&#109;&#98;&#101;&#114;"><u><font color=#0000ff>_functionname@number</font></u></a><br>　　下面我们亲自写一个程序，看看各种不同的调用在编译后有什么区别，我们的被调&nbsp;用函数如下：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;function(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;a,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;b)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;a&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;b;<br>}<br></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;function(</span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">20</span><span style="COLOR: #000000">);<br>}</span></div>
<p>1.__cdecl</p>
<p>_function<br>push&nbsp;&nbsp;&nbsp; ebp<br>mov&nbsp;&nbsp;&nbsp;&nbsp; ebp, esp<br>mov&nbsp;&nbsp;&nbsp;&nbsp; eax, [ebp+8]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;参数1<br>add&nbsp;&nbsp;&nbsp;&nbsp; eax, [ebp+C]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;加上参数2<br>pop&nbsp;&nbsp;&nbsp;&nbsp; ebp<br>retn<br>_main<br>push&nbsp;&nbsp;&nbsp; ebp<br>mov&nbsp;&nbsp;&nbsp;&nbsp; ebp, esp<br>push&nbsp;&nbsp;&nbsp; 14h&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;参数 2入栈<br>push&nbsp;&nbsp;&nbsp; 0Ah&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;参数 1入栈<br>call&nbsp;&nbsp;&nbsp; _function&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;调用函数<br>add&nbsp;&nbsp;&nbsp;&nbsp; esp, 8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;修正栈<br>xor&nbsp;&nbsp;&nbsp;&nbsp; eax, eax<br>pop&nbsp;&nbsp;&nbsp;&nbsp; ebp<br>retn</p>
<p>2.__fastcall</p>
<p>@function@8<br>push&nbsp;&nbsp;&nbsp; ebp<br>mov&nbsp;&nbsp;&nbsp;&nbsp; ebp, esp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;保存栈指针<br>sub&nbsp;&nbsp;&nbsp;&nbsp; esp, 8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;多了两个局部变量<br>mov&nbsp;&nbsp;&nbsp;&nbsp; [ebp-8], edx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;保存参数 2<br>mov&nbsp;&nbsp;&nbsp;&nbsp; [ebp-4], ecx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;保存参数 1<br>mov&nbsp;&nbsp;&nbsp;&nbsp; eax, [ebp-4]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;参数 1<br>add&nbsp;&nbsp;&nbsp;&nbsp; eax, [ebp-8]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;加上参数 2<br>mov&nbsp;&nbsp;&nbsp;&nbsp; esp, ebp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;修正栈<br>pop&nbsp;&nbsp;&nbsp;&nbsp; ebp<br>retn<br>_main<br>push&nbsp;&nbsp;&nbsp; ebp<br>mov&nbsp;&nbsp;&nbsp;&nbsp; ebp, esp<br>mov&nbsp;&nbsp;&nbsp;&nbsp; edx, 14h&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;参数 2给EDX<br>mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, 0Ah&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;参数 1给ECX<br>call&nbsp;&nbsp;&nbsp; @function@8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;调用函数<br>xor&nbsp;&nbsp;&nbsp;&nbsp; eax, eax<br>pop&nbsp;&nbsp;&nbsp;&nbsp; ebp<br>retn</p>
<p>3.__stdcall</p>
<p><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#95;&#102;&#117;&#110;&#99;&#116;&#105;&#111;&#110;&#64;&#56;"><u><font color=#0000ff>_function@8</font></u></a><br>push&nbsp;&nbsp;&nbsp; ebp<br>mov&nbsp;&nbsp;&nbsp;&nbsp; ebp, esp<br>mov&nbsp;&nbsp;&nbsp;&nbsp; eax, [ebp]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;参数 1<br>add&nbsp;&nbsp;&nbsp;&nbsp; eax, [ebp+C]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;加上参数 2<br>pop&nbsp;&nbsp;&nbsp;&nbsp; ebp<br>retn&nbsp;&nbsp;&nbsp; 8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;修复栈<br>_main<br>push&nbsp;&nbsp;&nbsp; ebp<br>mov&nbsp;&nbsp;&nbsp;&nbsp; ebp, esp<br>push&nbsp;&nbsp;&nbsp; 14h&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;参数 2入栈<br>push&nbsp;&nbsp;&nbsp; 0Ah&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;参数 1入栈<br>call&nbsp;&nbsp;&nbsp; <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#95;&#102;&#117;&#110;&#99;&#116;&#105;&#111;&#110;&#64;&#56;"><u><font color=#0000ff>_function@8</font></u></a>　　　　;函数调用<br>xor&nbsp;&nbsp;&nbsp;&nbsp; eax, eax<br>pop&nbsp;&nbsp;&nbsp;&nbsp; ebp<br>retn<br>可见上述三种方法各有各的特点，而且_main必须是__cdecl，一般WIN32的函数都是__stdcall。而且在Windef.h中有如下的定义：<br>#define CALLBACK __stdcall<br>#define WINAPI　 __stdcall <br><br><br>　　补：<br>　　C++编译时函数名修饰约定规则： <br>　　__stdcall调用约定： <br>　　1)、以"?"标识函数名的开始，后跟函数名； <br>　　2)、函数名后面以"@@YG"标识参数表的开始，后跟参数表； <br>　　3)、参数表以代号表示： <br>　　X--void ， <br>　　D--char， <br>　　E--unsigned char， <br>　　F--short， <br>　　H--int， <br>　　I--unsigned int， <br>　　J--long， <br>　　K--unsigned long， <br>　　M--float， <br>　　N--double， <br>　　_N--bool， <br>　　PA--表示指针，后面的代号表明指针类型，如果相同类型的指针连续出现，以"0"代替，一个"0"代表一次重复； <br>　　4)、参数表的第一项为该函数的返回值类型，其后依次为参数的数据类型,指针标识在其所指数据类型前； <br>　　5)、参数表后以"@Z"标识整个名字的结束，如果该函数无参数，则以"Z"标识结束。 <br>　　其格式为"<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#102;&#117;&#110;&#99;&#116;&#105;&#111;&#110;&#110;&#97;&#109;&#101;&#64;&#64;&#89;&#71;&#42;&#42;&#42;&#42;&#42;&#64;&#90;"><u><font color=#0000ff>?functionname@@YG*****@Z</font></u></a>"或"<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#63;&#102;&#117;&#110;&#99;&#116;&#105;&#111;&#110;&#110;&#97;&#109;&#101;&#64;&#64;&#89;&#71;&#42;&#88;&#90;"><u><font color=#0000ff>?functionname@@YG*XZ</font></u></a>"，例如 　　int Test1(char *var1,unsigned long)-----&#8220;?Test1@@YGHPADK@Z&#8221; 　　void Test2() <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#45;&#45;&#45;&#45;&#45;&#8220;&#63;&#84;&#101;&#115;&#116;&#50;&#64;&#64;&#89;&#71;&#88;&#88;&#90;"><u><font color=#0000ff>-----&#8220;?Test2@@YGXXZ</font></u></a>&#8221; <br>　　__cdecl调用约定： <br>　　规则同上面的_stdcall调用约定，只是参数表的开始标识由上面的"@@YG"变为"@@YA"。 <br>　　__fastcall调用约定： <br>　　规则同上面的_stdcall调用约定，只是参数表的开始标识由上面的"@@YG"变为"@@YI"。 <br>　　VC++对函数的省缺声明是"__cedcl",将只能被C/C++调用. <br>　　注意： <br>　　1、_beginthread需要__cdecl的线程函数地址，_beginthreadex和CreateThread需要__stdcall的线程函数地址。 <br>　　2、一般WIN32的函数都是__stdcall。而且在Windef.h中有如下的定义： <br>　　#define CALLBACK __stdcall <br>　　#define WINAPI　 __stdcall <br>　　3、extern "C" _declspec(dllexport) int __cdecl Add(int a, int b); <br>　　typedef int (__cdecl*FunPointer)(int a, int b); <br>　　修饰符的书写顺序如上。 <br>　　4、 extern "C"的作用：如果Add(int a, int b)是在c语言编译器编译，而在c++文件使用，则需要在c++文件中声明：extern "C" Add(int a, int b)，因为c编译器和c++编译器对函数名的解释不一样（c++编译器解释函数名的时候要考虑函数参数，这样是了方便函数重载，而在c语言中不存在函数重 载的问题），使用extern "C"，实质就是告诉c++编译器，该函数是c库里面的函数。如果不使用extern "C"则会出现链接错误。 <br>　　一般象如下使用： <br>　　#ifdef _cplusplus <br>　　#define EXTERN_C extern "C" <br>　　#else <br>　　#define EXTERN_C extern <br>　　#endif <br>　　#ifdef _cplusplus <br>　　extern "C"{ <br>　　#endif <br>　　EXTERN_C int func(int a, int b); <br>　　#ifdef _cplusplus <br>　　} <br>　　#endif <br>　　5、MFC提供了一些宏，可以使用AFX_EXT_CLASS来代替__declspec(DLLexport)，并修饰类名，从而导出类，AFX_API_EXPORT来修饰函数，AFX_DATA_EXPORT来修饰变量 <br>　　AFX_CLASS_IMPORT：__declspec(DLLexport) <br>　　AFX_API_IMPORT：__declspec(DLLexport) <br>　　AFX_DATA_IMPORT：__declspec(DLLexport) <br>　　AFX_CLASS_EXPORT：__declspec(DLLexport) <br>　　AFX_API_EXPORT：__declspec(DLLexport) <br>　　AFX_DATA_EXPORT：__declspec(DLLexport) <br>　　AFX_EXT_CLASS：#ifdef _AFXEXT <br>　　AFX_CLASS_EXPORT <br>　　#else <br>　　AFX_CLASS_IMPORT <br>　　6、 DLLMain负责初始化(Initialization)和结束(Termination)工作，每当一个新的进程或者该进程的新的线程访问DLL时， 或者访问DLL的每一个进程或者线程不再使用DLL或者结束时，都会调用DLLMain。但是，使用TerminateProcess或 TerminateThread结束进程或者线程，不会调用DLLMain。 <br>　　7、一个DLL在内存中只有一个实例 <br>　　DLL程序和调用其输出函数的程序的关系： <br>　　1)、DLL与进程、线程之间的关系 <br>　　DLL模块被映射到调用它的进程的虚拟地址空间。 <br>　　DLL使用的内存从调用进程的虚拟地址空间分配，只能被该进程的线程所访问。 <br>　　DLL的句柄可以被调用进程使用；调用进程的句柄可以被DLL使用。 <br>　　DLLDLL可以有自己的数据段，但没有自己的堆栈，使用调用进程的栈，与调用它的应用程序相同的堆栈模式。 <br>　　2)、关于共享数据段 <br>　　DLL 定义的全局变量可以被调用进程访问；DLL可以访问调用进程的全局数据。使用同一DLL的每一个进程都有自己的DLL全局变量实例。如果多个线程并发访问 同一变量，则需要使用同步机制；对一个DLL的变量，如果希望每个使用DLL的线程都有自己的值，则应该使用线程局部存储(TLS，Thread Local Strorage)<br></p>
<img src ="http://www.cppblog.com/IssacAsimoy/aggbug/58757.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/IssacAsimoy/" target="_blank">IssAc</a> 2008-08-13 19:41 <a href="http://www.cppblog.com/IssacAsimoy/articles/58757.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[Demo] -- DataTransformTool</title><link>http://www.cppblog.com/IssacAsimoy/articles/58271.html</link><dc:creator>IssAc</dc:creator><author>IssAc</author><pubDate>Thu, 07 Aug 2008 11:02:00 GMT</pubDate><guid>http://www.cppblog.com/IssacAsimoy/articles/58271.html</guid><wfw:comment>http://www.cppblog.com/IssacAsimoy/comments/58271.html</wfw:comment><comments>http://www.cppblog.com/IssacAsimoy/articles/58271.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/IssacAsimoy/comments/commentRss/58271.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/IssacAsimoy/services/trackbacks/58271.html</trackback:ping><description><![CDATA[<p>自己动手做的一个简单的工具,可以用来计算输入的日期<br><br>1.一年中的第多少天 <br>2.是什么星座<br>3.这一天星期几<br>4.分割栏操作的复习 <br><br><img height=440 alt="" src="http://photo1.9you.com/pic/userphoto/61/13/2036996113/kvri1218106772.jpg" width=489 border=0></p>
<p>&nbsp;</p>
<p>初学MFC的一个小练习 ..<br>下面留个链接 .供以后回顾 ..~</p>
<a href="http://www.cppblog.com/Files/IssacAsimoy/DataTransformTool.rar">/Files/IssacAsimoy/DataTransformTool.rar</a><br><br>生成的exe文件居然不能在别人的机子上运行,提示缺少库文件 ..~<br><br>解决一.<br>project-&gt;settings-&gt;general &nbsp; <br>&nbsp; 将USE&nbsp;&nbsp; MFC &nbsp; in &nbsp; a &nbsp; shared &nbsp; DLL &nbsp; 改为Use &nbsp; MFC &nbsp; in &nbsp; a &nbsp; static &nbsp; libery &nbsp; <br>&nbsp; 左边选release，再编译<br><br>解决二.<br>还有办法就是使用.net或是Install &nbsp; Shell来把这个这个程序给打包出来. &nbsp; <br>&nbsp; 这是最正式的方式.<br><br>
<img src ="http://www.cppblog.com/IssacAsimoy/aggbug/58271.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/IssacAsimoy/" target="_blank">IssAc</a> 2008-08-07 19:02 <a href="http://www.cppblog.com/IssacAsimoy/articles/58271.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《MFCWindows程序设计》--Hello MFC</title><link>http://www.cppblog.com/IssacAsimoy/articles/57378.html</link><dc:creator>IssAc</dc:creator><author>IssAc</author><pubDate>Mon, 28 Jul 2008 13:30:00 GMT</pubDate><guid>http://www.cppblog.com/IssacAsimoy/articles/57378.html</guid><wfw:comment>http://www.cppblog.com/IssacAsimoy/comments/57378.html</wfw:comment><comments>http://www.cppblog.com/IssacAsimoy/articles/57378.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/IssacAsimoy/comments/commentRss/57378.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/IssacAsimoy/services/trackbacks/57378.html</trackback:ping><description><![CDATA[<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #008000">//</span><span style="COLOR: #008000">hello.h</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;CMyApp:</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;CWinApp<br><img id=Codehighlighter1_38_78_Open_Image onclick="this.style.display='none'; Codehighlighter1_38_78_Open_Text.style.display='none'; Codehighlighter1_38_78_Closed_Image.style.display='inline'; Codehighlighter1_38_78_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_38_78_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_38_78_Closed_Text.style.display='none'; Codehighlighter1_38_78_Open_Image.style.display='inline'; Codehighlighter1_38_78_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_38_78_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_38_78_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;BOOL&nbsp;InitInstance();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;CMainWindow:</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;CFrameWnd<br><img id=Codehighlighter1_117_203_Open_Image onclick="this.style.display='none'; Codehighlighter1_117_203_Open_Text.style.display='none'; Codehighlighter1_117_203_Closed_Image.style.display='inline'; Codehighlighter1_117_203_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_117_203_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_117_203_Closed_Text.style.display='none'; Codehighlighter1_117_203_Open_Image.style.display='inline'; Codehighlighter1_117_203_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_117_203_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_117_203_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;CMainWindow();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;afx_msg&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;OnPaint();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;DECLARE_MESSAGE_MAP()<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;</span></div>
<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">afxwin.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Hello.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>CMyApp&nbsp;myApp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>BOOL&nbsp;CMyApp::InitInstance()<br><img id=Codehighlighter1_83_194_Open_Image onclick="this.style.display='none'; Codehighlighter1_83_194_Open_Text.style.display='none'; Codehighlighter1_83_194_Closed_Image.style.display='inline'; Codehighlighter1_83_194_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_83_194_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_83_194_Closed_Text.style.display='none'; Codehighlighter1_83_194_Open_Image.style.display='inline'; Codehighlighter1_83_194_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_83_194_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_83_194_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;m_pMainWnd</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;CMainWindow;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;m_pMainWnd</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">ShowWindow(m_nCmdShow);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;m_pMainWnd</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">UpdateWindow();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;TRUE;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>BEGIN_MESSAGE_MAP&nbsp;(CMainWindow,&nbsp;CFrameWnd)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;ON_WM_PAINT&nbsp;()<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>END_MESSAGE_MAP&nbsp;()<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>CMainWindow::CMainWindow()<br><img id=Codehighlighter1_306_351_Open_Image onclick="this.style.display='none'; Codehighlighter1_306_351_Open_Text.style.display='none'; Codehighlighter1_306_351_Closed_Image.style.display='inline'; Codehighlighter1_306_351_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_306_351_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_306_351_Closed_Text.style.display='none'; Codehighlighter1_306_351_Open_Image.style.display='inline'; Codehighlighter1_306_351_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_306_351_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_306_351_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Create(NULL,_T(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">The&nbsp;Hello&nbsp;Application</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">));<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;CMainWindow::OnPaint()<br><img id=Codehighlighter1_382_515_Open_Image onclick="this.style.display='none'; Codehighlighter1_382_515_Open_Text.style.display='none'; Codehighlighter1_382_515_Closed_Image.style.display='inline'; Codehighlighter1_382_515_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_382_515_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_382_515_Closed_Text.style.display='none'; Codehighlighter1_382_515_Open_Image.style.display='inline'; Codehighlighter1_382_515_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_382_515_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_382_515_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;CPaintDC&nbsp;dc(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;CRect&nbsp;rect;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;GetClientRect(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">rect);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;dc.DrawText(_T(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Hello,MFC</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">),</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">rect,DT_SINGLELINE</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">DT_CENTER</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">DT_VCENTER);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<img src ="http://www.cppblog.com/IssacAsimoy/aggbug/57378.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/IssacAsimoy/" target="_blank">IssAc</a> 2008-07-28 21:30 <a href="http://www.cppblog.com/IssacAsimoy/articles/57378.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>