﻿<?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++博客-Just enjoy programming-随笔分类-c/c++</title><link>http://www.cppblog.com/tankzhouqiang/category/16137.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 15 May 2014 03:24:12 GMT</lastBuildDate><pubDate>Thu, 15 May 2014 03:24:12 GMT</pubDate><ttl>60</ttl><item><title>skiplist</title><link>http://www.cppblog.com/tankzhouqiang/archive/2014/05/11/206903.html</link><dc:creator>周强</dc:creator><author>周强</author><pubDate>Sun, 11 May 2014 15:03:00 GMT</pubDate><guid>http://www.cppblog.com/tankzhouqiang/archive/2014/05/11/206903.html</guid><wfw:comment>http://www.cppblog.com/tankzhouqiang/comments/206903.html</wfw:comment><comments>http://www.cppblog.com/tankzhouqiang/archive/2014/05/11/206903.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tankzhouqiang/comments/commentRss/206903.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tankzhouqiang/services/trackbacks/206903.html</trackback:ping><description><![CDATA[&nbsp; &nbsp; 最近开始看leveldb的代码，周末看了下skiplist，详细介绍可以看http://blog.xiaoheshang.info/?p=248。基本原理就是空间换效率，多用几个指针来换取查找插入效率。自己也尝试写了下，对比了下leveldb的代码，内存控制没有leveldb实现的好，leveldb申请的时候基本上都是以block为单位申请空间，这样可以减少内存碎片，空间上每个节点就只会申请指定level个数的指针。以前一直记混淆 const char *p , char const *p 和char * const p的区别，前两者代码指向的内容不可变，后者指向的指针不可变。<img src ="http://www.cppblog.com/tankzhouqiang/aggbug/206903.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tankzhouqiang/" target="_blank">周强</a> 2014-05-11 23:03 <a href="http://www.cppblog.com/tankzhouqiang/archive/2014/05/11/206903.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Oracle Redo Log 机制 小结（转载）</title><link>http://www.cppblog.com/tankzhouqiang/archive/2013/01/08/197126.html</link><dc:creator>周强</dc:creator><author>周强</author><pubDate>Tue, 08 Jan 2013 11:20:00 GMT</pubDate><guid>http://www.cppblog.com/tankzhouqiang/archive/2013/01/08/197126.html</guid><wfw:comment>http://www.cppblog.com/tankzhouqiang/comments/197126.html</wfw:comment><comments>http://www.cppblog.com/tankzhouqiang/archive/2013/01/08/197126.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tankzhouqiang/comments/commentRss/197126.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tankzhouqiang/services/trackbacks/197126.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Oracle 的Redo 机制DB的一个重要机制，理解这个机制对DBA来说也是非常重要，之前的Blog里也林林散散的写了一些，前些日子看老白日记里也有说明，所以结合老白日记里的内容，对oracle 的整个Redo log 机制重新整理一下。&nbsp;一．Redo log 说明Oracle 的Online redo log 是为确保已经提交的事务不会丢失而建立的一个机制。 因为这种健全的机制，才能...&nbsp;&nbsp;<a href='http://www.cppblog.com/tankzhouqiang/archive/2013/01/08/197126.html'>阅读全文</a><img src ="http://www.cppblog.com/tankzhouqiang/aggbug/197126.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tankzhouqiang/" target="_blank">周强</a> 2013-01-08 19:20 <a href="http://www.cppblog.com/tankzhouqiang/archive/2013/01/08/197126.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++虚函数原理及实现（转载）</title><link>http://www.cppblog.com/tankzhouqiang/archive/2011/05/11/146186.html</link><dc:creator>周强</dc:creator><author>周强</author><pubDate>Wed, 11 May 2011 06:13:00 GMT</pubDate><guid>http://www.cppblog.com/tankzhouqiang/archive/2011/05/11/146186.html</guid><wfw:comment>http://www.cppblog.com/tankzhouqiang/comments/146186.html</wfw:comment><comments>http://www.cppblog.com/tankzhouqiang/archive/2011/05/11/146186.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tankzhouqiang/comments/commentRss/146186.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tankzhouqiang/services/trackbacks/146186.html</trackback:ping><description><![CDATA[虚函数是在类中被声明为virtual的成员函数，当编译器看到通过指针或引用调用此类函数时，对其执行晚绑定，即通过指针（或引用）指向的类的类型信息来决定该函数是哪个类的。通常此类指针或引用都声明为基类的，它可以指向基类或派生类的对象。<br>&nbsp;多态指同一个方法根据其所属的不同对象可以有不同的行为（根据自己理解，不知这么说是否严谨）。
<p>&nbsp;举个例子说明虚函数、多态、早绑定和晚绑定：<br>&nbsp;
李氏两兄妹（哥哥和妹妹）参加姓氏运动会（不同姓氏组队参加），哥哥男子项目比赛，妹妹参加女子项目比赛，开幕式有一个参赛队伍代表发言仪式，兄妹俩都想
去露露脸，可只能一人去，最终他们决定到时抓阄决定，而组委会也不反对，它才不关心是哥哥还是妹妹来发言，只要派一个姓李的来说两句话就行。运动会如期举
行，妹妹抓阄获得代表李家发言的机会，哥哥参加了男子项目比赛，妹妹参加了女子项目比赛。比赛结果就不是我们关心的了。<br>&nbsp;现在让我们来做个类比（只讨论与运动会相关的话题）：<br>&nbsp;（1）类的设计：<br>&nbsp;
李氏兄妹属于李氏家族，李氏是基类（这里还是抽象的纯基类），李氏又派生出两个子类（李氏男和李氏女），李氏男会所有男子项目的比赛（李氏男的成员函
数），李氏女会所有女子项目的比赛（李氏女的成员函数）。姓李的人都会发言（基类虚函数），李氏男和李氏女继承自李氏当然也会发言，只是男女说话声音不一
样，内容也会又差异，给人感觉不同（李氏男和李氏女分别重新定义发言这个虚函数）。李氏两兄妹就是李氏男和李氏女两个类的实体。<br>&nbsp;（2）程序设计：<br>&nbsp;李氏兄妹填写参赛报名表。<br>&nbsp;（3）编译：<br>&nbsp;
李氏兄妹的参赛报名表被上交给组委会（编译器），哥哥和妹妹分别参加男子和女子的比赛，组委会一看就明白了（早绑定），只是发言人选不明确，组委会看到报
名表上写的是&#8220;李家代表&#8221;（基类指针），组委会不能确定到底是谁，就做了个备注：如果是男的，就是哥哥李某某；如果是女的，就是妹妹李某某（晚绑定）。组
委会做好其它准备工作后，就等运动会开始了（编译完毕）。<br>&nbsp;（4）程序运行：<br>&nbsp;运动会开始了（程序开始运行），开幕式上我们听到了李家妹妹的发言，如果是哥哥运气好抓阄胜出，我们将听到哥哥的发言（多态）。然后就是看到兄妹俩参加比赛了。。。</p>
<p>&nbsp;但愿这个比喻说清楚了虚函数、多态、早绑定和晚绑定的概念和它们之间的关系。再说一下，早绑定指编译器在编译期间即知道对象的具体类型并确定此对象调用成员函数的确切地址；而晚绑定是根据指针所指对象的类型信息得到类的虚函数表指针进而确定调用成员函数的确切地址。<br>&nbsp;&nbsp;</p>
<p>&nbsp;2、揭密晚绑定的秘密</p>
<p>&nbsp;编译器到底做了什么实现的虚函数的晚绑定呢？我们来探个究竟。</p>
<p>&nbsp;
编译器对每个包含虚函数的类创建一个表（称为V&nbsp;TA&nbsp;B&nbsp;L&nbsp;E）。在V&nbsp;TA&nbsp;B&nbsp;L&nbsp;E中，编译器放置特定类的虚函数地址。在每个带有虚函数的类
中，编译器秘密地置一指针，称为v&nbsp;p&nbsp;o&nbsp;i&nbsp;n&nbsp;t&nbsp;e&nbsp;r（缩写为V&nbsp;P&nbsp;T&nbsp;R），指向这个对象的V&nbsp;TA&nbsp;B&nbsp;L&nbsp;E。<span style="color: #000000;"><span style="font-weight: bold; color: #ff0000;">通过基类指针做虚函数调 用时（也就是做多态调用时），编译器静态地插入取得这个V&nbsp;P&nbsp;T&nbsp;R，并在V&nbsp;TA&nbsp;B&nbsp;L&nbsp;E表中查找函数地址的代码，</span>这样就能调用正确的函数使晚捆绑发生。</span>为每个类设置V&nbsp;TA&nbsp;B&nbsp;L&nbsp;E、初始化V&nbsp;P&nbsp;T&nbsp;R、为虚函数调用插入代码，所有这些都是自动发生的，所以我们不必担心这些。利用虚函数， 这个对象的合适的函数就能被调用，哪怕在编译器还不知道这个对象的特定类型的情况下。（<span style="font-weight: bold; color: #ff0000;">《C++编程思想》</span>）</p>
<p><span style="font-weight: bold; color: #ff0000;">————这段话红色加粗部分似乎有点问题，我个人的理解看后面的总结。</span><br></p>
<p>&nbsp;在任何类中不存在显示的类型信息，可对象中必须存放类信息，否则类型不可能在运行时建立。那这个类信息是什么呢？我们来看下面几个类：</p>
<p>&nbsp;class&nbsp;no_virtual<br>&nbsp;{<br>&nbsp;public:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;fun1()&nbsp;const{}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;fun2()&nbsp;const&nbsp;{&nbsp;return&nbsp;a;&nbsp;}<br>&nbsp;private:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;a;<br>&nbsp;}</p>
<p>&nbsp;class&nbsp;one_virtual<br>&nbsp;{<br>&nbsp;public:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;void&nbsp;fun1()&nbsp;const{}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;fun2()&nbsp;const&nbsp;{&nbsp;return&nbsp;a;&nbsp;}<br>&nbsp;private:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;a;<br>&nbsp;}</p>
<p>&nbsp;class&nbsp;two_virtual<br>&nbsp;{<br>&nbsp;public:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;void&nbsp;fun1()&nbsp;const{}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;int&nbsp;&nbsp;fun2()&nbsp;const&nbsp;{&nbsp;return&nbsp;a;&nbsp;}<br>&nbsp;private:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;a;<br>&nbsp;}</p>
<p>&nbsp;以上三个类中：<br>&nbsp;no_virtual没有虚函数，sizeof(no_virtual)=4，类no_virtual的长度就是其成员变量整型a的长度；<br>&nbsp;one_virtual有一个虚函数，sizeof(one_virtual)=8；<br>&nbsp;two_virtual
有两个虚函数，sizeof(two_virtual)=8；&nbsp;有一个虚函数和两个虚函数的类的长度没有区别，其实它们的长度就是no_virtual的
长度加一个void指针的长度，它反映出，如果有一个或多个虚函数，编译器在这个结构中插入一个指针（&nbsp;V&nbsp;P&nbsp;T&nbsp;R）。在one_virtual&nbsp;和
two_virtual之间没有区别。这是因为V&nbsp;P&nbsp;T&nbsp;R指向一个存放地址的表，只需要一个指针，因为所有虚函数地址都包含在这个表中。</p>
<p>&nbsp;这个VPTR就可以看作类的类型信息。</p>
<p>&nbsp;那我们来看看编译器是怎么建立VPTR指向的这个虚函数表的。先看下面两个类：<br>&nbsp;class&nbsp;base<br>&nbsp;{<br>&nbsp;public:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;bfun(){}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;void&nbsp;vfun1(){}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;int&nbsp;vfun2(){}<br>&nbsp;private:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;a;<br>&nbsp;}</p>
<p>&nbsp;class&nbsp;derived&nbsp;:&nbsp;public&nbsp;base<br>&nbsp;{<br>&nbsp;public:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;dfun(){}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;void&nbsp;vfun1(){}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;int&nbsp;vfun3(){}<br>&nbsp;private:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;b;<br>&nbsp;}</p>
<p>&nbsp;两个类VPTR指向的虚函数表（VTABLE）分别如下：<br>&nbsp;base类<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;——————<br>&nbsp;VPTR——&gt;&nbsp;|&amp;base::vfun1&nbsp;|<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;——————<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&amp;base::vfun2&nbsp;|<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;——————<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;derived类<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;———————<br>&nbsp;VPTR——&gt;&nbsp;|&amp;derived::vfun1&nbsp;|<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;———————<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&amp;base::vfun2&nbsp;&nbsp;&nbsp;&nbsp;|<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;———————<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&amp;derived::vfun3&nbsp;|<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;———————<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;
每当创建一个包含有虚函数的类或从包含有虚函数的类派生一个类时，编译器就为这个类创建一个VTABLE，如上图所示。在这个表中，编译器放置了在这个类
中或在它的基类中所有已声明为virtual的函数的地址。如果在这个派生类中没有对在基类中声明为virtual的函数进行重新定义，编译器就使用基类
的这个虚函数地址。（在derived的VTABLE中，vfun2的入口就是这种情况。）然后编译器在这个类中放置VPTR。当使用简单继承时，对于每
个对象只有一个VPTR。<span style="font-weight: bold; color: #ff0000;">VPTR必须被初始化为指向相应的VTABLE，这在构造函数中发生。</span><br>&nbsp;一旦VPTR被初始化为指向相应的VTABLE，对象就"知道"它自己是什么类型。但只有当虚函数被调用时这种自我认知才有用。</p>
<p><span style="font-weight: bold; color: #ff0000;">个人总结如下：</span><br style="font-weight: bold; color: #ff0000;"><span style="font-weight: bold; color: #ff0000;">1、从包含虚函数的类派生一个类时，编译器就为该类创建一个VTABLE。其每一个表项是该类的虚函数地址。<br></span><span style="font-weight: bold; color: #ff0000;">2、在定义该派生类对象时，先调用其基类的构造函数，然后再初始化VPTR，最后再调用派生类的构造函数（</span>
从二进制的视野来看，所谓基类子类是一个大结构体，其中this指针开头的四个字节存放虚函数表头指针。执行子类的构造函数的时候，首先调用基类构造函
数，this指针作为参数，在基类构造函数中填入基类的vptr，然后回到子类的构造函数，填入子类的vptr，覆盖基类填入的vptr。如此以来完成
vptr的初始化。 <span style="font-weight: bold; color: #ff0000;">）<br></span>3、在实现动态绑定时，不能直接采用类对象，而一定要采用指针或者引用。因为采用类对象传值方式，有临时基类对象的产生，而采用指针，<span style="color: #ff0000; font-weight: bold;">则是通过指针来访问外部的派生类对象的VPTR来达到访问派生类虚函数的结果。 </span><br><span style="font-weight: bold; color: #ff0000;"><span style="font-weight: bold; color: #ff0000;"><br></span></span></p>
<p>&nbsp;VPTR
常常位于对象的开头，编译器能很容易地取到VPTR的值，从而确定VTABLE的位置。VPTR总指向VTABLE的开始地址，所有基类和它的子类的虚函
数地址（子类自己定义的虚函数除外）在VTABLE中存储的位置总是相同的，如上面base类和derived类的VTABLE中vfun1和vfun2
的地址总是按相同的顺序存储。编译器知道vfun1位于VPTR处，vfun2位于VPTR+1处，因此在用基类指针调用虚函数时，编译器首先获取指针指
向对象的类型信息（VPTR），然后就去调用虚函数。如一个base类指针pBase指向了一个derived对象，那pBase-&gt;vfun2
()被编译器翻译为&nbsp;VPTR+1&nbsp;的调用，因为虚函数vfun2的地址在VTABLE中位于索引为1的位置上。同理，pBase-&gt;vfun3
()被编译器翻译为&nbsp;VPTR+2的调用。这就是所谓的晚绑定。</p>
<p>&nbsp;我们来看一下虚函数调用的汇编代码，以加深理解。</p>
<p>&nbsp;void&nbsp;test(base*&nbsp;pBase)<br>&nbsp;{<br>&nbsp;&nbsp;pBase-&gt;vfun2();<br>&nbsp;}</p>
<p>&nbsp;int&nbsp;main(int&nbsp;argc,&nbsp;char*&nbsp;argv[])<br>&nbsp;{<br>&nbsp;&nbsp;derived&nbsp;td;<br>&nbsp;&nbsp;</p>
<p>&nbsp;<br>&nbsp;&nbsp;test(&amp;td);<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;return&nbsp;0;<br>&nbsp;}</p>
<p>&nbsp;derived&nbsp;td;编译生成的汇编代码如下：<br>&nbsp;&nbsp;mov&nbsp;DWORD&nbsp;PTR&nbsp;_td$[esp+24],&nbsp;OFFSET&nbsp;FLAT:??_7derived@@6B@&nbsp;;&nbsp;derived::`vftable'<br>&nbsp;&nbsp;由编译器的注释可知，此时PTR&nbsp;_td$[esp+24]中存储的就是derived类的VTABLE地址。<br>&nbsp;&nbsp;<br>&nbsp;test(&amp;td);编译生成的汇编代码如下：<br>&nbsp;&nbsp;lea&nbsp;eax,&nbsp;DWORD&nbsp;PTR&nbsp;_td$[esp+24]&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;mov&nbsp;DWORD&nbsp;PTR&nbsp;__$EHRec$[esp+32],&nbsp;0<br>&nbsp;&nbsp;push&nbsp;eax<br>&nbsp;&nbsp;call&nbsp;?test@@YAXPAVbase@@@Z&nbsp;&nbsp;&nbsp;;&nbsp;test&nbsp;<br>&nbsp;&nbsp;调用test函数时完成了如下工作：取对象td的地址，将其压栈，然后调用test。</p>
<p>&nbsp;pBase-&gt;vfun2();编译生成的汇编代码如下：<br>&nbsp;&nbsp;&nbsp;mov&nbsp;ecx,&nbsp;DWORD&nbsp;PTR&nbsp;_pBase$[esp-4]<br>&nbsp;&nbsp;mov&nbsp;eax,&nbsp;DWORD&nbsp;PTR&nbsp;[ecx]<br>&nbsp;&nbsp;jmp&nbsp;DWORD&nbsp;PTR&nbsp;[eax+4]<br>&nbsp;&nbsp;
首先从栈中取出pBase指针指向的对象地址赋给ecx，然后取对象开头的指针变量中的地址赋给eax，此时eax的值即为VPTR的值，也就是
VTABLE的地址。最后就是调用虚函数了，由于vfun2位于VTABLE的第二个位置，相当于&nbsp;VPTR+1，每个函数指针是4个字节长，所以最后的
调用被编译器翻译为&nbsp;jmp&nbsp;DWORD&nbsp;PTR&nbsp;[eax+4]。如果是调用pBase-&gt;vfun1()，这句就该被编译为
jmp&nbsp;DWORD&nbsp;PTR&nbsp;[eax]。<br>&nbsp;&nbsp;</p>
<p>&nbsp;现在应该对多态、虚函数、晚绑定有比较清楚的了解了吧。<br>&nbsp;</p>
转贴：http://blog.csdn.net/shenmea00000/archive/2007/10/31/1859762.aspx<img src ="http://www.cppblog.com/tankzhouqiang/aggbug/146186.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tankzhouqiang/" target="_blank">周强</a> 2011-05-11 14:13 <a href="http://www.cppblog.com/tankzhouqiang/archive/2011/05/11/146186.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++设计模式（九） 抽象工厂（Abstract Factory）</title><link>http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145613.html</link><dc:creator>周强</dc:creator><author>周强</author><pubDate>Tue, 03 May 2011 15:40:00 GMT</pubDate><guid>http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145613.html</guid><wfw:comment>http://www.cppblog.com/tankzhouqiang/comments/145613.html</wfw:comment><comments>http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145613.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tankzhouqiang/comments/commentRss/145613.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tankzhouqiang/services/trackbacks/145613.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 抽象工厂(Abstract Factory)模式看起来和前面看到的工厂方法很相似，只是它使用若干工厂方法(Factory Method）模式。每个工厂方法模式创建一个不同类型的对象。当创建一个工厂对象时，要决定将如何使用由那个工厂创建的所有对象。示例代码如下（假设要创建一个通用的游戏环境，并且希望它能支持不同类型的游戏）：<br>#include&lt;iostream&gt;<br>using namespace std;<br><br>class Obstacle<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; virtual void action()=0;<br>};<br><br>class Player<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; virtual void interactWith(Obstacle*)=0;<br>};<br><br>class Kitty: public Player<br>{<br>&nbsp;&nbsp;&nbsp; virtual void interactWith(Obstacle *ob)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cout&lt;&lt;"Kitty has encountered a";<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ob-&gt;action();<br>&nbsp;&nbsp;&nbsp; }<br>};<br><br>class KungFuGuy: public Player<br>{<br>&nbsp;&nbsp;&nbsp; virtual void interactWith(Obstacle* ob)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cout&lt;&lt;"KungFuGuy now battles against a";<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ob-&gt;action();<br>&nbsp;&nbsp;&nbsp; }<br>};<br>class Puzzle: public Obstacle<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; void action(){cout&lt;&lt;"Puzzle"&lt;&lt;endl;}<br>};<br><br>class NastyWeapon: public Obstacle<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; void action(){cout&lt;&lt;"NastyWeapon"&lt;&lt;endl;}<br>};<br><br>//the abstract factory<br>class GameElementFactory<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; virtual Player* makePlayer()=0;<br>&nbsp;&nbsp;&nbsp; virtual Obstacle* makeObstacle()=0;<br>};<br><br>//concreate factories<br>class KittiesAndPuzzles:public GameElementFactory<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; virtual Player* makePlayer(){return new Kitty;}<br>&nbsp;&nbsp;&nbsp; virtual Obstacle * makeObstacle(){return new Puzzle;}<br>};<br><br>class KillAndDismember:public GameElementFactory<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; virtual Player* makePlayer(){return new KungFuGuy;}<br>&nbsp;&nbsp;&nbsp; virtual Obstacle *makeObstacle(){return new NastyWeapon;}<br>};<br><br><br>class GameEnvironment<br>{<br>&nbsp;&nbsp;&nbsp; GameElementFactory* gef;<br>&nbsp;&nbsp;&nbsp; Player* p;<br>&nbsp;&nbsp;&nbsp; Obstacle *ob;<br>public:<br>&nbsp;&nbsp;&nbsp; GameEnvironment(GameElementFactory * factory)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; :gef(factory),p(factory-&gt;makePlayer()),ob(factory-&gt;makeObstacle()){}<br>&nbsp;&nbsp;&nbsp; void play(){p-&gt;interactWith(ob);}<br>&nbsp;&nbsp;&nbsp; ~GameEnvironment()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; delete p;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; delete ob;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; delete gef;<br>&nbsp;&nbsp;&nbsp; }<br>};<br><br>int main()<br>{<br>&nbsp;&nbsp;&nbsp; GameEnvironment<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; g1(new KittiesAndPuzzles),<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; g2(new KillAndDismember);<br>&nbsp;&nbsp;&nbsp; g1.play();<br>&nbsp;&nbsp;&nbsp; g2.play();<br>}<br><br>在此环境中，Player对象与Obstacle 对象交互，但是Player和Obstacle类型依赖于具体的游戏。可以选择特定的GameElementFactory来决定游戏的类型，然后GameEnvironment控制游戏的设置和进行。在本例中，游戏的设置和进行很简单，但是那些动作在很大程度上决定了游戏的结果。<br><br><img src ="http://www.cppblog.com/tankzhouqiang/aggbug/145613.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tankzhouqiang/" target="_blank">周强</a> 2011-05-03 23:40 <a href="http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145613.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++设计模式（八） 工厂模式：封装对象的创建</title><link>http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145610.html</link><dc:creator>周强</dc:creator><author>周强</author><pubDate>Tue, 03 May 2011 15:12:00 GMT</pubDate><guid>http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145610.html</guid><wfw:comment>http://www.cppblog.com/tankzhouqiang/comments/145610.html</wfw:comment><comments>http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145610.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tankzhouqiang/comments/commentRss/145610.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tankzhouqiang/services/trackbacks/145610.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 工厂模式不允许将创建对象的代码散布于整个系统。如果程序中所有需要创建对象的代码都转到这个工厂执行，那么在增加新对象时所要做的全部工作就是只需修改工厂。这种设计时众所周知<span style="font-family: courier new;"></span>的工厂方法模式的一种变体。由于每个面向对象应用程序都需要创建对象，并且由于人们可能通过添加新类型来扩展应用程序，工厂模式可能是所有设计模式中最有用的模式之一。实现工厂模式的一种方法就是在基类中定义一个静态成员函数，示例如下：<br>#include&lt;iostream&gt;<br>#include&lt;stdexcept&gt;<br>#include&lt;cstddef&gt;<br>#include&lt;string&gt;<br>#include&lt;vector&gt;<br><br>using namespace std;<br><br>class Shape<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; virtual void draw()=0;<br>&nbsp;&nbsp;&nbsp; virtual void erase()=0;<br>&nbsp;&nbsp;&nbsp; virtual ~Shape(){}<br>&nbsp;&nbsp;&nbsp; class BadShapeCreation :public logic_error<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; BadShapeCreation(string type):<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; logic_error("Cannot create type"+type){}<br>&nbsp;&nbsp;&nbsp; };<br>&nbsp;&nbsp;&nbsp; static Shape* factory(const string &amp;type)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throw(BadShapeCreation);<br>};<br><br>class Circle:public Shape<br>{<br>&nbsp;&nbsp;&nbsp; Circle(){}<br>&nbsp;&nbsp;&nbsp; friend class Shape;<br>public:<br>&nbsp;&nbsp;&nbsp; void draw(){cout&lt;&lt;"Circle::draw"&lt;&lt;endl;}<br>&nbsp;&nbsp;&nbsp; void erase(){cout&lt;&lt;"Circle::erase"&lt;&lt;endl;}<br>&nbsp;&nbsp;&nbsp; ~Circle(){cout&lt;&lt;"Circle::~Circle"&lt;&lt;endl;}<br>};<br><br>class Square:public Shape<br>{<br>&nbsp;&nbsp;&nbsp; Square(){}<br>&nbsp;&nbsp;&nbsp; friend class Shape;<br>public:<br>&nbsp;&nbsp;&nbsp; void draw(){cout&lt;&lt;"Square::draw"&lt;&lt;endl;}<br>&nbsp;&nbsp;&nbsp; void erase(){cout&lt;&lt;"Square::erase"&lt;&lt;endl;}<br>&nbsp;&nbsp;&nbsp; ~Square(){cout&lt;&lt;"Square::~Square"&lt;&lt;endl;}<br>};<br><br>Shape *Shape::factory(const string &amp; type)<br>&nbsp;&nbsp;&nbsp; throw(Shape::BadShapeCreation)<br>{<br>&nbsp;&nbsp;&nbsp; if(type=="Circle")return new Circle;<br>&nbsp;&nbsp;&nbsp; if(type=="Square")return new Square;<br>&nbsp;&nbsp;&nbsp; throw BadShapeCreation(type);<br>}<br><br>char *sl[]={"Circle","Square","Square","Circle","Circle","Circle","Square"};<br><br>int main()<br>{<br>&nbsp;&nbsp;&nbsp; vector&lt;Shape*&gt;shapes;<br>&nbsp;&nbsp;&nbsp; try{<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(size_t i=0;i&lt;sizeof sl/sizeof sl[0];i++)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shapes.push_back(Shape::factory(sl[i]));<br>&nbsp;&nbsp;&nbsp; }catch(Shape::BadShapeCreation e)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cout&lt;&lt;e.what()&lt;&lt;endl;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return -1;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; for(size_t i=0;i&lt;shapes.size();i++)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shapes[i]-&gt;draw();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; shapes[i]-&gt;erase();<br>&nbsp;&nbsp;&nbsp; }<br>}<br><br>函数factory 允许以一个参数来决定创建何种类型的Shape。在这里，参数类型为string,也可以是任何数据集。为了确保对象的创建只能发生在函数factory()中，Shape的特定类型的构造函数被设为私有，同时Shape被声明为友元类，因此factory()能够访问这些构造函数。<br><br>参考： C++编程思想卷2<br><br><img src ="http://www.cppblog.com/tankzhouqiang/aggbug/145610.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tankzhouqiang/" target="_blank">周强</a> 2011-05-03 23:12 <a href="http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145610.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++设计模式（七） 职责链模式：尝试采用一系列策略模式</title><link>http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145561.html</link><dc:creator>周强</dc:creator><author>周强</author><pubDate>Tue, 03 May 2011 06:01:00 GMT</pubDate><guid>http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145561.html</guid><wfw:comment>http://www.cppblog.com/tankzhouqiang/comments/145561.html</wfw:comment><comments>http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145561.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/tankzhouqiang/comments/commentRss/145561.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tankzhouqiang/services/trackbacks/145561.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 职责链（Chain of Responsibility)模式也许被看做一个使用策略对象的&#8220;递归的动态一般化".此时提出一个调用，在一个链序列中的每个策略都试图满足这个调用。这个过程直到有一个策略成功满足该调用或者到达序列的末尾才结束。在递归方法中，有个函数反复调用其自身至达到某个终止条件。在职责链中，一个函数调用自身，（通过遍历策略链）调用函数的一个不同实现，如此反复直至达到某个终止条件。这个终止条件或者是已达到策略链的底部（这样就会返回一个默认对象；不管能否提供这个默认结果，必须有个方法能够决定该职责链搜索是成功还是失败）或者是成功找到一个策略。<br>&nbsp;&nbsp;&nbsp;&nbsp; 除了调用一个函数来满足某个请求以外，链中的多个函数都有此机会满足某个请求，因此它有点专家系统的意味。由于职责链实际上就是一个链表，它能够动态创建，因此它可以看做是一个更一般的动态构建的switch语句。示例代码如下：<br>#include&lt;iostream&gt;<br>#include&lt;vector&gt;<br><br>using namespace std;<br><br><br>enum Answer{NO,YES};<br><br>class GimmeStrategy<br>{<br>&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; virtual Answer canIHave()=0;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; virtual ~GimmeStrategy(){}<br>};<br><br>class AskMom: public GimmeStrategy<br>{<br>&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Answer canIHave()<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cout&lt;&lt;"Moom? can I have this?"&lt;&lt;endl;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return NO;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>};<br><br>class AskDad: public GimmeStrategy<br>{<br>&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Answer canIHave()<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cout&lt;&lt;"Dad,I really need this!"&lt;&lt;endl;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return NO;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>};<br><br><br>class AskGrandpa:public GimmeStrategy<br>{<br>&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Answer canIHave()<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cout&lt;&lt;"Grandpa , is it my birthday yet?"&lt;&lt;endl;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return NO;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>};<br><br>class AskGrandma:public GimmeStrategy<br>{<br>&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Answer canIHave()<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cout&lt;&lt;"Grandma,I really love you!"&lt;&lt;endl;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return YES;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>};<br><br>class Gimme:public GimmeStrategy<br>{<br>&nbsp;&nbsp;&nbsp; vector&lt;GimmeStrategy*&gt;chain;<br>&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Gimme(){<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; chain.push_back(new AskMom());<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; chain.push_back(new AskDad());<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; chain.push_back(new AskGrandpa());<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; chain.push_back(new AskGrandma());<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Answer canIHave()<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; vector&lt;GimmeStrategy*&gt;::iterator it=chain.begin();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; while(it!=chain.end())<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if((*it++)-&gt;canIHave()==YES)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return YES;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cout&lt;&lt;"whiiiiiinnne!"&lt;&lt;endl;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return NO;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ~Gimme(){};<br>};<br><br>int main()<br>{<br>&nbsp;&nbsp;&nbsp; Gimme chain;<br>&nbsp;&nbsp;&nbsp; chain.canIHave();<br>}<br><br><br>参考 ：c++编程思想卷二<br><br><img src ="http://www.cppblog.com/tankzhouqiang/aggbug/145561.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tankzhouqiang/" target="_blank">周强</a> 2011-05-03 14:01 <a href="http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145561.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++设计模式（六）策略模式：运行时选择算法</title><link>http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145541.html</link><dc:creator>周强</dc:creator><author>周强</author><pubDate>Tue, 03 May 2011 03:33:00 GMT</pubDate><guid>http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145541.html</guid><wfw:comment>http://www.cppblog.com/tankzhouqiang/comments/145541.html</wfw:comment><comments>http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145541.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tankzhouqiang/comments/commentRss/145541.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tankzhouqiang/services/trackbacks/145541.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 前面模板方法模式是&#8220;坚持相同的代码&#8220;，而被覆盖的函数是&#8220;变化的代码&#8220;。然而，这种变化在编译时通过继承被固定下来。按照&#8220;组合优于继承&#8220;的格言，可以利用组合来解决将变化的代码从&#8220;坚持相同的代码&#8220;中分开的问题，从而产生策略（Strategy)模式。这种方法的一个明显的好处：在程序运行时，可以插入变化的代码。策略模式也加入&#8220;语境&#8220;，它可以是一个代理类，这个类控制着对特定策略对象的选择和使用。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;策略&#8220;的意思就是：可以使用多种方法来解决某个问题，即条条大陆通罗马。现在考虑一下忘记了某个人姓名时的情景。这里的程序可以用不同方法解决这个问题，实例代码如下：<br>#include&lt;iostream&gt;<br><br>using namespace std;<br><br>class NameStrategy<br>{<br>&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; virtual void greet()=0;<br>};<br><br>class SayHi: public NameStrategy<br>{<br>&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; void greet()<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cout&lt;&lt;"Hi! How's it going?"&lt;&lt;endl;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>};<br><br>class Ignore: public NameStrategy<br>{<br>&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; void greet()<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cout&lt;&lt;"Pretend I don't see you)"&lt;&lt;endl;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>};<br><br>class Admission:public NameStrategy<br>{<br>&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; void greet()<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cout&lt;&lt;"I'm sorry ,I forgot your name."&lt;&lt;endl;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>};<br><br>class Context<br>{<br>&nbsp;&nbsp;&nbsp; NameStrategy &amp; strategy;<br>&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Context(NameStrategy &amp; strat):strategy(strat){}<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; void greet(){strategy.greet();}<br>};<br><br><br>int main()<br>{<br>&nbsp;&nbsp;&nbsp; SayHi sayhi;<br>&nbsp;&nbsp;&nbsp; Ignore ignore;<br>&nbsp;&nbsp;&nbsp; Admission admission;<br>&nbsp;&nbsp;&nbsp; Context c1(sayhi),c2(ignore),c3(admission);<br>&nbsp;&nbsp;&nbsp; c1.greet();<br>&nbsp;&nbsp;&nbsp; c2.greet();<br>&nbsp;&nbsp;&nbsp; c3.greet();<br><br>}<br><br>Context::greet()可以正规地写得更加复杂些，它类似模板方法模式，因为其中包含了不能改变的代码。但在函数main()中可以看到，可以在运行时就策略进行选择。更进一步的做法。可以将状态模式与Context对象的生存期间变化的策略模式结合起来使用。<br><br><img src ="http://www.cppblog.com/tankzhouqiang/aggbug/145541.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tankzhouqiang/" target="_blank">周强</a> 2011-05-03 11:33 <a href="http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145541.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++设计模式（五）模板方法模式</title><link>http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145537.html</link><dc:creator>周强</dc:creator><author>周强</author><pubDate>Tue, 03 May 2011 03:15:00 GMT</pubDate><guid>http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145537.html</guid><wfw:comment>http://www.cppblog.com/tankzhouqiang/comments/145537.html</wfw:comment><comments>http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145537.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tankzhouqiang/comments/commentRss/145537.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tankzhouqiang/services/trackbacks/145537.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 应用程序结构框架允许从一个或一组类中继承以便创建一个新的应用程序，重用现存类中几乎所有的代码，并且覆盖其中一个或多个函数以便自定义所需要的应用程序。应用程序结构框架中的一个基本的概念是模板方法模式，它很典型地隐藏在覆盖的下方，通过调用基类的不同函数来驱动程序运行。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 模板方法模式的一个重要特征是它的定义在基类中（有时作为一个私有成员函数）并且不能改动，模板方法模式就是&#8220;坚持相同的代码&#8220;。它调用其他基类函数（就是那些被覆盖的函数）以便完成其工作，但是客户程序员不必直接调用这些函数。驱动应用程序运行的&#8220;引擎&#8221;是模板方法模式，示例代码如下：<br>#include&lt;iostream&gt;<br><br>using namespace std;<br><br>class ApplicationFramework<br>{<br>&nbsp;&nbsp;&nbsp; protected :<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; virtual void customize1()=0;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; virtual void customize2()=0;<br>&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; void templateMethod()<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for(int i=0;i&lt;5;i++)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; customize1();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; customize2();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>};<br><br>class MyApp: public ApplicationFramework<br>{<br>&nbsp;&nbsp;&nbsp; protected:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; void customize1(){cout&lt;&lt;"Hello";}<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; void customize2(){cout&lt;&lt;"World!"&lt;&lt;endl;}<br>};<br><br>int main()<br>{<br>&nbsp;&nbsp;&nbsp; MyApp app;<br>&nbsp;&nbsp;&nbsp; app.templateMethod();<br><br>}<br><br>参考：c++编程思想卷二<br><br><img src ="http://www.cppblog.com/tankzhouqiang/aggbug/145537.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tankzhouqiang/" target="_blank">周强</a> 2011-05-03 11:15 <a href="http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145537.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++设计模式（四）适配器(Adapter)模式</title><link>http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145534.html</link><dc:creator>周强</dc:creator><author>周强</author><pubDate>Tue, 03 May 2011 02:49:00 GMT</pubDate><guid>http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145534.html</guid><wfw:comment>http://www.cppblog.com/tankzhouqiang/comments/145534.html</wfw:comment><comments>http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145534.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tankzhouqiang/comments/commentRss/145534.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tankzhouqiang/services/trackbacks/145534.html</trackback:ping><description><![CDATA[适配器（Adapter)模式接受一种类型并且提供一个对其他类型的接口。当给定一个库或者具有某一接口的一段代码，同事还给定另外一个库或者与前面那段代码的基本思想相同的一段代码而只是表达式不一致时，适配器模式将十分有用。通过调整彼此的表达方式来适配彼此，将会迅速产生解决方法。<br><br>实例代码如下：<br>//FibonacciGenerator.h, 斐波那契数列产生器类<br><br>#ifndef FIBONACCIGENERATOR_H<br>#define FIBONACCIGENERATOR_H<br><br>class FibonacciGenerator<br>{<br>&nbsp;&nbsp;&nbsp; int n;<br>&nbsp;&nbsp;&nbsp; int val[2];<br>&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; FibonacciGenerator():n(0){val[0]=val[1]=0;}<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int operator()()<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int result=n&gt;2?val[0]+val[1]:n&gt;0?1:0;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ++n;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; val[0]=val[1];<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; val[1]=result;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return result;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int count(){return n;}<br>};<br>#endif<br><br>也许读者希望利用这个产生器来执行STL数值算法操作。遗憾的是，STL算法只能使用迭代器才能工作，这就存在接口不匹配的问题。解决方法就是产生一个适配器。代码如下。<br>#include&lt;iostream&gt;<br>#include&lt;numeric&gt;<br>#include"FibonacciGenerator.h"<br><br>using namespace std;<br><br>class FibonacciAdapter<br>{<br>&nbsp;&nbsp;&nbsp; FibonacciGenerator f;<br>&nbsp;&nbsp;&nbsp; int length;<br>&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; FibonacciAdapter(int size):length(size){}<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; class iterator;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; friend class iterator;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; class iterator:public std::iterator&lt;std::input_iterator_tag,FibonacciAdapter,ptrdiff_t&gt;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; FibonacciAdapter&amp; ap;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; typedef int value_type;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; iterator(FibonacciAdapter &amp;a):ap(a){}<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; bool operator==(const iterator &amp;)const{<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return ap.f.count()==ap.length;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; bool operator!=(const iterator &amp;x)const<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return !(*this==x);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int operator*()const{return ap.f();}<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; iterator&amp; operator++(){return *this;}<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; iterator operator++(int){return *this;}<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; };<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; iterator begin(){return iterator(*this);}<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; iterator end(){return iterator(*this);}<br>};<br><br>int main()<br>{<br>&nbsp;&nbsp;&nbsp; const int SZ=20;<br>&nbsp;&nbsp;&nbsp; FibonacciAdapter a1(SZ);<br>&nbsp;&nbsp;&nbsp; cout&lt;&lt;"accumulate:"&lt;&lt;accumulate(a1.begin(),a1.end(),0)&lt;&lt;endl;<br>}<br><br><br><br><img src ="http://www.cppblog.com/tankzhouqiang/aggbug/145534.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tankzhouqiang/" target="_blank">周强</a> 2011-05-03 10:49 <a href="http://www.cppblog.com/tankzhouqiang/archive/2011/05/03/145534.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++设计模式(三)代理模式（Proxy）与状态模式(State)模式</title><link>http://www.cppblog.com/tankzhouqiang/archive/2011/04/28/145229.html</link><dc:creator>周强</dc:creator><author>周强</author><pubDate>Thu, 28 Apr 2011 08:04:00 GMT</pubDate><guid>http://www.cppblog.com/tankzhouqiang/archive/2011/04/28/145229.html</guid><wfw:comment>http://www.cppblog.com/tankzhouqiang/comments/145229.html</wfw:comment><comments>http://www.cppblog.com/tankzhouqiang/archive/2011/04/28/145229.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tankzhouqiang/comments/commentRss/145229.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tankzhouqiang/services/trackbacks/145229.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 代理（Proxy）模式,状态（State）模式都提供一个代理类。代码与代理类打交道，而实际工作的类隐藏在代理类背后。当调用代理类中的一个函数时，代理类仅转而去调用实现类中的相应的函数。这两种模式是如此相似，从结构上看，可以认为代理模式只是状态模式的一个特例。但是这两个模式的内涵是不一样的。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 基本思想很简单：代理类派生来自一个基类，由平行地派生来自同一个基类的一个或多个类提供实际的实现。当一个代理对象被创建的时候，一个实现对象就分配给了它，代理对象就将函数调用发给实现对象。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 从结构上来看，代理模式和状态模式的区别很简单：代理模式只有一个实现类，而状态模式有多个（一个以上）实现。认为这两种设计模式的应用也不同：代理模式控制对其实现类的访问，而状态模式动态地改变其实现类。<br>（1）代理模式例子：<br>#include&lt;iostream&gt;<br><br>using namespace std;<br><br>class ProxyBase<br>{<br>&nbsp;&nbsp; &nbsp;public:<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;virtual void f()=0;<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;virtual void g()=0;<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;virtual void h()=0;<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;virtual ~ProxyBase(){}<br>};<br><br><br>class Implementation :public ProxyBase<br>{<br>&nbsp;&nbsp; &nbsp;public:<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;void f(){cout&lt;&lt;"Implementation.f()"&lt;&lt;endl;}<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;void g(){cout&lt;&lt;"Implementation.g()"&lt;&lt;endl;}<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;void h(){cout&lt;&lt;"Implementation.h()"&lt;&lt;endl;}<br>};<br><br><br>class Proxy: public ProxyBase<br>{<br>&nbsp;&nbsp; &nbsp;ProxyBase *implementation;<br>&nbsp;&nbsp; &nbsp;public:<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;Proxy(){implementation=new Implementation();}<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;~Proxy(){delete implementation;}<br><br><br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;void f(){implementation-&gt;f();}<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;void g(){implementation-&gt;g();}<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;void h(){implementation-&gt;h();}<br>};<br><br>int main()<br>{<br>&nbsp;&nbsp; &nbsp;Proxy p;<br>&nbsp;&nbsp; &nbsp;p.f();<br>&nbsp;&nbsp; &nbsp;p.g();<br>&nbsp;&nbsp; &nbsp;p.h();<br>}
<br><br>（2）状态模式<br>#include&lt;iostream&gt;<br><br>using namespace std;<br><br>class Creature<br>{<br>&nbsp;&nbsp; &nbsp;class State<br>&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;public:<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;virtual string response()=0;<br>&nbsp;&nbsp; &nbsp;};<br><br>&nbsp;&nbsp; &nbsp;class Frog : public State<br>&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;public:<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;string response(){return "Ribbet!";}<br>&nbsp;&nbsp; &nbsp;};<br><br>&nbsp;&nbsp; &nbsp;class Prince:public State<br>&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;public:<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;string response(){return "Darling!";}<br>&nbsp;&nbsp; &nbsp;};<br><br>&nbsp;&nbsp; &nbsp;State *state;<br>&nbsp;&nbsp; &nbsp;public:<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;Creature(): state(new Frog()){}<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;void greet()<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;cout&lt;&lt;state-&gt;response()&lt;&lt;endl;<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;void kiss()<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;delete state;<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;state=new Prince();<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br>};<br><br><br>int main()<br>{<br>&nbsp;&nbsp; &nbsp;Creature creature;<br>&nbsp;&nbsp; &nbsp;creature.greet();<br>&nbsp;&nbsp; &nbsp;creature.kiss();<br>&nbsp;&nbsp; &nbsp;creature.greet();<br>}
<br><br><img src ="http://www.cppblog.com/tankzhouqiang/aggbug/145229.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tankzhouqiang/" target="_blank">周强</a> 2011-04-28 16:04 <a href="http://www.cppblog.com/tankzhouqiang/archive/2011/04/28/145229.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++设计模式( 二） 命令：选择操作</title><link>http://www.cppblog.com/tankzhouqiang/archive/2011/04/28/145212.html</link><dc:creator>周强</dc:creator><author>周强</author><pubDate>Thu, 28 Apr 2011 06:26:00 GMT</pubDate><guid>http://www.cppblog.com/tankzhouqiang/archive/2011/04/28/145212.html</guid><wfw:comment>http://www.cppblog.com/tankzhouqiang/comments/145212.html</wfw:comment><comments>http://www.cppblog.com/tankzhouqiang/archive/2011/04/28/145212.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tankzhouqiang/comments/commentRss/145212.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tankzhouqiang/services/trackbacks/145212.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 命令（command）模式的结构很简单，但是对于消除代码间的耦合，清理代码去有着重要的影响。从最直观的角度来看，命令模式就是一个函数对象：一个作为对象的函数。通过将函数封装为对象，就能够以参数的形式将其传递给其他函数或者对象，告诉它们在履行请求的过程中执行特定的操作。可以说，命令模式是携带行为信息的信使。一个简单的例子如下：<br>#include&lt;iostream&gt;<br>#include&lt;vector&gt;<br><br>using namespace std;<br><br>class Command<br>{<br>&nbsp;&nbsp; &nbsp;public:<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;virtual void execute()=0;<br>};<br><br><br>class Hello: public Command<br>{<br>&nbsp;&nbsp; &nbsp;public:<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;void execute(){cout&lt;&lt;"hello ";}<br>};<br><br><br>class World : public Command<br>{<br>&nbsp;&nbsp; &nbsp;public:<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;void execute(){cout&lt;&lt;"world!";}<br>};<br><br>class IAm:public Command<br>{<br>&nbsp;&nbsp; &nbsp;public:<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;void execute(){cout&lt;&lt;"I'm the command pattern!";}<br>};<br><br>class Macro<br>{<br>&nbsp;&nbsp; &nbsp;vector&lt;Command *&gt;commands;<br>&nbsp;&nbsp; &nbsp;public:<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;void add(Command *c){commands.push_back(c);}<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;void run()<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;vector&lt;Command*&gt;::iterator it=commands.begin();<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;while(it!=commands.end())<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;(*it++)-&gt;execute();<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;cout&lt;&lt;endl;<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>};<br><br><br>int main()<br>{<br>&nbsp;&nbsp;&nbsp; Macro macro;<br>&nbsp;&nbsp;&nbsp; macro.add(new Hello);<br>&nbsp;&nbsp;&nbsp; macro.add(new World);<br>&nbsp;&nbsp;&nbsp; macro.add(new IAm);<br>&nbsp;&nbsp;&nbsp; macro.run();<br>} <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 命令模式的主要特点是允许向一个函数或者对象传递一个想要的动作。上述例子提供了将一系列需要一起执行的动作集进行排队的方法。在这里，可以动态创建新的行为，某些事情通常只能通过编写新的代码来完成，而在上述例子中可以通过解释一个脚本来实现。<br><br>参考：c++编程思想2<br><br><img src ="http://www.cppblog.com/tankzhouqiang/aggbug/145212.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tankzhouqiang/" target="_blank">周强</a> 2011-04-28 14:26 <a href="http://www.cppblog.com/tankzhouqiang/archive/2011/04/28/145212.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++设计模式（一） 单件（Singleton)</title><link>http://www.cppblog.com/tankzhouqiang/archive/2011/04/28/145192.html</link><dc:creator>周强</dc:creator><author>周强</author><pubDate>Thu, 28 Apr 2011 02:41:00 GMT</pubDate><guid>http://www.cppblog.com/tankzhouqiang/archive/2011/04/28/145192.html</guid><wfw:comment>http://www.cppblog.com/tankzhouqiang/comments/145192.html</wfw:comment><comments>http://www.cppblog.com/tankzhouqiang/archive/2011/04/28/145192.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tankzhouqiang/comments/commentRss/145192.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tankzhouqiang/services/trackbacks/145192.html</trackback:ping><description><![CDATA[设计模式或许是面向对象设计方法学前进过程中的最新，最重要的一步。设计模式当今已成为面向对象程序设计的重要部分。<br><br>单件也许是最简单的设计模式，它是允许一个类有且仅有一个实例的方法。创建一个单件模式的关键是防止客户程序员获得任何控制其对象生存期的权利。为了做到这一点，声明所有的构造函数为私有，并且防止编译器隐式生成任何构造函数。注意，拷贝构造函数和赋值操作符（这两个故意没有实现，，因为它们根本不会被调用）被声明为私有，以便防止任何这类复制动作产生。这种方法并没有限制只创建一个对象。这种技术也支持创建有限个对象的对象池。<br><br>下面的程序显示在c++中如何实现一个单件模式<br>#include&lt;iostream&gt;<br><br>using namespace std;<br><br><br>class Singleton<br>{<br>&nbsp;&nbsp; &nbsp;static Singleton s;<br>&nbsp;&nbsp; &nbsp;int i;<br>&nbsp;&nbsp; &nbsp;Singleton(int x):i(x){}<br>&nbsp;&nbsp; &nbsp;Singleton &amp; operator=(Singleton &amp;); //disallowed<br>&nbsp;&nbsp; &nbsp;Singleton(const Singleton &amp;);<br><br>public:<br>&nbsp;&nbsp; &nbsp;static Singleton &amp; instance(){return s;}<br>&nbsp;&nbsp; &nbsp;int getValue(){return i;}<br>&nbsp;&nbsp; &nbsp;void setValue(int x){i=x;}<br>};<br><br><br>Singleton Singleton::s(47);<br><br><br>int main()<br>{<br>&nbsp;&nbsp; &nbsp;Singleton &amp;s =Singleton::instance();<br>&nbsp;&nbsp; &nbsp;cout&lt;&lt;s.getValue()&lt;&lt;endl;<br>&nbsp;&nbsp; &nbsp;Singleton &amp;s2=Singleton::instance();<br>&nbsp;&nbsp; &nbsp;s2.setValue(9);<br>&nbsp;&nbsp; &nbsp;cout&lt;&lt;s.getValue()&lt;&lt;endl;<br>}
<br><br><br>参考：c++ 编程思想 2<br><br><img src ="http://www.cppblog.com/tankzhouqiang/aggbug/145192.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tankzhouqiang/" target="_blank">周强</a> 2011-04-28 10:41 <a href="http://www.cppblog.com/tankzhouqiang/archive/2011/04/28/145192.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>