﻿<?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++博客-loop_in_codes-随笔分类-模块架构</title><link>http://www.cppblog.com/kevinlynx/category/7299.html</link><description>低调做技术__
C/C++\MMORPG服务器\模块架构__ TODO：linux env/read more books __Kevin Lynx</description><language>zh-cn</language><lastBuildDate>Thu, 21 Mar 2013 15:19:32 GMT</lastBuildDate><pubDate>Thu, 21 Mar 2013 15:19:32 GMT</pubDate><ttl>60</ttl><item><title>浅析软件工程开发方法学RUP</title><link>http://www.cppblog.com/kevinlynx/archive/2013/03/21/198692.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Thu, 21 Mar 2013 13:41:00 GMT</pubDate><guid>http://www.cppblog.com/kevinlynx/archive/2013/03/21/198692.html</guid><wfw:comment>http://www.cppblog.com/kevinlynx/comments/198692.html</wfw:comment><comments>http://www.cppblog.com/kevinlynx/archive/2013/03/21/198692.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/kevinlynx/comments/commentRss/198692.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kevinlynx/services/trackbacks/198692.html</trackback:ping><description><![CDATA[
<div class="entry-content"><h2>前言</h2> <p>因为之前一直处在游戏开发行业，由于种种原因一直对软件工程中的项目管理、项目开发方法缺乏体验。虽然项目中也曾倡导编写更多的文档，无论是模块说明文档还是设计文档，但效果一直不好。不甚理想的地方主要体现在文档的规范性欠缺、不统一、浮于表面没有实质内容。文档的编写缺乏详尽的方法指导，那么所谓的设计文档要么是用来敷衍上级要么就是随着开发人员的水平不一而千差万别。</p> <p>当我开始目前这个非游戏项目时，我也曾想，前期做好结构设计，制定好关键问题的解决方案，那么要完成这个项目就不在话下了。但是我很快就面临了一个问题：需求不定。回想身处游戏公司的那些日子，程序员总是抱怨策划需求变更过快过多，在每一次策划提出一个需求变更时，谨慎的程序员都会再三让策划保证：放心，不会变了。而我面临的问题则更为严峻。我意识到，项目的需求，就连用户也无法一一罗列出来。我们需要的是需求调研。但就算你将客户的所有需求全部挖掘出来后（这几乎不可能，因为他们自己也不太清楚自己想要什么），当你交付了第一个软件版本，几乎可以肯定客户会提出一大堆的需求变更：我要的不是这个，我要的那个怎么没有，哦，我当初以为你说的是另一个意思。</p> <p>当然，需求调研这种工作不是让程序员去做的（那会更悲剧，无论是对客户还是对程序员而言，他们都是在对牛弹琴）。但需求的不确定性也总是存在的。</p> <p>事实上，需求变化本身就是一个很正常的现象。我一向愿意更悲观地处理软件开发方面的问题，所谓小心使得万年船。基于此，我决定摆好心态学学软件开发的方法学。</p> <h2>概要</h2> <p>本文简要描述、总结了RUP开发方法学的主要内容，结合我自己的感受阐述了一些RUP的核心原则。我相信我所理解的内容是肤浅的，对于非代码的表达我更相信其是存在歧义的。所以本文仅当是一种经验参考，不必当真。</p> <p>RUP据传是用于指导大型甚至超大型项目开发的，我们做的不是这样规模的项目。但是我们需要记录下整个项目的开发过程，通过这个过程中产出的<strong>工件</strong>任何一个人可以看出这个项目是如何实现出来的，其目的在于规避唯有从海量代码中才能熟悉项目实现这种问题。这里出现了一个概念：工件，其指的是软件项目开发过程中任何留下记录的事物，例如文档、图、代码等。<strong>RUP的一个重要思想，在于其整个软件开发过程都是可推导的</strong>。例如我们通常说的软件架构，或小一点的模块结构，都是通过开发过程中前面阶段产出的工件推导得出，而<strong>不是凭借程序员的经验拍脑袋想出来的</strong>（经验不太可靠，并且千差万别，而<strong>推导</strong>意味着将每个环节变得可靠）。我们借助RUP的这个特性，创建这些工件，用以建立起软件实现的可靠知识库。</p> <!-- more --> <h2>RUP概览</h2> <p>以下均摘自&lt;Thinking in UML>中对RUP的描述：</p> <blockquote><p>统一过程归纳和集成了软件开发活动中的最佳实践，它定义了软件开发过程中最重要的阶段和工作（四个阶段和九个核心工作流），定义了参与软件开发过程的各种角色和他们的职责，还定义了软件生产过程中产生的工件，并提供了模板。最后，采用演进式软件生命周期（迭代）将工作、角色和工件串在一起，形成了统一过程。</p> <p>统一过程是一种追求稳定的软件方法，它追求开发稳定架构，控制变更</p> <p>统一过程集成了面向对象方法、UML语言、核心工作流、工件模板和过程指导等知识</p></blockquote>
<p>简单来说，RUP作为一种软件项目开发方法学，<strong>它定义了软件开发的每一个过程，最重要的是它指导了在每一个过程需要产出什么，这些产出又是怎样得到。它试图规范化整个流程，以规避需求变更，项目参与者水平不一等带来的项目不可控等问题，以期一个软件产品稳定地开发出来</strong>。在一个项目开发过程中，最核心的资源是人，最不可控的亦是人。</p> <h2>RUP过程与实践</h2> <p>我觉得要快速学习一种知识，需要首先获得这门知识的总体框架。另一方面，在我们获得更多信息后，我们需要挖掘出这门知识的核心思想。学习RUP我觉得从这两方面入手是相对比较快速和有效的手段。</p> <h3>RUP框架</h3> <p><strong>RUP定义了软件开发过程的四个阶段，以及9个工作流程</strong>。一张极为经典的RUP开发过程框架图如下：</p>
<p><img src="http://codemacro.com/assets/res/rup/rup.png" alt="rup" /></p> <p>RUP将整个软件开发过程分为四个阶段：</p> <ul>
<li>先启(Inception)、</li>
<li>精化(Elaboration)</li>
<li>构建(Construction)</li>
<li>产品化(Transition)</li>
</ul> <p>每一个阶段的工作分为9个流程：</p> <ul>
<li>业务建模</li>
<li>需求</li>
<li>分析设计</li>
<li>实施</li>
<li>测试</li>
<li>部署</li>
<li>配置与变更管理</li>
<li>项目管理</li>
<li>环境</li>
</ul> <p>其中，前6个流程被统称为&#8221;engineering disciplines&#8221;，后3个流程被称为&#8221;supporting disciplines&#8221;。当然，我们主要关注前6个流程。那么，这些工作流程和开发阶段又有什么关系呢？上图中其实已经阐明了这些关系。</p> <p>RUP指导迭代开发。在软件开发的这4个阶段中，每一个阶段会被分为若干次迭代。而每一次迭代则涵盖了这9个工作流程。随着开发阶段向产品化靠近，自然而然地，需求的变更、增加自然会减少，所以从图中可以看出，开发过程越到后期，其工作流程中关于需求的工作则越少。同样，在先启阶段，其需求相关的工作则占据了该阶段的主要工作内容。</p>
<p>RUP中的迭代要求在每一次迭代中，都会完整地实施一遍整个工作流程。在软件实施阶段，甚至会在每一个迭代过程完后输出一个可运行的软件版本。这个版本可能会被交付给客户，以期进一步地在功能需求上取得与客户一致的意见。这倒是同敏捷开发有点类似。</p> <p>既然制定了工作流程，那每一个工作流程该如何去实施呢？<strong>RUP制定了每个工作流程需要参与的角色，这些角色需要从事的活动，以及这些活动产生的工件。</strong></p> <p>这句话实际上反映了RUP的一个重要信息，摘自wiki：</p> <blockquote><p>RUP is based on a set of building blocks, or content elements, describing what is to be produced, the necessary skills required and the step-by-step explanation describing how specific development goals are to be achieved. The main building blocks, or content elements, are the following:</p> <ul>
<li><strong>Roles (who)</strong> &#8211; A Role defines a set of related skills, competencies and responsibilities.</li>
<li><strong>Work Products (what)</strong> &#8211; A Work Product represents something resulting from a task, including all the documents and models produced while working through the process.</li>
<li><strong>Tasks (how)</strong> &#8211; A Task describes a unit of work assigned to a Role that provides a meaningful result.</li>
</ul>
</blockquote> <h3>RUP建模</h3> <p>在我看来，RUP每个工作流程所完成的工作，就是一个建模的过程。所谓建模，简单来说就是将需要描述的事物通过更系统的形式表达出来，以期获得对该事物更深入的理解。&lt;Thinking in UML>中定义建模概念为：</p>
<blockquote><p>建模(modeling)，是指通过对客观事物建立一种抽象的方法用以表征事物并获得对事物本身的理解，同时把这种理解概念化，将这些逻辑概念组织起来，构成一种对所观察的对象的内部结构和工作原理的便于理解的表达。</p></blockquote> <p>在这里，建模的过程需要使用一些工具。在RUP中建模使用UML来完成。在&lt;Thinking in UML>中讲述了UML的核心模型，包括：</p> <ul>
<li>业务用例模型</li>
<li>概念用例模型</li>
<li>系统用例模型</li>
<li>领域模型</li>
<li>分析模型</li>
<li>软件架构和框架</li>
<li>设计模型</li>
<li>组件模型</li>
<li>实施模型</li>
</ul> <p>可能在大家的普遍认识中，UML无非就是几种图，并且粗看一眼理解起来也不困难，甚至还能用来画画类图做下代码结构设计。但UML的作用不仅仅如此。</p> <p>以上所描述的UML核心模型中，每个模型并不单指的的是一种UML图。每个模型实际上都会包含几种UML图，会包含若干张UML图。这些模型基本上渗透于RUP的9个工作流程中，只不过不同的工作流程使用的模型比重不一而已。</p>
<p>例如在&#8220;分析设计&#8221;工作流程中，可能会使用到系统用例模型、分析模型、软件架构和框架、设计模型等，而业务用例模型可能在这个流程中根本不会用到；相反，业务用例模型则可能在&#8220;业务建模&#8221;流程中被广泛使用。</p> <p>前已述及在RUP的每个工作流程中，RUP定义了该流程需要参与的角色，以及这些角色需要进行的活动，例如这里可以看看&#8220;分析设计&#8221;流程中的角色和活动集（摘自&lt;Thinking in UML>）：</p> <p><img src="http://codemacro.com/assets/res/rup/analyse-action.png" alt="analyse-action" /></p> <p>相应的，在该工作流程中需要产出的工件集为（摘自&lt;Thinking in UML>）：</p> <p><img src="http://codemacro.com/assets/res/rup/analyse-ar.png" alt="analyse-ar" /></p> <p>既然使用了UML作为建模工具，所以可以简单地说这些工件主要就是UML图，当然也会有其他文档性质的事物，例如网络协议结构、数据库表等UML无法描述的东西则通过普通文字性文档描述。</p>
<h3>RUP最佳实践</h3> <p>到目前为止我们已经了解到RUP定义了开发过程(phase)，定义了每个过程包含的若干工作流程，还定义了每个工作流程需要哪些角色从事哪些活动来完成哪些工件。除此之外，RUP还提供了6条最佳实践用以指导软件开发：</p> <ul>
<li>迭代开发</li>
<li>管理需求</li>
<li>使用基于组件的架构</li>
<li>可视建模</li>
<li>持续的质量验证</li>
<li>控制变更</li>
</ul> <p>这些实践在我看来仅仅是一些项目开发的指导原则，它们渗透到每一个过程，每一个工作流程。在项目过程中实践这些原则，用以确保项目的成功。例如我们使用UML建模，以达到&#8220;可视建模&#8221;。我们通过建立需求用例，以&#8220;管理需求&#8221;。</p> <h2>RUP核心思想</h2> <p>似乎没有文档来专门阐述RUP的核心思想，但我觉得掌握其核心思想才是学习的要点所在。要理解一种软件开发方法学的核心思想，其实最好是将其与别的方法学做比较。这里先就我的一些感想做阐述。</p> <h3>用例驱动</h3> <p>用例驱动指的是整个软件项目的推进过程，是依靠&#8220;用例&#8221;来完成。&lt;Thinking in UML>：</p> <blockquote><p>在实际的软件项目中，一个软件要实现的功能通过用例来捕获，接下来的所有分析、设计、实现、测试都由用例来取得，即以实现用例为目标。在统一过程中用例能够驱动的不仅仅是分析设计。</p></blockquote> <p>用例简单来说就是描述了一个系统功能。但必须注意的是，这仅仅是它定义的一小部分。用例主要分布在&#8220;业务建模&#8221;、&#8220;需求&#8221;、&#8220;分析设计&#8221;这些工作过程中。在不同的过程中用例的粒度和性质都不一样。例如对于一个借书系统而言，在业务建模阶段，我们可以获取出一个&#8220;借书&#8221;用例，其系统边界甚至不是系统而可能仅关注这个业务本身（因为这个阶段还没有考虑到计算机如何实现这个借书业务）；在系统分析阶段，我们就可以将&#8220;借书&#8221;这个用例细化为用户和计算机软件系统的交互；进一步地，我们可能会进一步精化这个用例，例如用户通过网页终端&#8220;借书&#8221;。（这里描述了很多建模的细节，可不必深究，本文只给出一个概要性的介绍）</p> <p>我们说用例驱动软件开发，但它如何驱动的呢？我在实际的建模过程中，最明显的感受就是用例驱动了整个建模过程。</p> <ul>
<li>在需求分析阶段，我以系统使用者的角度绘制出了一份用例图，用于表达使用者对该系统的需求</li>
<li>然后我绘制序列图（活动图等）来实现这些用例，也就是阐述使用者具体是如何与系统交互的</li>
<li>从之前的建模过程中我获得对系统功能需求方面的认识</li>
<li>基于前面的分析我可以绘制出系统用例图，以明确系统的各个功能需求</li>
<li>同样针对用例绘制用例实现图</li>
<li>用例本身应该包含更多的文档，因此我编写用例规约用以详细描述各个用例</li>
<li>从用例规约、用例实现中我可以抽离出一些分析类（较设计类更高抽象的类），包含用例场景中涉及到的实体，控制逻辑</li>
<li>细化这些分析类，将分析类组织起来形成系统，我会用界面类去衔接各个控制类</li>
<li>将得到的分析类按模块来划分，从而可以得到一个初步的系统架构</li>
<li>初步考虑系统实现，我甚至会得到一个初步是的系统部署图</li>
<li>回过头不断审视系统用例，以确认我是否实现了所有用例，这可以保证我的分析实现了所有需求，<strong>我不用枚举所有系统特性是否被我考虑周全，我仅需在已有用例图中核实</strong></li>
<li>基于模块实现各个用例，或者基于分析类来实现系统用例</li>
<li>通过重新绘制以及核实用例，可以进一步精化分析类，分析类在很大程度上会一一对应到设计类，而设计类则对应到实际的代码</li>
<li>可以进入设计阶段，设计阶段会考虑到系统的实现细节，例如使用的语言，使用的框架等</li>
</ul> <p>进入设计阶段后，虽然可以进一步建模，得到会直接映射到代码的类图、序列图等，但这样的图在面临需求变更时，基本上会面临修改，这意味着维护这些文档需要耗费精力。所以，&lt;Thinking in UML>中主张将精力放在维护分析类模型中，而通过其他约定实现从分析类到实际代码的转换。我觉得这个也在理。</p> <h3>规范化整个过程</h3> <p>我个人觉得RUP的一大特点在于规范化了整个软件开发过程，每一个步骤需要哪些角色参与，该干什么，怎么去干都有指导。加之这些活动的&#8221;可推导性&#8220;，这意味着不论参与角色属于什么水平，都可以稳固地推进项目进程。</p>
<p>此外，这种规范化也会给项目留下详细的演化过程。你可以明确地看到整个软件是如何演化出最终的产品代码，可以深入地理解项目代码中的设计。</p> <h2>总结</h2> <p>我只是一个RUP新手，即便如此，我依然不觉得RUP是软件开发的万能药。我相信任何软件开发方法都是有局限性的。我们在实际使用的时候也只是吸取其精华。不同的开发方法其适用范围也是不一样的。正如有人将RUP和XP做比较时说，如果你使用RUP去开一个杂货铺，在没开张之前你就已经破产了；同样如果你用XP去做飞机，飞机毁了十来次也许才能做出来（from &lt;Thinking in UML> again）。</p> <h2>参考文档</h2> <ul>
<li><a href="http://blog.csdn.net/coffeewoo/">&lt;Thinking in UML></a></li>
<li><a href="http://www.uml.org.cn/SoftWareProcess/2009031017.asp">RUP和IPD流程的优缺点</a></li>
<li><a href="http://en.wikipedia.org/wiki/IBM_Rational_Unified_Process">IBM Rational Unified Process(wiki)</a></li>
<li><a href="http://blog.roodo.com/rocksaying/archives/2051417.html">軟體工程三大陣營, RUP, CMMI, Agile Method</a></li>
<li><a href="http://incredibleagile.com/download/xpVsrup.pdf">XP与RUP的比较</a></li>
</ul> <p class='post-footer'> 原文地址： <a href='http://codemacro.com/2013/03/21/rup/'>http://codemacro.com/2013/03/21/rup/</a><br/> written by <a href='http://codemacro.com'>Kevin Lynx</a>
 &nbsp;posted at <a href='http://codemacro.com'>http://codemacro.com</a> </p> </div>
<img src ="http://www.cppblog.com/kevinlynx/aggbug/198692.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2013-03-21 21:41 <a href="http://www.cppblog.com/kevinlynx/archive/2013/03/21/198692.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MMO游戏对象属性设计</title><link>http://www.cppblog.com/kevinlynx/archive/2011/05/02/145504.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Mon, 02 May 2011 11:19:00 GMT</pubDate><guid>http://www.cppblog.com/kevinlynx/archive/2011/05/02/145504.html</guid><wfw:comment>http://www.cppblog.com/kevinlynx/comments/145504.html</wfw:comment><comments>http://www.cppblog.com/kevinlynx/archive/2011/05/02/145504.html#Feedback</comments><slash:comments>18</slash:comments><wfw:commentRss>http://www.cppblog.com/kevinlynx/comments/commentRss/145504.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kevinlynx/services/trackbacks/145504.html</trackback:ping><description><![CDATA[<div class="document" id="mmo">
<h1 class="title">MMO游戏对象属性设计</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr><th class="docinfo-name">Author:</th>
<td>Kevin Lynx</td></tr>
<tr><th class="docinfo-name">Date:</th>
<td>5.2.2011</td></tr>
</tbody>
</table>
<p>一般的MMORPG中，游戏对象主要包括怪物和玩家。这两类对象在经过游戏性方面的不断&#8220;进化&#8221;后，其属性数量及与之相关的逻辑往往会变得很巨大。如何将这一块做得既不损失效率，又能保证结构的灵活、清晰、可维护？本文将提供一种简单的结构。</p>
<div class="section" id="id1">
<h1>原始结构</h1>
<p>最原始的结构，极有可能为这样:</p>
<pre class="literal-block">
Player:     +---------------+
            | property-1    |
            +---------------+
            | property-2    |
            +---------------+
            |     ...       |
            +---------------+
            | operator-1    |
            +---------------+
            | operator-2    |
            +---------------+
            | ...           |
            +---------------+
</pre>
<p>也就是，一个对象为一个C++类，然后里面直接塞满了各种属性名，然后是针对这个属性的逻辑操作（函数）。其结果就是Player成为巨类。针对这个情况，一直以来我觉得可以使用一种简单的方法来拆分这个类。冠以官腔，称之为Entity-Component-based Desgin。产生这种想法和我的个人技术积累有一定关系，见下文。</p>
</div>
<div class="section" id="policy-based-design">
<h1>Policy-based Design</h1>
<p>Policy-based Design，基于决策的设计。这个概念来源于&lt;Modern C++ Design&gt;。虽然这本书讲述的是针对C++模板的使用及设计技巧。但这种思想依然被我潜意识般地用在其他地方。Policy大致来说就是一个小的组件(Component)。它努力不依赖于其他东西，它可能就是个简单的类，它拥有极少的数据结构，及针对这些数据的极少操作接口。举例而言，玩家MP的自动回复功能，就可封装为一个Policy。将许多Policy组合起来，就可完成一个复杂的功能。</p>
<p>这种思想还可指导很多程序结构方面的设计。例如在做功能的接口拆分时，就将每个函数设计得足够小，小到单纯地完成一个功能。一个功能的入口函数，就将之前实现的小函数全部组合起来，然后共同完成功能点。</p>
<p>当然，&lt;Modern C++ Design&gt;里的Policy在表现形式上有所不同。但其核心思想相同，主要体现在 <strong>组合</strong> 特点上。</p>
</div>
<div class="section" id="entity-component-based-design">
<h1>Entity-Component-based Design</h1>
<p>Entity-Component-based Design按照google到的文章，严格来说算是与OOP完全不同的软件设计方法。不过在这里它将按照我的意思重新被解释。</p>
<p>如果说Policy-based Design极大可能地影响着我们平时的细节编码，那么Entity-Component则是直接对游戏对象的结构设计做直接的说明。 <strong>一个游戏对象就是一个Entity。</strong> Entity拥有很少的属性，也许仅包含一个全局标示的ID。 <strong>一个Component则是Entity的某个行为、或者说某个组成部分。</strong> 其实说白了，以玩家为例，一个玩家对象就是一个Entity，而一个MP的自动回复功能就可被包装为一个Component。这个Component可能包含若干与该功能相关的数据，例如回复时间间隔，每次的回复量等。我们往玩家对象这个Entity添加各种Component，也就是给玩家添加各种逻辑功能。</p>
<p>但是，Component之间可能会涉及到交互，玩家对象之外的模块可能也会与玩家内的某个Component交互。子功能点的拆分，不得不涉及到更多的胶水代码，这也算一种代价。</p>
</div>
<div class="section" id="id2">
<h1>游戏对象属性设计</h1>
<p>这份属性结构设计，基本就是参考了上面提到的设计思想。整个系统有如下组件:</p>
<pre class="literal-block">
Entity:    +-------------------+
           | property-table    |
           +-------------------+
           | component-table   |
           +-------------------+
Property:  +-------------------+
           | observer-list     |
           +-------------------+
Component: +--------------------+
           | logic-related data |
           +--------------------+
           | logic-related func |
           +--------------------+
</pre>
<p>意即，所有Entity都包含一个属性表和组件表。这里的属性表并非硬编码的属性数据成员集合，而是一个key-value形式的表。Property包含一个观察者列表，其实就是一系列回调函数，但是这些观察者本质上也是组件，后面会提到。Component正如上文描述，仅包含Component本身实现的功能所需要的数据和函数。整个结构大致的代码如下:</p>
<pre class="literal-block">
class Entity {
private:
    GUID id;
    std::map&lt;std::string, IComponent*&gt; components;
    std::map&lt;std::string, Property*&gt; properties;
};
class Property {
private:
    std::string name;
    Value val;
    std::vector&lt;IComponent*&gt; observers;
};
class IComponent {
public:
    virtual bool Operate (const Args &amp;args) { return false; }
    virtual void OnNotify (const Property &amp;property, const Args &amp;args) {}
protected:
    std::string name;
    Entity *entity;
};
</pre>
<p>属性本身是抽象的，这完全是因为我们将属性统一地放在了一个表里。从而又导致属性的值也需要<a href="http://codemacro.com/blog/display?id=8">继续阅读</a></p>
</div>
</div><img src ="http://www.cppblog.com/kevinlynx/aggbug/145504.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2011-05-02 19:19 <a href="http://www.cppblog.com/kevinlynx/archive/2011/05/02/145504.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>浅谈代码分层：构建模块化程序</title><link>http://www.cppblog.com/kevinlynx/archive/2011/04/05/143430.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Tue, 05 Apr 2011 02:12:00 GMT</pubDate><guid>http://www.cppblog.com/kevinlynx/archive/2011/04/05/143430.html</guid><wfw:comment>http://www.cppblog.com/kevinlynx/comments/143430.html</wfw:comment><comments>http://www.cppblog.com/kevinlynx/archive/2011/04/05/143430.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/kevinlynx/comments/commentRss/143430.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kevinlynx/services/trackbacks/143430.html</trackback:ping><description><![CDATA[<div id="id1" class="document"><h1 class="title">&#x6D45;&#x8C08;&#x4EE3;&#x7801;&#x5206;&#x5C42;&#xFF1A;&#x6784;&#x5EFA;&#x6A21;&#x5757;&#x5316;&#x7A0B;&#x5E8F;</h1><table rules="none" frame="void" class="docinfo"><col class="docinfo-name"></col><col class="docinfo-content"></col><tbody valign="top"><tr><th class="docinfo-name">Author:</th><td>Kevin Lynx</td></tr><tr><th class="docinfo-name">Date:</th><td>4.4.2011</td></tr><tr><th class="docinfo-name">Contact:</th><td>kevinlynx at gmail dot com</td></tr></tbody></table><p>&#x6A21;&#x5757;&#x5316;&#x7684;&#x7A0B;&#x5E8F;&#x662F;&#x600E;&#x6837;&#x7684;&#x7A0B;&#x5E8F;&#xFF1F;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x8BF4;&#x4E00;&#x4E2A;&#x5177;&#x6709;&#x660E;&#x663E;&#x7269;&#x7406;&#x7ED3;&#x6784;&#x7684;&#x8F6F;&#x4EF6;&#x662F;&#x6A21;&#x5757;&#x5316;&#x7684;&#xFF0C;&#x4F8B;&#x5982;&#x5E26;
&#x63D2;&#x4EF6;&#x7684;&#x8F6F;&#x4EF6;&#xFF0C;&#x4E00;&#x4E2A;&#x5B8C;&#x6574;&#x7684;&#x8F6F;&#x4EF6;&#x7531;&#x82E5;&#x5E72;&#x8FD0;&#x884C;&#x65F6;&#x5E93;&#x5171;&#x540C;&#x6784;&#x5EFA;&#xFF1B;&#x4E5F;&#x53EF;&#x4EE5;&#x8BF4;&#x4E00;&#x4E2A;&#x9AD8;&#x5EA6;&#x9762;&#x5411;&#x5BF9;&#x8C61;&#x7684;&#x5E93;&#x662F;
&#x6A21;&#x5757;&#x5316;&#x7684;&#xFF0C;&#x4F8B;&#x5982;&#x56FE;&#x5F62;&#x5F15;&#x64CE;OGRE&#xFF1B;&#x4E5F;&#x53EF;&#x4EE5;&#x8BF4;&#x4E00;&#x4E9B;&#x5177;&#x6709;&#x660E;&#x663E;&#x5C42;&#x6B21;&#x7ED3;&#x6784;&#x7684;&#x4EE3;&#x7801;&#x662F;&#x6A21;&#x5757;&#x5316;&#x7684;&#x3002;</p><p>&#x6A21;&#x5757;&#x5316;&#x7684;&#x8F6F;&#x4EF6;&#x5177;&#x6709;&#x5F88;&#x591A;&#x663E;&#x800C;&#x6613;&#x89C1;&#x7684;&#x597D;&#x5904;&#x3002;&#x5728;&#x5F00;&#x53D1;&#x671F;&#xFF0C;&#x4E00;&#x4E2A;&#x6A21;&#x5757;&#x5316;&#x7684;&#x8BBE;&#x8BA1;&#x6709;&#x5229;&#x4E8E;&#x7A0B;&#x5E8F;&#x5458;&#x5B9E;&#x73B0;&#xFF0C;
&#x4F7F;&#x5176;&#x5728;&#x5B9E;&#x73B0;&#x8FC7;&#x7A0B;&#x4E2D;&#x4E00;&#x76F4;&#x4FDD;&#x6301;&#x6E05;&#x6670;&#x7684;&#x601D;&#x8DEF;&#xFF0C;&#x51CF;&#x5C11;&#x6F5C;&#x4F0F;&#x7684;BUG&#xFF1B;&#x800C;&#x5728;&#x7EF4;&#x62A4;&#x671F;&#xFF0C;&#x5219;&#x6709;&#x5229;&#x4E8E;&#x5176;&#x4ED6;&#x7A0B;&#x5E8F;
&#x5458;&#x7684;&#x7406;&#x89E3;&#x3002;</p><p>&#x5728;&#x6211;&#x770B;&#x6765;&#xFF0C;&#x5177;&#x6709;&#x826F;&#x597D;&#x6A21;&#x5757;&#x8BBE;&#x8BA1;&#x7684;&#x4EE3;&#x7801;&#xFF0C;&#x81F3;&#x5C11;&#x5206;&#x4E3A;&#x4E24;&#x79CD;&#x5F62;&#x5F0F;&#xFF1A;</p><ul class="simple"><li>&#x6574;&#x4F53;&#x8BBE;&#x8BA1;&#x6CA1;&#x6709;&#x5C42;&#x6B21;&#x4E4B;&#x5206;&#xFF0C;&#x4F46;&#x4E5F;&#x6709;&#x72EC;&#x7ACB;&#x7684;&#x5B50;&#x6A21;&#x5757;&#xFF0C;&#x5B50;&#x6A21;&#x5757;&#x5F7C;&#x6B64;&#x4E4B;&#x95F4;&#x8026;&#x5408;&#x751A;&#x5C11;&#xFF0C;&#x8FD9;&#x4E9B;&#x5B50;&#x6A21;&#x5757;
&#x6784;&#x6210;&#x4E86;&#x4E00;&#x4E2A;&#x8F6F;&#x4EF6;&#x5C42;&#xFF0C;&#x5171;&#x540C;&#x4E3A;&#x4E0A;&#x5C42;&#x5E94;&#x7528;&#x63D0;&#x4F9B;&#x670D;&#x52A1;&#xFF1B;</li><li>&#x6574;&#x4E2A;&#x5E93;/&#x8F6F;&#x4EF6;&#x62E5;&#x6709;&#x660E;&#x663E;&#x7684;&#x5C42;&#x6B21;&#x4E4B;&#x5206;&#xFF0C;&#x4ECE;&#x6700;&#x5E95;&#x5C42;&#xFF0C;&#x4E0E;&#x5E94;&#x7528;&#x4E1A;&#x52A1;&#x6BEB;&#x65E0;&#x76F8;&#x5173;&#x7684;&#x4E00;&#x5C42;&#xFF0C;&#x5230;&#x6700;&#x9876;&#x5C42;&#xFF0C;
&#x5B8C;&#x5168;&#x5BF9;&#x5E94;&#x7528;&#x8FDB;&#x884C;&#x76F4;&#x63A5;&#x5B9E;&#x73B0;&#x7684;&#x90A3;&#x4E00;&#x5C42;&#xFF0C;&#x6BCF;&#x4E00;&#x4E2A;&#x76F8;&#x5BF9;&#x9AD8;&#x5C42;&#x7684;&#x8F6F;&#x4EF6;&#x5C42;&#x4F9D;&#x8D56;&#x4E8E;&#x66F4;&#x5E95;&#x5C42;&#x7684;&#x8F6F;&#x4EF6;&#x5C42;&#xFF0C;
&#x9010;&#x5C42;&#x6784;&#x5EFA;&#x3002;</li></ul><p>&#x4E0A;&#x8FF0;&#x4E24;&#x79CD;&#x5F62;&#x5F0F;&#x5E76;&#x975E;&#x5B8C;&#x5168;&#x5206;&#x79BB;&#xFF0C;&#x5728;&#x5206;&#x5C42;&#x8BBE;&#x8BA1;&#x4E2D;&#xFF0C;&#x67D0;&#x4E00;&#x5C42;&#x8F6F;&#x4EF6;&#x5C42;&#x4E5F;&#x53EF;&#x80FD;&#x7531;&#x82E5;&#x5E72;&#x4E2A;&#x72EC;&#x7ACB;&#x7684;&#x6A21;&#x5757;&#x6784;&#x6210;
&#x3002;&#x53E6;&#x4E00;&#x65B9;&#x9762;&#xFF0C;&#x8FD9;&#x91CC;&#x4E5F;&#x4E0D;&#x4F1A;&#x7EDD;&#x5BF9;&#x8BF4;&#x4F4E;&#x5C42;&#x6A21;&#x5757;&#x5C31;&#x5B8C;&#x5168;&#x4E0D;&#x4F9D;&#x8D56;&#x4E8E;&#x9AD8;&#x5C42;&#x6A21;&#x5757;&#x3002;&#x8FD9;&#x79CD;&#x53CC;&#x5411;&#x4F9D;&#x8D56;&#x7EDD;&#x5BF9;&#x4E0D;&#x662F;
&#x597D;&#x7684;&#x8BBE;&#x8BA1;&#xFF0C;&#x4F46;&#x4E8B;&#x5B9E;&#x4E0A;&#x6211;&#x4EEC;&#x672C;&#x6765;&#x5C31;&#x65E0;&#x6CD5;&#x505A;&#x51FA;&#x5B8C;&#x7F8E;&#x7684;&#x8BBE;&#x8BA1;&#x3002;</p><p>&#x672C;&#x6587;&#x5C06;&#x4EE3;&#x7801;&#x5206;&#x5C42;&#x5206;&#x4E3A;&#x4E24;&#x5927;&#x7C7B;&#xFF1A;&#x4E00;&#x662F;&#x72ED;&#x4E49;&#x4E0A;&#x7684;&#x5206;&#x5C42;&#xFF0C;&#x8FD9;&#x79CD;&#x5206;&#x5C42;&#x4E00;&#x822C;&#x4F34;&#x6709;&#x6587;&#x4EF6;&#x5F62;&#x5F0F;&#x4E0A;&#x7684;&#x8868;&#x73B0;&#xFF1B;&#x4E00;
&#x662F;&#x5E7F;&#x4E49;&#x4E0A;&#x7684;&#x5206;&#x5C42;&#xFF0C;&#x5B8C;&#x5168;&#x7740;&#x773C;&#x4E8E;&#x6211;&#x4EEC;&#x5E73;&#x65F6;&#x5199;&#x7684;&#x4EE3;&#x7801;&#x3002;</p><div id="id2" class="section"><h1>&#x8F6F;&#x4EF6;&#x5206;&#x5C42;</h1><p>&#x8F6F;&#x4EF6;&#x5206;&#x5C42;&#x4E00;&#x822C;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x5728;&#x5F88;&#x591A;&#x5927;&#x578B;&#x8F6F;&#x4EF6;/&#x5E93;&#x7684;&#x7ED3;&#x6784;&#x56FE;&#x4E2D;&#x770B;&#x5230;&#x3002;&#x8FD9;&#x4E9B;&#x5206;&#x5C42;&#x6BCF;&#x4E00;&#x5C42;&#x672C;&#x8EAB;&#x5C31;&#x5305;&#x542B;&#x5927;
&#x91CF;&#x4EE3;&#x7801;&#x3002;&#x6BCF;&#x4E2A;&#x6A21;&#x5757;&#xFF0C;&#x6BCF;&#x4E00;&#x4E2A;&#x8F6F;&#x4EF6;&#x5C42;&#x90FD;&#x53EF;&#x80FD;&#x88AB;&#x5B9E;&#x73B0;&#x4E3A;&#x4E00;&#x4E2A;&#x8FD0;&#x884C;&#x65F6;&#x5E93;&#xFF0C;&#x6216;&#x8005;&#x5176;&#x4ED6;&#x4EE5;&#x6587;&#x4EF6;&#x5F62;&#x5F0F;&#x4E3A;
&#x8868;&#x73B0;&#x7684;&#x4E1C;&#x897F;&#x3002;</p><div id="example-android" class="section"><h2>Example Android</h2><p>Android&#x662F;Google&#x63A8;&#x51FA;&#x7684;&#x667A;&#x80FD;&#x624B;&#x673A;&#x64CD;&#x4F5C;&#x7CFB;&#x7EDF;&#xFF0C;&#x5728;&#x5176;&#x5B98;&#x65B9;&#x6587;&#x6863;&#x4E2D;&#x6709;Android&#x7684;&#x7CFB;&#x7EDF;&#x67B6;&#x6784;&#x56FE;&#xFF1A;</p><img src="http://www.cppblog.com/images/cppblog_com/kevinlynx/cl-writer/201145101241/android-architecture.jpg" alt="imgs/android-architecture.jpg"></img><p>&#x8FD9;&#x5E45;&#x56FE;&#x4E2D;&#x5F88;&#x597D;&#x5730;&#x53CD;&#x6620;&#x4E86;&#x4E0A;&#x6587;&#x4E2D;&#x63D0;&#x5230;&#x7684;&#x8F6F;&#x4EF6;&#x5C42;&#x6B21;&#x3002;&#x6574;&#x4E2A;&#x7CFB;&#x7EDF;&#x4ECE;&#x5E95;&#x5C42;&#x5230;&#x9AD8;&#x5C42;&#x5206;&#x4E3A;Linux kernel&#xFF0C;
Libraries/Runtime&#xFF0C;Application Framework&#xFF0C;Applications&#x3002;&#x6700;&#x5E95;&#x5C42;&#x7684;Kernel&#x53EF;&#x4EE5;&#x8BF4;&#x4E0E;&#x5E94;
&#x7528;&#x5B8C;&#x5168;&#x4E0D;&#x76F8;&#x5173;&#xFF0C;&#x76F4;&#x5230;&#x6700;&#x4E0A;&#x5C42;&#x7684;Applications&#xFF0C;&#x624D;&#x63D0;&#x4F9B;&#x624B;&#x673A;&#x8BF8;&#x5982;&#x8054;&#x7CFB;&#x4EBA;&#x3001;&#x6253;&#x7535;&#x8BDD;&#x7B49;&#x5E94;&#x7528;&#x529F;&#x80FD;&#x3002;</p><p>&#x6BCF;&#x4E00;&#x5C42;&#x4E2D;&#xFF0C;&#x53C8;&#x53EF;&#x80FD;&#x5206;&#x4E3A;&#x82E5;&#x5E72;&#x76F8;&#x4E92;&#x72EC;&#x7ACB;&#xFF08;Again&#xFF0C;&#x6CA1;&#x6709;&#x7EDD;&#x5BF9;&#xFF09;&#x7684;&#x6A21;&#x5757;&#xFF0C;&#x4F8B;&#x5982;Libraries&#x90A3;&#x4E00;&#x5C42;
&#x4E2D;&#xFF0C;&#x5C31;&#x5305;&#x542B;&#x8BF8;&#x5982;Surface manager/SGL&#x7B49;&#x6A21;&#x5757;&#x3002;&#x5B83;&#x4EEC;&#x53EF;&#x80FD;&#x90FD;&#x4F9D;&#x8D56;&#x4E8E;Kernel&#xFF0C;&#x5E76;&#x4E14;&#x63D0;&#x4F9B;&#x63A5;&#x53E3;&#x7ED9;
&#x4E0A;&#x5C42;&#xFF0C;&#x4F46;&#x5F7C;&#x6B64;&#x72EC;&#x7ACB;&#x3002;</p></div><div id="example-compiler" class="section"><h2>Example Compiler</h2><p>&#x5728;&#x7F16;&#x8BD1;&#x5668;&#x5B9E;&#x73B0;&#x4E2D;&#xFF0C;&#x4E5F;&#x6709;&#x975E;&#x5E38;&#x660E;&#x663E;&#x7684;&#x5C42;&#x6B21;&#x4E4B;&#x5206;&#x3002;&#x8FD9;&#x4E9B;&#x5C42;&#x6B21;&#x53EF;&#x4EE5;&#x5B8C;&#x5168;&#x6309;&#x7167;&#x7F16;&#x8BD1;&#x539F;&#x7406;&#x7406;&#x8BBA;&#x6765;&#x5212;&#x5206;&#x3002;
&#x5305;&#x62EC;&#xFF1A;</p><ul class="simple"><li>&#x8BCD;&#x6CD5;&#x5206;&#x6790;&#xFF1A;&#x5C06;&#x6587;&#x672C;&#x4EE3;&#x7801;&#x62C6;&#x5206;&#x4E3A;&#x4E00;&#x4E2A;&#x4E00;&#x4E2A;&#x5408;&#x6CD5;&#x7684;&#x5355;&#x8BCD;</li><li>&#x8BED;&#x6CD5;&#x5206;&#x6790;&#xFF1A;&#x57FA;&#x4E8E; <em>&#x8BCD;&#x6CD5;&#x5206;&#x6790;</em> &#x5F97;&#x5230;&#x7684;&#x5355;&#x8BCD;&#x6D41;&#x6784;&#x5EFA;&#x8BED;&#x6CD5;&#x6811;</li><li>&#x8BED;&#x4E49;&#x5206;&#x6790;&#xFF1A;&#x57FA;&#x4E8E; <em>&#x8BED;&#x6CD5;&#x5206;&#x6790;</em> &#x5F97;&#x5230;&#x7684;&#x8BED;&#x6CD5;&#x6811;&#x8FDB;&#x884C;&#x8BED;&#x4E49;&#x4E0A;&#x7684;&#x68C0;&#x67E5;&#x7B49;</li><li>&#x751F;&#x6210;&#x5668;&#xFF1A;&#x57FA;&#x4E8E; <em>&#x8BED;&#x4E49;&#x5206;&#x6790;</em> &#x7ED3;&#x679C;&#xFF08;&#x53EF;&#x80FD;&#x4F9D;&#x7136;&#x662F;&#x8BED;&#x6CD5;&#x6811;&#xFF09;&#x751F;&#x6210;&#x4E2D;&#x95F4;&#x4EE3;&#x7801;</li><li>&#x7F16;&#x8BD1;&#x5668;&#xFF1A;&#x57FA;&#x4E8E; <em>&#x751F;&#x6210;&#x5668;</em> &#x5F97;&#x5230;&#x7684;&#x4E2D;&#x95F4;&#x4EE3;&#x7801;&#x751F;&#x6210;&#x76EE;&#x6807;&#x673A;&#x5668;&#x4E0A;&#x7684;&#x673A;&#x5668;&#x4EE3;&#x7801;</li><li>&#x94FE;&#x63A5;&#x5668;&#xFF1A;&#x57FA;&#x4E8E; <em>&#x7F16;&#x8BD1;&#x5668;</em> &#x751F;&#x6210;&#x7684;&#x76EE;&#x6807;&#x4EE3;&#x7801;&#x94FE;&#x63A5;&#x6210;&#x6700;&#x7EC8;&#x53EF;&#x6267;&#x884C;&#x7A0B;&#x5E8F;</li></ul><p><strong>&#x8F6F;&#x4EF6;&#x5206;&#x5C42;&#x7684;&#x597D;&#x5904;&#x4E4B;&#x4E00;&#x5C31;&#x662F;&#x5BF9;&#x4EFB;&#x52A1;(task)&#x7684;&#x62BD;&#x8C61;&#xFF0C;&#x5C01;&#x88C5;&#x67D0;&#x4E2A;&#x4EFB;&#x52A1;&#x7684;&#x5B9E;&#x73B0;&#x7EC6;&#x8282;&#xFF0C;&#x63D0;&#x4F9B;&#x7ED9;&#x5176;&#x4ED6;
&#x4F9D;&#x8D56;&#x6A21;&#x5757;&#x66F4;&#x53CB;&#x597D;&#x7684;&#x4F7F;&#x7528;&#x63A5;&#x53E3;&#x3002;&#x9694;&#x79BB;&#x5E26;&#x6765;&#x7684;&#x597D;&#x5904;&#x4E4B;&#x4E00;&#x5C31;&#x662F;&#x53EF;&#x8F7B;&#x6613;&#x66FF;&#x6362;&#x67D0;&#x4E2A;&#x5B9E;&#x73B0;&#x3002;</strong> &#x4F8B;&#x5982;&#x5F88;
&#x591A;UI&#x5E93;&#x9694;&#x79BB;&#x4E86;&#x6E32;&#x67D3;&#x5668;&#x7684;&#x5B9E;&#x73B0;&#xFF0C;&#x5728;&#x5B9E;&#x9645;&#x4F7F;&#x7528;&#x8FC7;&#x7A0B;&#x4E2D;&#xFF0C;&#x65E2;&#x53EF;&#x4EE5;&#x4F7F;&#x7528;Direct X&#x7684;&#x6E32;&#x67D3;&#x65B9;&#x5F0F;&#xFF0C;&#x4E5F;&#x53EF;
&#x4EE5;&#x4F7F;&#x7528;OpenGL&#x7684;&#x5B9E;&#x73B0;&#x65B9;&#x5F0F;&#x3002;</p><p>&#x4F46;&#x6B63;&#x5982;&#x4E4B;&#x524D;&#x6240;&#x5F3A;&#x8C03;&#xFF0C;&#x51E1;&#x4E8B;&#x6CA1;&#x6709;&#x7EDD;&#x5BF9;&#xFF0C;&#x51E1;&#x4E8B;&#x4E5F;&#x4E0D;&#x53EF;&#x8FC7;&#x5EA6;&#x3002;&#x5F88;&#x591A;&#x65F6;&#x5019;&#x65E0;&#x6CD5;&#x4FDD;&#x8BC1;&#x8F6F;&#x4EF6;&#x5C42;&#x4E4B;&#x95F4;&#x5C31;&#x662F;&#x5355;
&#x5411;&#x4F9D;&#x8D56;&#x3002;&#x800C;&#x53E6;&#x4E00;&#x4E9B;&#x65F6;&#x5019;&#x8FC7;&#x5EA6;&#x7684;&#x5206;&#x5C42;&#x4E5F;&#x5BFC;&#x81F4;&#x6211;&#x4EEC;&#x7684;&#x7A0B;&#x5E8F;&#x8FC7;&#x4E8E;&#x677E;&#x6563;&#xFF0C;&#x6548;&#x7387;&#x5728;&#x7C98;&#x5408;&#x5C42;&#x4E4B;&#x95F4;&#x7ED5;&#x6765;&#x7ED5;&#x53BB;
&#x800C;&#x6D88;&#x5931;&#x6B86;&#x5C3D;&#x3002;</p></div></div><div id="id3" class="section"><h1>&#x4EE3;&#x7801;&#x5206;&#x5C42;</h1><p>&#x5982;&#x679C;&#x8BF4;&#x8F6F;&#x4EF6;&#x5206;&#x5C42;&#x662F;&#x4ECE;&#x5927;&#x7684;&#x65B9;&#x9762;&#x8BA8;&#x8BBA;&#xFF0C;&#x90A3;&#x4E48;&#x672C;&#x8282;&#x8BF4;&#x7684;&#x4EE3;&#x7801;&#x5206;&#x5C42;&#xFF0C;&#x5219;&#x662F;&#x4ECE;&#x5C0F;&#x5904;&#x5165;&#x624B;&#x3002;&#x800C;&#x8FD9;&#x4E5F;&#x66F4;&#x662F;
&#x8D34;&#x8FD1;&#x6211;&#x4EEC;&#x65E5;&#x5E38;&#x5DE5;&#x4F5C;&#x7684;&#x5730;&#x65B9;&#x3002;&#x672C;&#x8282;&#x8BA8;&#x8BBA;&#x7684;&#x4EE3;&#x7801;&#x5206;&#x5C42;&#xFF0C;&#x4E0D;&#x50CF;&#x8F6F;&#x4EF6;&#x5206;&#x5C42;&#x90A3;&#x6837;&#x5927;&#x3002;&#x6BCF;&#x4E00;&#x5C42;&#x53EF;&#x80FD;&#x5C31;&#x662F;
&#x767E;&#x6765;&#x884C;&#x4EE3;&#x7801;&#xFF0C;&#x51E0;&#x4E2A;&#x63A5;&#x53E3;&#x3002;</p><div id="example-c" class="section"><h2>Example C&#x4E2D;&#x7684;&#x6A21;&#x5757;&#x7EC4;&#x7EC7;</h2><p>&#x5F88;&#x591A;C&#x4EE3;&#x7801;&#x5199;&#x5F97;&#x5C11;&#x7684;C++&#x7A0B;&#x5E8F;&#x5458;&#x751A;&#x81F3;&#x5BF9;&#x4E00;&#x4E2A;&#x5927;&#x578B;C&#x7A0B;&#x5E8F;&#x4E2D;&#x7684;&#x6A21;&#x5757;&#x7EC4;&#x7EC7;&#x6BEB;&#x65E0;&#x6982;&#x5FF5;&#x3002;&#x8FD9;&#x662F;&#x5BF9;&#x5176;&#x4ED6;&#x6280;
&#x672F;&#x63A5;&#x89E6;&#x5C11;&#x5E26;&#x6765;&#x7684;&#x89C6;&#x91CE;&#x72ED;&#x7A84;&#x7684;&#x53EF;&#x6015;&#x7ED3;&#x679C;&#x3002;</p><p>&#x5728;C&#x8BED;&#x8A00;&#x7684;&#x4E16;&#x754C;&#x91CC;&#xFF0C;&#x5E76;&#x4E0D;&#x50CF;&#x67D0;&#x4E9B;C++&#x6559;&#x6750;&#x4E2D;&#x6307;&#x51FA;&#x7684;&#x90A3;&#x6837;&#xFF0C;&#x5E03;&#x6EE1;&#x5168;&#x5C40;&#x53D8;&#x91CF;&#x3002;&#x5F53;&#x7136;&#x5168;&#x5C40;&#x53D8;&#x91CF;&#x7684;&#x4F7F;
&#x7528;&#x4E5F;&#x5E76;&#x4E0D;&#x662F;&#x7CDF;&#x7CD5;&#x8BBE;&#x8BA1;&#x7684;&#x6807;&#x5FD7;(goto&#x4E0D;&#x662F;&#x9B54;&#x9B3C;)&#x3002;&#x4E00;&#x4E2A;&#x826F;&#x597D;&#x8BBE;&#x8BA1;&#x7684;C&#x8BED;&#x8A00;&#x7A0B;&#x5E8F;&#x61C2;&#x5F97;&#x5982;&#x4F55;&#x53BB;&#x62BD;&#x8C61;&#x3001;
&#x5C01;&#x88C5;&#x6A21;&#x5757;/&#x8F6F;&#x4EF6;&#x5C42;&#x3002;&#x6211;&#x4EEC;&#x4EE5;Lua&#x7684;&#x6E90;&#x4EE3;&#x7801;&#x4E3A;&#x4F8B;&#x3002;</p><p>lua.h&#x6587;&#x4EF6;&#x662F;&#x66B4;&#x9732;&#x7ED9;Lua&#x5E94;&#x7528;&#xFF08;Lua&#x4F7F;&#x7528;&#x8005;&#xFF09;&#x7684;&#x76F4;&#x63A5;&#x4FE1;&#x606F;&#x6E90;&#x3002;&#x63A5;&#x89E6;&#x8FC7;Lua&#x7684;&#x4EBA;&#x90FD;&#x77E5;&#x9053;&#x6709;&#x4E2A;&#x7ED3;&#x6784;&#x4F53;
&#x53EB;lua_State&#x3002;&#x4F46;&#x662F;lua.h&#x4E2D;&#x5E76;&#x6CA1;&#x6709;&#x66B4;&#x9732;&#x8FD9;&#x4E2A;&#x7ED3;&#x6784;&#x4F53;&#x7684;&#x5B9E;&#x73B0;&#x3002;&#x56E0;&#x4E3A;&#x4E00;&#x65E6;&#x66B4;&#x9732;&#x4E86;&#x5B9E;&#x73B0;&#xFF0C;&#x4F7F;&#x7528;&#x8005;&#x5C31;
&#x53EF;&#x80FD;&#x4F1A;&#x968F;&#x610F;&#x4F7F;&#x7528;&#x5176;&#x7ED3;&#x6784;&#x4F53;&#x6210;&#x5458;&#xFF0C;&#x800C;&#x8FD9;&#x5E76;&#x4E0D;&#x662F;&#x5E93;&#x8BBE;&#x8BA1;&#x8005;&#x6240;&#x5E0C;&#x671B;&#x7684;&#x3002; <strong>&#x5C01;&#x88C5;&#x6570;&#x636E;&#x7684;&#x5B9E;&#x73B0;&#xFF0C;&#x4E5F;&#x7B97;
&#x662F;&#x6784;&#x5EFA;&#x6A21;&#x5757;&#x5316;&#x7A0B;&#x5E8F;&#x7684;&#x4E00;&#x79CD;&#x65B9;&#x6CD5;&#x3002;</strong></p><p>&#x5927;&#x5BB6;&#x90FD;&#x77E5;&#x9053;&#x66B4;&#x9732;&#x5728;&#x5934;&#x6587;&#x4EF6;&#x4E2D;&#x7684;&#x4FE1;&#x606F;&#xFF0C;&#x5219;&#x53EF;&#x80FD;&#x88AB;&#x5F53;&#x4F5C;&#x8BE5;&#x5934;&#x6587;&#x4EF6;&#x6240;&#x63CF;&#x8FF0;&#x6A21;&#x5757;&#x7684;&#x63A5;&#x53E3;&#x63CF;&#x8FF0;&#x3002;&#x6240;&#x4EE5;&#xFF0C;
&#x5728;C&#x8BED;&#x8A00;&#x4E2D;&#x4EFB;&#x4F55;&#x7F6E;&#x4E8E;&#x5934;&#x6587;&#x4EF6;&#x4E2D;&#x7684;&#x4FE1;&#x606F;&#x90FD;&#x9700;&#x8981;&#x614E;&#x91CD;&#x8003;&#x8651;&#x3002;</p><p>&#x76F8;&#x5BF9;&#x7684;&#xFF0C;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x5728;&#x5F88;&#x591A;.c&#x6587;&#x4EF6;&#x4E2D;&#x770B;&#x5230;&#x5F88;&#x591A;static&#x51FD;&#x6570;&#x3002;&#x4F8B;&#x5982;lstate.c&#x4E2D;&#x7684;stack_init&#x3002;
static&#x7528;&#x4E8E;&#x9650;&#x5B9A;&#x5176;&#x4FEE;&#x9970;&#x5BF9;&#x8C61;&#x7684;&#x4F5C;&#x7528;&#x57DF;&#xFF0C;&#x7528;&#x5B83;&#x53BB;&#x4FEE;&#x9970;&#x67D0;&#x4E2A;&#x51FD;&#x6570;&#xFF0C;&#x65E8;&#x5728;&#x544A;&#x8BC9;&#xFF1A;&#x8FD9;&#x4E2A;&#x51FD;&#x6570;&#x4EC5;&#x88AB;&#x5F53;&#x524D;&#x6587;&#x4EF6;&#xFF08;
&#x6A21;&#x5757;&#xFF09;&#x4F7F;&#x7528;&#xFF0C;&#x5B83;&#x4EC5;&#x7528;&#x4E8E;&#x672C;&#x6A21;&#x5757;&#x5B9E;&#x73B0;&#x6240;&#x4F9D;&#x8D56;&#xFF0C;&#x5B83;&#x4E0D;&#x662F;&#x63D0;&#x4F9B;&#x7ED9;&#x6A21;&#x5757;&#x5916;&#x7684;&#x63A5;&#x53E3;&#xFF01; <strong>&#x5C01;&#x88C5;&#x5185;&#x90E8;&#x5B9E;&#x73B0;
&#xFF0C;&#x66B4;&#x9732;&#x591F;&#x7528;&#x7684;&#x63A5;&#x53E3;&#xFF0C;&#x4E5F;&#x662F;&#x4FDD;&#x6301;&#x6A21;&#x5757;&#x6E05;&#x6670;&#x7684;&#x65B9;&#x5F0F;&#x4E4B;&#x4E00;&#x3002;</strong></p><p>&#x826F;&#x597D;&#x7684;&#x8BED;&#x8A00;&#x66F4;&#x61C2;&#x5F97;&#x5BF9;&#x7A0B;&#x5E8F;&#x5458;&#x505A;&#x4E00;&#x79CD;&#x826F;&#x597D;&#x8BBE;&#x8BA1;&#x7684;&#x5BFC;&#x5411;&#x3002;&#x4F46;&#x76F8;&#x5BF9;&#x800C;&#x8A00;&#xFF0C;C&#x8BED;&#x8A00;&#x8F83;&#x7F3A;&#x4E4F;&#x8FD9;&#x65B9;&#x9762;&#x7684;&#x8BED;
&#x8A00;&#x673A;&#x5236;&#x3002;&#x5728;C&#x8BED;&#x8A00;&#x4E2D;&#xFF0C;&#x826F;&#x597D;&#x7684;&#x8BBE;&#x8BA1;&#x66F4;&#x4F9D;&#x8D56;&#x4E8E;&#x7A0B;&#x5E8F;&#x5458;&#x81EA;&#x5DF1;&#x7684;&#x529F;&#x5E95;&#x3002;</p></div><div id="example-java" class="section"><h2>Example Java&#x4E2D;&#x7684;&#x6A21;&#x5757;&#x7EC4;&#x7EC7;</h2><p>&#x76F8;&#x8F83;&#x800C;&#x8A00;&#xFF0C;Java&#x8BED;&#x8A00;&#x5219;&#x63D0;&#x4F9B;&#x4E86;&#x6A21;&#x5757;&#x5316;&#x8BBE;&#x8BA1;&#x7684;&#x8BED;&#x6CD5;&#x673A;&#x5236;&#x3002;&#x5728;Java&#x4E2D;&#xFF0C;&#x5982;&#x540C;&#x5927;&#x90E8;&#x5206;&#x8BED;&#x8A00;&#x4E00;&#x6837;&#xFF0C;&#x4E00;
&#x822C;&#x4E00;&#x4E2A;&#x4EE3;&#x7801;&#x6587;&#x4EF6;&#x5BF9;&#x5E94;&#x4E8E;&#x4E00;&#x4E2A;&#x4EE3;&#x7801;&#x6A21;&#x5757;&#x3002;&#x800C;&#x5728;Java&#x4E2D;&#xFF0C;&#x6BCF;&#x4E2A;&#x6587;&#x4EF6;&#x5185;&#x53EA;&#x80FD;&#x6709;&#x4E00;&#x4E2A;public class&#x3002;
public class&#x4F5C;&#x4E3A;&#x8BE5;&#x6A21;&#x5757;&#x7684;&#x5BF9;&#x5916;&#x63A5;&#x53E3;&#x3002;&#x800C;&#x5728;&#x6A21;&#x5757;&#x5185;&#x90E8;&#xFF0C;&#x5219;&#x53EF;&#x80FD;&#x6709;&#x5F88;&#x591A;&#x5176;&#x4ED6;&#x8F85;&#x52A9;&#x5B9E;&#x73B0;&#x7684;class
&#xFF0C;&#x4F46;&#x5B83;&#x4EEC;&#x65E0;&#x6CD5;&#x88AB;&#x5916;&#x90E8;&#x6A21;&#x5757;&#x8BBF;&#x95EE;&#x3002;&#x8FD9;&#x662F;&#x8BED;&#x8A00;&#x63D0;&#x4F9B;&#x7684;&#x5C01;&#x88C5;&#x673A;&#x5236;&#xFF0C;&#x4E00;&#x79CD;&#x5BF9;&#x7A0B;&#x5E8F;&#x5458;&#x7684;&#x5BFC;&#x5411;&#x3002;</p></div><div id="example-oo" class="section"><h2>Example OO&#x8BED;&#x8A00;&#x4E2D;&#x7C7B;&#x63A5;&#x53E3;&#x8BBE;&#x8BA1;</h2><p>&#x65E0;&#x8BBA;&#x5728;C++&#x4E2D;&#xFF0C;&#x8FD8;&#x662F;&#x5728;Java&#x4E2D;&#xFF0C;&#x4E00;&#x4E2A;&#x7C7B;&#x4E2D;&#x7684;&#x63A5;&#x53E3;&#xFF0C;&#x90FD;&#x5927;&#x81F4;&#x6709;&#x5404;&#x79CD;&#x8BBF;&#x95EE;&#x6743;&#x9650;&#x3002;&#x4F8B;&#x5982;public&#x3001;
private&#x3001;protected&#x3002;&#x8BBF;&#x95EE;&#x6743;&#x9650;&#x7684;&#x52A0;&#x5165;&#x65E8;&#x5728;&#x66F4;&#x7CBE;&#x786E;&#x5730;&#x66B4;&#x9732;&#x6A21;&#x5757;&#x63A5;&#x53E3;&#xFF0C;&#x9690;&#x85CF;&#x7EC6;&#x8282;&#x3002;</p><p>&#x5728;C&#x4E2D;&#x8F83;&#x4E3A;&#x7F3A;&#x4E4F;&#x7C7B;&#x4F3C;&#x7684;&#x673A;&#x5236;&#xFF0C;&#x4F46;&#x4F9D;&#x7136;&#x53EF;&#x4EE5;&#x8FD9;&#x6837;&#x505A;&#x3002;&#x4F8B;&#x5982;&#x5C06;&#x7ED3;&#x6784;&#x4F53;&#x5B9A;&#x4E49;&#x4E8E;.c&#x6587;&#x4EF6;&#x4E2D;&#xFF0C;&#x5C06;&#x975E;
&#x63A5;&#x53E3;&#x51FD;&#x6570;&#x4EE5;static&#x7684;&#x65B9;&#x5F0F;&#x5B9E;&#x73B0;&#x4E8E;.c&#x6587;&#x4EF6;&#x4E2D;&#x3002;</p><p>OO&#x8BED;&#x8A00;&#x4E2D;&#x7684;&#x8FD9;&#x4E9B;&#x8BBF;&#x95EE;&#x6743;&#x9650;&#x5173;&#x952E;&#x5B57;&#x7684;&#x5E94;&#x7528;&#x5C24;&#x4E3A;&#x91CD;&#x8981;&#x3002;C++&#x65B0;&#x624B;&#x4EEC;&#x5F80;&#x5F80;&#x4E0D;&#x77E5;&#x9053;&#x54EA;&#x4E9B;&#x6210;&#x5458;&#x8BE5;public
&#xFF0C;&#x54EA;&#x4E9B;&#x8BE5;private&#x3002;C++&#x719F;&#x624B;&#x4EEC;&#x5728;&#x4E0D;&#x5228;&#x6839;&#x6316;&#x5E95;&#x7684;&#x60C5;&#x51B5;&#x4E0B;&#xFF0C;&#x751A;&#x81F3;&#x4F1A;&#x5BF9;&#x6BCF;&#x4E2A;&#x6570;&#x636E;&#x6210;&#x5458;&#x5199;&#x51FA;get/set
&#x63A5;&#x53E3;&#xFF08;&#x90A3;&#x8FD8;&#x4E0D;&#x5982;&#x76F4;&#x63A5;public&#xFF09;&#x3002;&#x5728;public/private&#x4E4B;&#x95F4;&#xFF0C;&#x6211;&#x4EEC;&#x9700;&#x8981;&#x505A;&#x7684;&#x552F;&#x4E00;&#x51B3;&#x7B56;&#x5C31;&#x662F;&#xFF0C;&#x54EA;&#x4E9B;
&#x6570;&#x636E;/&#x64CD;&#x4F5C;&#x5E76;&#x975E;&#x5916;&#x90E8;&#x6A21;&#x5757;&#x6240;&#x9700;&#x3002;&#x5982;&#x679C;&#x5916;&#x90E8;&#x6A21;&#x5757;&#x4E0D;&#x9700;&#x8981;&#xFF0C;&#x751A;&#x81F3;&#x76EE;&#x524D;&#x4E0D;&#x9700;&#x8981;&#xFF0C;&#x90A3;&#x4E48;&#x6B64;&#x523B;&#xFF0C;&#x90FD;&#x4E0D;&#x8981;
&#x5C06;&#x5176;public&#x3002;&#x4E00;&#x4E2A;public&#x4FE1;&#x606F;&#x5C11;&#x7684;class&#xFF0C;&#x5F80;&#x5F80;&#x662F;&#x4E00;&#x4E2A;&#x88AB;&#x4F7F;&#x7528;&#x8005;&#x66F4;&#x559C;&#x6B22;&#x7684;class&#x3002;</p><p>&#xFF08;&#x81F3;&#x4E8E;protected&#xFF0C;&#x5219;&#x662F;&#x7528;&#x4E8E;&#x7EE7;&#x627F;&#x4F53;&#x7CFB;&#x4E4B;&#x95F4;&#xFF0C;&#x7C7B;&#x4E4B;&#x95F4;&#x7684;&#x4FE1;&#x606F;&#x9690;&#x85CF;&#x3002;&#xFF09;</p></div><div id="example-lisp" class="section"><h2>Example Lisp&#x4E2D;&#x7684;&#x6A21;&#x5757;&#x8BBE;&#x8BA1;</h2><p>&#x53C8;&#x5F97;&#x63D0;&#x63D0;Lisp&#x3002;</p><p>&#x57FA;&#x4E8E;&#x4E0A;&#x6587;&#xFF0C;&#x6211;&#x4EEC;&#x53D1;&#x73B0;&#x4E86;&#x5404;&#x79CD;&#x5212;&#x5206;&#x6A21;&#x5757;&#x3001;&#x5212;&#x5206;&#x4EE3;&#x7801;&#x5C42;&#x7684;&#x65B9;&#x5F0F;&#xFF0C;&#x65E0;&#x8BBA;&#x662F;&#x8BED;&#x8A00;&#x63D0;&#x4F9B;&#xFF0C;&#x8FD8;&#x662F;&#x7A0B;&#x5E8F;&#x5458;&#x81EA;
&#x5DF1;&#x7684;&#x5E94;&#x7528;&#x3002;&#x4F46;&#x662F;&#x5982;&#x4F55;&#x9010;&#x4E2A;&#x5730;&#x6784;&#x5EFA;&#x8FD9;&#x4E9B;&#x5C42;&#x6B21;&#x5462;&#xFF1F;</p><p>Lisp&#x4E2D;&#x5021;&#x5BFC;&#x4E86;&#x4E00;&#x79CD;&#x66F4;&#x80FD;&#x4F53;&#x73B0;&#x8FD9;&#x79CD;&#x5C06;&#x4EE3;&#x7801;&#x5206;&#x5C42;&#x7684;&#x65B9;&#x5F0F;&#xFF1A;&#x81EA;&#x5E95;&#x800C;&#x4E0A;&#x5730;&#x6784;&#x5EFA;&#x4EE3;&#x7801;&#x3002;&#x8FD9;&#x4E2A;&#x81EA;&#x5E95;&#x800C;&#x4E0A;&#xFF0C;
&#x81EA;&#x7136;&#x662F;&#x6309;&#x7167;&#x8F6F;&#x4EF6;&#x5C42;&#x7684;&#x9AD8;&#x4F4E;&#x4E4B;&#x5206;&#x800C;&#x8A00;&#x3002;&#x8FD9;&#x4E2A;&#x8FC7;&#x7A0B;&#x5C31;&#x50CF;&#x4E0A;&#x6587;&#x4E3E;&#x7684;&#x7F16;&#x8BD1;&#x539F;&#x7406;&#x4F8B;&#x5B50;&#x4E00;&#x6837;&#x3002;&#x6211;&#x4EEC;&#x5148;&#x7F16;&#x5199;
&#x8BCD;&#x6CD5;&#x5206;&#x6790;&#x6A21;&#x5757;&#xFF0C;&#x8BE5;&#x6A21;&#x5757;&#x53EF;&#x80FD;&#x4EC5;&#x66B4;&#x9732;&#x4E00;&#x4E2A;&#x63A5;&#x53E3;&#xFF1A;get-token&#x3002;&#x7136;&#x540E;&#x53EF;&#x4EE5;&#x7ACB;&#x9A6C;&#x5BF9;&#x8BE5;&#x6A21;&#x5757;&#x8FDB;&#x884C;&#x529F;&#x80FD;
&#x6D4B;&#x8BD5;&#x3002;&#x7136;&#x540E;&#x518D;&#x7F16;&#x5199;&#x8BED;&#x6CD5;&#x5206;&#x6790;&#x6A21;&#x5757;&#xFF0C;&#x8BE5;&#x6A21;&#x5757;&#x4E5F;&#x53EF;&#x80FD;&#x53EA;&#x66B4;&#x9732;&#x4E00;&#x4E2A;&#x63A5;&#x53E3;&#xFF1A;parse&#x3002;&#x8BED;&#x6CD5;&#x5206;&#x6790;&#x6A21;&#x5757;&#x5EFA;
&#x7ACB;&#x4E8E;&#x8BCD;&#x6CD5;&#x5206;&#x6790;&#x6A21;&#x5757;&#x4E4B;&#x4E0A;&#x3002;&#x56E0;&#x4E3A;&#x6211;&#x4EEC;&#x4E4B;&#x524D;&#x5DF2;&#x7ECF;&#x5BF9;&#x8BCD;&#x6CD5;&#x5206;&#x6790;&#x6A21;&#x5757;&#x8FDB;&#x884C;&#x8FC7;&#x6D4B;&#x8BD5;&#xFF0C;&#x6240;&#x4EE5;&#x5BF9;&#x8BED;&#x6CD5;&#x5206;&#x6790;&#x7684;
&#x6D4B;&#x8BD5;&#x4E5F;&#x53EF;&#x4EE5;&#x7ACB;&#x5373;&#x8FDB;&#x884C;&#x3002;&#x5982;&#x6B64;&#x4E0B;&#x53BB;&#xFF0C;&#x76F4;&#x81F3;&#x6784;&#x5EFA;&#x51FA;&#x6574;&#x4E2A;&#x7A0B;&#x5E8F;&#x3002;</p><p>&#x6BCF;&#x4E00;&#x4E2A;&#x4EE3;&#x7801;&#x5C42;&#x90FD;&#x4F1A;&#x63D0;&#x4F9B;&#x82E5;&#x5E72;&#x63A5;&#x53E3;&#x7ED9;&#x4E0A;&#x5C42;&#x6A21;&#x5757;&#x3002;&#x8D8A;&#x4E0A;&#x5C42;&#x7684;&#x6A21;&#x5757;&#x4E2D;&#xFF0C;&#x5C31;&#x66F4;&#x8D34;&#x8FD1;&#x4E8E;&#x6700;&#x7EC8;&#x76EE;&#x6807;&#x3002;&#x6BCF;&#x4E00;
&#x5C42;&#x90FD;&#x611F;&#x89C9;&#x662F;&#x5EFA;&#x7ACB;&#x5728;&#x65B0;&#x7684;&#x201C;&#x8BED;&#x8A00;&#x201C;&#x4E4B;&#x4E0A;&#x3002;&#x6309;&#x7167;&#x8FD9;&#x79CD;&#x601D;&#x60F3;&#xFF0C;&#x6700;&#x7EC8;&#x6211;&#x4EEC;&#x5C31;&#x53EF;&#x4EE5;&#x6784;&#x5EFA;&#x51FA;DSL&#xFF0C;&#x5373;Domain
Specific Language&#x3002;</p></div><div id="id4" class="section"><h2>&#x5206;&#x5C42;&#x7684;&#x597D;&#x5904;</h2><p>&#x57FA;&#x4E8E;&#x4EE5;&#x4E0A;&#xFF0C;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x603B;&#x7ED3;&#x5F88;&#x591A;&#x4EE3;&#x7801;&#x5206;&#x5C42;&#x7684;&#x597D;&#x5904;&#xFF0C;&#x5B83;&#x4EEC;&#x5305;&#x62EC;&#xFF08;&#x4F46;&#x4E0D;&#x9650;&#x4E8E;&#xFF09;&#xFF1A;</p><ul class="simple"><li>&#x9690;&#x85CF;&#x7EC6;&#x8282;&#xFF0C;&#x63D0;&#x4F9B;&#x62BD;&#x8C61;&#xFF0C;&#x9690;&#x85CF;&#x7684;&#x7EC6;&#x8282;&#x5305;&#x62EC;&#x6570;&#x636E;&#x7684;&#x8868;&#x793A;&#xFF08;&#x5982;lua_State&#xFF09;&#x3001;&#x529F;&#x80FD;&#x7684;&#x5B9E;&#x73B0;</li><li>&#x5728;&#x65B0;&#x7684;&#x4E00;&#x5C42;&#x5EFA;&#x7ACB;&#x66F4;&#x9AD8;&#x5C42;&#x7684;&#x201C;&#x8BED;&#x8A00;&#x201D;</li><li>&#x63A5;&#x53E3;&#x6E05;&#x6670;&#xFF0C;&#x4FEE;&#x6539;&#x7EF4;&#x62A4;&#x65B9;&#x4FBF;</li><li>&#x65B9;&#x4FBF;&#x5F00;&#x53D1;&#xFF0C;&#x5C06;&#x8F6F;&#x4EF6;&#x5206;&#x4E3A;&#x82E5;&#x5E72;&#x5C42;&#x6B21;&#xFF0C;&#x9010;&#x5C42;&#x5B9E;&#x73B0;</li></ul></div><div id="id5" class="section"><h2>&#x4E00;&#x4E2A;&#x95EE;&#x9898;&#x7684;&#x89E3;&#x51B3;</h2><p>&#x6709;&#x65F6;&#x5019;&#xFF0C;&#x6211;&#x4EEC;&#x7684;&#x8F6F;&#x4EF6;&#x5C42;&#x5F88;&#x96BE;&#x505A;&#x5230;&#x5355;&#x5411;&#x4F9D;&#x8D56;&#x3002;&#x8FD9;&#x53EF;&#x80FD;&#x662F;&#x7531;&#x4E8E;&#x524D;&#x671F;&#x8BBE;&#x8BA1;&#x7684;&#x5931;&#x8BEF;&#x5BFC;&#x81F4;&#xFF0C;&#x4E5F;&#x53EF;&#x80FD;&#x786E;&#x5B9E;
&#x662F;&#x60C5;&#x51B5;&#x6240;&#x8FEB;&#x3002;&#x5728;&#x5F88;&#x591A;&#x5E93;&#x4EE3;&#x7801;&#x4E2D;&#xFF0C;&#x4E5F;&#x6709;&#x73B0;&#x6210;&#x7684;&#x4F8B;&#x5B50;&#x3002;&#x4E00;&#x79CD;&#x89E3;&#x51B3;&#x65B9;&#x6CD5;&#x5C31;&#x662F;&#x901A;&#x8FC7;&#x56DE;&#x8C03;&#x3002;&#x56DE;&#x8C03;&#x7684;&#x5B9E;&#x73B0;
&#x65B9;&#x5F0F;&#x53EF;&#x4EE5;&#x662F;&#x56DE;&#x8C03;&#x51FD;&#x6570;&#x3001;&#x591A;&#x6001;&#x3002;&#x591A;&#x6001;&#x7684;&#x8868;&#x73B0;&#x53C8;&#x53EF;&#x80FD;&#x662F;Listener&#x7B49;&#x6A21;&#x5F0F;&#x3002;</p><p>&#x6240;&#x6709;&#x8FD9;&#x4E9B;&#xFF0C;&#x4E3B;&#x8981;&#x662F;&#x8BA9;&#x5E95;&#x5C42;&#x6A21;&#x5757;&#x4E0D;&#x7528;&#x77E5;&#x9053;&#x9AD8;&#x5C42;&#x6A21;&#x5757;&#x3002;&#x5728;&#x4EE3;&#x7801;&#x5C42;&#x6B21;&#x4E0A;&#xFF0C;&#x5B83;&#x4EC5;&#x4EC5;&#x4FDD;&#x5B58;&#x7684;&#x662F;&#x4E00;&#x4E2A;&#x56DE;&#x8C03;
&#x4FE1;&#x606F;&#xFF0C;&#x800C;&#x8FD9;&#x4E2A;&#x4FE1;&#x606F;&#x5177;&#x4F53;&#x662F;&#x4EC0;&#x4E48;&#xFF0C;&#x5219;&#x53D1;&#x751F;&#x5728;&#x8FD0;&#x884C;&#x671F;&#xFF08;&#x8BDD;&#x8BF4;&#x4EE5;&#x524D;&#x7ED9;&#x540C;&#x4E8B;&#x8BB2;&#x8FC7;&#x8FD9;&#x4E2A;&#xFF09;&#x3002;&#x8FD9;&#x6837;&#x5C31;&#x7B80;&#x5355;
&#x907F;&#x514D;&#x4E86;&#x5E95;&#x5C42;&#x6A21;&#x5757;&#x4F9D;&#x8D56;&#x9AD8;&#x5C42;&#x6A21;&#x5757;&#x7684;&#x95EE;&#x9898;&#x3002;</p></div></div><div id="end" class="section"><h1>END</h1><p>&#x7CBE;&#x786E;&#x5730;&#x5B9A;&#x4E49;&#x4E00;&#x4E2A;&#x8F6F;&#x4EF6;&#x4E2D;&#x6709;&#x54EA;&#x4E9B;&#x6A21;&#x5757;&#xFF0C;&#x54EA;&#x4E9B;&#x8F6F;&#x4EF6;&#x5C42;&#x3002;&#x7136;&#x540E;&#x518D;&#x7CBE;&#x786E;&#x5730;&#x5B9A;&#x4E49;&#x6BCF;&#x4E2A;&#x6A21;&#x5757;&#xFF0C;&#x6BCF;&#x4E2A;&#x5934;&#x6587;&#x4EF6;
&#xFF0C;&#x6BCF;&#x4E2A;&#x7C7B;&#x4E2D;&#x54EA;&#x4E9B;&#x4FE1;&#x606F;&#x662F;&#x63D0;&#x4F9B;&#x7ED9;&#x5916;&#x90E8;&#x6A21;&#x5757;&#x7684;&#xFF0C;&#x54EA;&#x4E9B;&#x4FE1;&#x606F;&#x662F;&#x79C1;&#x6709;&#x7684;&#x3002;&#x8FD9;&#x4E9B;&#x8FC7;&#x7A0B;&#x662F;&#x8BBE;&#x8BA1;&#x6A21;&#x5757;&#x5316;&#x7A0B;
&#x5E8F;&#x7684;&#x91CD;&#x8981;&#x65B9;&#x5F0F;&#x3002;</p><p>&#x4F46;&#x9700;&#x8981;&#x91CD;&#x65B0;&#x5F3A;&#x8C03;&#x7684;&#x662F;&#xFF0C;&#x8FC7;&#x4E86;&#x67D0;&#x4E2A;&#x5EA6;&#xFF0C;&#x90A3;&#x53C8;&#x662F;&#x53E6;&#x4E00;&#x79CD;&#x5F62;&#x5F0F;&#x7684;&#x7CDF;&#x7CD5;&#x8BBE;&#x8BA1;&#x3002;&#x4F46;&#x5176;&#x4E2D;&#x62FF;&#x634F;&#x6280;&#x5DE7;&#xFF0C;&#x5219;&#x53EA;
&#x80FD;&#x9760;&#x5B9E;&#x8DF5;&#x83B7;&#x53D6;&#x3002;</p></div></div><img src ="http://www.cppblog.com/kevinlynx/aggbug/143430.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2011-04-05 10:12 <a href="http://www.cppblog.com/kevinlynx/archive/2011/04/05/143430.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>低耦合模块间的通信组件：两个模板</title><link>http://www.cppblog.com/kevinlynx/archive/2009/08/23/94143.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Sun, 23 Aug 2009 01:55:00 GMT</pubDate><guid>http://www.cppblog.com/kevinlynx/archive/2009/08/23/94143.html</guid><wfw:comment>http://www.cppblog.com/kevinlynx/comments/94143.html</wfw:comment><comments>http://www.cppblog.com/kevinlynx/archive/2009/08/23/94143.html#Feedback</comments><slash:comments>18</slash:comments><wfw:commentRss>http://www.cppblog.com/kevinlynx/comments/commentRss/94143.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kevinlynx/services/trackbacks/94143.html</trackback:ping><description><![CDATA[<p style="FONT-SIZE: 10pt"><strong>用途</strong></p>
<p style="FONT-SIZE: 10pt">在一个UI与逻辑模块交互比较多的程序中，因为并不想让两个模块发生太大的耦合，基本目标是<br>可以完全不改代码地换一个UI。逻辑模块需要在产生一些事件后通知到UI模块，并且在这个通知<br>里携带足够多的信息（数据）给接收通知的模块，例如UI模块。逻辑模块还可能被放置于与UI模<br>块不同的线程里。</p>
<p style="FONT-SIZE: 10pt"><strong>最初的结构</strong></p>
<p style="FONT-SIZE: 10pt">最开始我直接采用最简单的方法，逻辑模块保存一个UI模块传过来的listener。当有事件发生时，<br>就回调相应的接口将此通知传出去。大致结构如下：<br></p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img id=Codehighlighter1_1_10_Open_Image onclick="this.style.display='none'; Codehighlighter1_1_10_Open_Text.style.display='none'; Codehighlighter1_1_10_Closed_Image.style.display='inline'; Codehighlighter1_1_10_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_1_10_Closed_Image onclick="this.style.display='none'; Codehighlighter1_1_10_Closed_Text.style.display='none'; Codehighlighter1_1_10_Open_Image.style.display='inline'; Codehighlighter1_1_10_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif"><span style="COLOR: #000000">&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_1_10_Closed_Text>/**/</span><span id=Codehighlighter1_1_10_Open_Text><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;Logic</span><span style="COLOR: #808080"></span></span><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;EventNotify<br><img id=Codehighlighter1_31_101_Open_Image onclick="this.style.display='none'; Codehighlighter1_31_101_Open_Text.style.display='none'; Codehighlighter1_31_101_Closed_Image.style.display='inline'; Codehighlighter1_31_101_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_31_101_Closed_Image onclick="this.style.display='none'; Codehighlighter1_31_101_Closed_Text.style.display='none'; Codehighlighter1_31_101_Open_Image.style.display='inline'; Codehighlighter1_31_101_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif">&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_31_101_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_31_101_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;OnEnterRgn(&nbsp;Player&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">player,&nbsp;</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&nbsp;rgn_id&nbsp;);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">&nbsp;}</span></span><span style="COLOR: #000000">;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><br><img id=Codehighlighter1_106_112_Open_Image onclick="this.style.display='none'; Codehighlighter1_106_112_Open_Text.style.display='none'; Codehighlighter1_106_112_Closed_Image.style.display='inline'; Codehighlighter1_106_112_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_106_112_Closed_Image onclick="this.style.display='none'; Codehighlighter1_106_112_Closed_Text.style.display='none'; Codehighlighter1_106_112_Open_Image.style.display='inline'; Codehighlighter1_106_112_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif">&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_106_112_Closed_Text>/**/</span><span id=Codehighlighter1_106_112_Open_Text><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;UI</span><span style="COLOR: #808080"></span></span><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;EventNotifyImpl&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;EventNotify<br><img id=Codehighlighter1_158_161_Open_Image onclick="this.style.display='none'; Codehighlighter1_158_161_Open_Text.style.display='none'; Codehighlighter1_158_161_Closed_Image.style.display='inline'; Codehighlighter1_158_161_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_158_161_Closed_Image onclick="this.style.display='none'; Codehighlighter1_158_161_Closed_Text.style.display='none'; Codehighlighter1_158_161_Open_Image.style.display='inline'; Codehighlighter1_158_161_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif">&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_158_161_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_158_161_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">&nbsp;}</span></span><span style="COLOR: #000000">;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><br><img id=Codehighlighter1_166_175_Open_Image onclick="this.style.display='none'; Codehighlighter1_166_175_Open_Text.style.display='none'; Codehighlighter1_166_175_Closed_Image.style.display='inline'; Codehighlighter1_166_175_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_166_175_Closed_Image onclick="this.style.display='none'; Codehighlighter1_166_175_Closed_Text.style.display='none'; Codehighlighter1_166_175_Open_Image.style.display='inline'; Codehighlighter1_166_175_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif">&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_166_175_Closed_Text>/**/</span><span id=Codehighlighter1_166_175_Open_Text><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;Logic</span><span style="COLOR: #808080"></span></span><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000">&nbsp;GetEventNotify()</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">OnEnterRgn(&nbsp;player,&nbsp;rgn_id&nbsp;);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span></div>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt">但是，在代码越写越多之后，逻辑模块需要通知的事件越来越多之后，EventNotify这个类开始<br>膨胀：接口变多了、不同接口定义的参数看起来也越来越恶心了。</p>
<p style="FONT-SIZE: 10pt"><strong>改进</strong></p>
<p style="FONT-SIZE: 10pt">于是我决定将各种事件通知统一化：</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;Event<br><img id=Codehighlighter1_13_48_Open_Image onclick="this.style.display='none'; Codehighlighter1_13_48_Open_Text.style.display='none'; Codehighlighter1_13_48_Closed_Image.style.display='inline'; Codehighlighter1_13_48_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_13_48_Closed_Image onclick="this.style.display='none'; Codehighlighter1_13_48_Closed_Text.style.display='none'; Codehighlighter1_13_48_Open_Image.style.display='inline'; Codehighlighter1_13_48_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif"></span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_13_48_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_13_48_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&nbsp;type;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;事件类型</span><span style="COLOR: #008000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"></span><span style="COLOR: #000000">&nbsp;<img src="http://www.cppblog.com/Images/dot.gif">&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;附属参数</span><span style="COLOR: #008000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif"></span><span style="COLOR: #000000">}</span></span><span style="COLOR: #000000">;</span></div>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt">这样，逻辑模块只需要创建事件结构，两个模块间的通信就只需要一个接口即可：</p>
<p style="FONT-SIZE: 10pt">void OnNotify( const Event &amp;event );</p>
<p style="FONT-SIZE: 10pt">但是问题又来了，不同的事件类型携带的附属参数（数据）不一样。也许，可以使用一个序列化<br>的组件，将各种数据先序列化，然后在事件处理模块对应地取数据出来。这样做总感觉有点大动<br>干戈了。当然，也可以使用C语言里的不定参数去解决，如：</p>
<p style="FONT-SIZE: 10pt">void OnNotify( long event_type, ... )</p>
<p style="FONT-SIZE: 10pt">其实，我需要的就是一个可以表面上类型一样，但其内部保存的数据却多样的东西。这样一想，<br>模块就能让事情简单化：</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000">template&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">typename&nbsp;P1,&nbsp;typename&nbsp;P2</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Param<br><img id=Codehighlighter1_48_130_Open_Image onclick="this.style.display='none'; Codehighlighter1_48_130_Open_Text.style.display='none'; Codehighlighter1_48_130_Closed_Image.style.display='inline'; Codehighlighter1_48_130_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_48_130_Closed_Image onclick="this.style.display='none'; Codehighlighter1_48_130_Closed_Text.style.display='none'; Codehighlighter1_48_130_Open_Image.style.display='inline'; Codehighlighter1_48_130_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif"></span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_48_130_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_48_130_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;Param(&nbsp;P1&nbsp;p1,&nbsp;P2&nbsp;p2&nbsp;)&nbsp;:&nbsp;_p1(&nbsp;p1&nbsp;),&nbsp;_p2(&nbsp;p2&nbsp;)<br><img id=Codehighlighter1_105_108_Open_Image onclick="this.style.display='none'; Codehighlighter1_105_108_Open_Text.style.display='none'; Codehighlighter1_105_108_Closed_Image.style.display='inline'; Codehighlighter1_105_108_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_105_108_Closed_Image onclick="this.style.display='none'; Codehighlighter1_105_108_Closed_Text.style.display='none'; Codehighlighter1_105_108_Open_Image.style.display='inline'; Codehighlighter1_105_108_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_105_108_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_105_108_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif">&nbsp;}</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;P1&nbsp;_p1;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;P2&nbsp;_p2;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">}</span></span><span style="COLOR: #000000">;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">template&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">typename&nbsp;P1,&nbsp;typename&nbsp;P2</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;OnNotify(&nbsp;</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&nbsp;event_type,&nbsp;Param</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">P1,&nbsp;P2</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;param&nbsp;);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">GetNotify()</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">OnNotify(&nbsp;ET_ENTER_RGN,&nbsp;Param</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">Player</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">(&nbsp;player,&nbsp;rgn_id&nbsp;)&nbsp;);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">GetNotify()</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">OnNotify(&nbsp;ET_MOVE,&nbsp;Param</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">(&nbsp;x,&nbsp;y&nbsp;)&nbsp;);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span></div>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt">在上面这个例子中，虽然通过Param的包装，逻辑模块可以在事件通知里放置任意类型的数据，但<br>毕竟只支持2个参数。实际上为了实现支持多个参数（起码得有15个），还是免不了自己实现多个<br>参数的Param。</p>
<p style="FONT-SIZE: 10pt">幸亏我以前写过宏递归产生代码的东西，可以自动地生成这种情况下诸如Param1、Param2的代码。<br>如：</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000">&nbsp;CREATE_PARAM(&nbsp;n&nbsp;)&nbsp;\</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;template&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">DEF_PARAM(&nbsp;n&nbsp;)</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;\<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;Param##n&nbsp;\<br><img id=Codehighlighter1_80_217_Open_Image onclick="this.style.display='none'; Codehighlighter1_80_217_Open_Text.style.display='none'; Codehighlighter1_80_217_Closed_Image.style.display='inline'; Codehighlighter1_80_217_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_80_217_Closed_Image onclick="this.style.display='none'; Codehighlighter1_80_217_Closed_Text.style.display='none'; Codehighlighter1_80_217_Open_Image.style.display='inline'; Codehighlighter1_80_217_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif">&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_80_217_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_80_217_Open_Text><span style="COLOR: #000000">{&nbsp;\<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;DEF_PARAM_TYPE(&nbsp;n&nbsp;);&nbsp;\<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;Param##n(&nbsp;DEF_FUNC_PARAM(&nbsp;n&nbsp;)&nbsp;)&nbsp;\<br><img id=Codehighlighter1_150_188_Open_Image onclick="this.style.display='none'; Codehighlighter1_150_188_Open_Text.style.display='none'; Codehighlighter1_150_188_Closed_Image.style.display='inline'; Codehighlighter1_150_188_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_150_188_Closed_Image onclick="this.style.display='none'; Codehighlighter1_150_188_Closed_Text.style.display='none'; Codehighlighter1_150_188_Open_Image.style.display='inline'; Codehighlighter1_150_188_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_150_188_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_150_188_Open_Text><span style="COLOR: #000000">{&nbsp;\<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;DEF_MEM_VAR_ASSIGN(&nbsp;n&nbsp;);&nbsp;\<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif">&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;\<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;DEF_VAR_DEF(&nbsp;n&nbsp;);&nbsp;\<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">&nbsp;}</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;CREATE_PARAM(&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">&nbsp;);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;CREATE_PARAM(&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">&nbsp;);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span></div>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt">即可生成Param1和Param2的版本。其实这样定义了Param1、Param2的东西之后，又使得OnNotify<br>的参数不是特定的了。虽然可以把Param也泛化，但是在逻辑层写过多的模板代码，总感觉不好。</p>
<p style="FONT-SIZE: 10pt">于是又想到以前写的一个东西，可以把各种类型包装成一种类型---对于外界而言：any。any在<br>boost中有提到，我只是实现了个简单的版本。any的大致实现手法就是在内部通过多态机制将各<br>种类型在某种程度上隐藏，如：</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;base_type<br><img id=Codehighlighter1_32_169_Open_Image onclick="this.style.display='none'; Codehighlighter1_32_169_Open_Text.style.display='none'; Codehighlighter1_32_169_Closed_Image.style.display='inline'; Codehighlighter1_32_169_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_32_169_Closed_Image onclick="this.style.display='none'; Codehighlighter1_32_169_Closed_Text.style.display='none'; Codehighlighter1_32_169_Open_Image.style.display='inline'; Codehighlighter1_32_169_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_32_169_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_32_169_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">base_type()<br><img id=Codehighlighter1_95_109_Open_Image onclick="this.style.display='none'; Codehighlighter1_95_109_Open_Text.style.display='none'; Codehighlighter1_95_109_Closed_Image.style.display='inline'; Codehighlighter1_95_109_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_95_109_Closed_Image onclick="this.style.display='none'; Codehighlighter1_95_109_Closed_Text.style.display='none'; Codehighlighter1_95_109_Open_Image.style.display='inline'; Codehighlighter1_95_109_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_95_109_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_95_109_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000">&nbsp;base_type&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">clone()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;template&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">typename&nbsp;_Tp</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;var_holder&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;base_type<br><img id=Codehighlighter1_265_600_Open_Image onclick="this.style.display='none'; Codehighlighter1_265_600_Open_Text.style.display='none'; Codehighlighter1_265_600_Closed_Image.style.display='inline'; Codehighlighter1_265_600_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_265_600_Closed_Image onclick="this.style.display='none'; Codehighlighter1_265_600_Closed_Text.style.display='none'; Codehighlighter1_265_600_Open_Image.style.display='inline'; Codehighlighter1_265_600_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_265_600_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_265_600_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;_Tp&nbsp;type;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;var_holder</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">type</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;self;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var_holder(&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;type&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">t&nbsp;)&nbsp;:&nbsp;_t(&nbsp;t&nbsp;)<br><img id=Codehighlighter1_434_448_Open_Image onclick="this.style.display='none'; Codehighlighter1_434_448_Open_Text.style.display='none'; Codehighlighter1_434_448_Closed_Image.style.display='inline'; Codehighlighter1_434_448_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_434_448_Closed_Image onclick="this.style.display='none'; Codehighlighter1_434_448_Closed_Text.style.display='none'; Codehighlighter1_434_448_Open_Image.style.display='inline'; Codehighlighter1_434_448_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_434_448_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_434_448_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;base_type&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">clone()&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"><br><img id=Codehighlighter1_500_553_Open_Image onclick="this.style.display='none'; Codehighlighter1_500_553_Open_Text.style.display='none'; Codehighlighter1_500_553_Closed_Image.style.display='inline'; Codehighlighter1_500_553_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_500_553_Closed_Image onclick="this.style.display='none'; Codehighlighter1_500_553_Closed_Text.style.display='none'; Codehighlighter1_500_553_Open_Image.style.display='inline'; Codehighlighter1_500_553_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_500_553_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_500_553_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;self(&nbsp;_t&nbsp;);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;type&nbsp;_t;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span></div>
<p style="FONT-SIZE: 10pt"><br>这样，any类通过一个base_type类，利用C++多态机制即可将类型隐藏于var_holder里。那么，<br>最终的事件通知接口成为下面的样子：</p>
<p style="FONT-SIZE: 10pt">void OnNotify( long type, any data );</p>
<p style="FONT-SIZE: 10pt">OnNotify( ET_ENTER_RGN, any( create_param( player, rgn_id ) ) );其中，create_param<br>是一个辅助函数，用于创建各种Param对象。</p>
<p style="FONT-SIZE: 10pt">事实上，实现各种ParamN版本，让其名字不一样其实有点不妥。还有一种方法可以让Param的名字<br>只有一个，那就是模板偏特化。例如：</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000">template&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">typename&nbsp;_Tp</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;Param;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">template&nbsp;</span><span style="COLOR: #000000">&lt;&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;Param</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">()</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">template&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">typename&nbsp;P1</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;Param</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">(P1)</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif">template&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">typename&nbsp;P1,&nbsp;typename&nbsp;P2</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;Param</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">(P1,P2)</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span></div>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt">这种方法主要是通过组合出一种函数类型，来实现偏特化。因为我觉得构造一个函数类型给主模版，<br>并不是一种合情理的事情。但是，即使使用偏特化来让Param名字看起来只有一个，但对于不同的<br>实例化版本，还是不同的类型，所以还是需要any来包装。</p>
<p style="FONT-SIZE: 10pt"><strong>实际使用</strong></p>
<p style="FONT-SIZE: 10pt">实际使用起来让我觉得非常赏心悦目。上面做的这些事情，实际上是做了一个不同模块间零耦合<br>通信的通道（零耦合似乎有点过激）。现在逻辑模块通知UI模块，只需要定义新的事件类型，在<br>两边分别写通知和处理通知的代码即可。</p>
<p style="FONT-SIZE: 10pt">PS:<br>针对一些评论，我再解释下。其实any只是用于包装Param列表而已，这里也可以用void*，再转成<br>Param*。在这里过多地关注是用any*还是用void*其实偏离了本文的重点。本文的重点其实是Param：</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<div style="BORDER-BOTTOM: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; PADDING-BOTTOM: 4px; BACKGROUND-COLOR: #eeeeee; PADDING-LEFT: 4px; WIDTH: 98%; PADDING-RIGHT: 5px; FONT-SIZE: 13px; WORD-BREAK: break-all; BORDER-TOP: #cccccc 1px solid; BORDER-RIGHT: #cccccc 1px solid; PADDING-TOP: 4px"><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><span style="COLOR: #000000">OnNotify(&nbsp;NT_ENTER_RGN,&nbsp;ang(&nbsp;create_param(&nbsp;player,&nbsp;rgn_id&nbsp;)&nbsp;)&nbsp;);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;OnNotify(&nbsp;</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&nbsp;type,&nbsp;any&nbsp;data&nbsp;)<br><img id=Codehighlighter1_106_235_Open_Image onclick="this.style.display='none'; Codehighlighter1_106_235_Open_Text.style.display='none'; Codehighlighter1_106_235_Closed_Image.style.display='inline'; Codehighlighter1_106_235_Closed_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif"><img style="DISPLAY: none" id=Codehighlighter1_106_235_Closed_Image onclick="this.style.display='none'; Codehighlighter1_106_235_Closed_Text.style.display='none'; Codehighlighter1_106_235_Open_Image.style.display='inline'; Codehighlighter1_106_235_Open_Text.style.display='inline';" align=top src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif"></span><span style="BORDER-BOTTOM: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BACKGROUND-COLOR: #ffffff; DISPLAY: none; BORDER-TOP: #808080 1px solid; BORDER-RIGHT: #808080 1px solid" id=Codehighlighter1_106_235_Closed_Text><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_106_235_Open_Text><span style="COLOR: #000000">{<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;Param2</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">Player</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;ParamType;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;ParamType&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;any_cast</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">ParamType</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">(&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">data&nbsp;);<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;Player&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">player&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;p</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">p1;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif">&nbsp;</span><span style="COLOR: #0000ff">long</span><span style="COLOR: #000000">&nbsp;rgn_id&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;p</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">p2;<br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif">}</span></span><span style="COLOR: #000000"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"><br><img align=top src="http://www.cppblog.com/Images/OutliningIndicators/None.gif"></span></div>
<p style="FONT-SIZE: 10pt"><br><br><a href="http://www.cppblog.com/Files/kevinlynx/ParamList.rar">下载相关代码</a></p>
<img src ="http://www.cppblog.com/kevinlynx/aggbug/94143.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2009-08-23 09:55 <a href="http://www.cppblog.com/kevinlynx/archive/2009/08/23/94143.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>指针和模块健壮</title><link>http://www.cppblog.com/kevinlynx/archive/2009/06/28/88711.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Sun, 28 Jun 2009 11:35:00 GMT</pubDate><guid>http://www.cppblog.com/kevinlynx/archive/2009/06/28/88711.html</guid><wfw:comment>http://www.cppblog.com/kevinlynx/comments/88711.html</wfw:comment><comments>http://www.cppblog.com/kevinlynx/archive/2009/06/28/88711.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/kevinlynx/comments/commentRss/88711.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kevinlynx/services/trackbacks/88711.html</trackback:ping><description><![CDATA[<p><font size=2>仔细想想能导致一个C++程序崩溃的几乎90%原因都是跟指针有关。空指针野指针，一不小心<br>程序就崩了。写C++程序的人基本上都知道这个问题。在我们周围避免这些问题的常规方法<br>也很多，诸如auto_ptr（及其他基于template的原始指针wrapper）、SAFE_DELETE。当然也<br>会有很多人在实现一个函数时会很勤劳地对每一个parameter进行合法判断。 </font>
<p><font size=2>其实，我们都知道，auto_ptr这些东西始终是无法避免野指针和空指针带来的灾难。<br>SAFE_DELETE也不能阻止别人使用这个空指针。 </font>
<p><font size=2>在我看过的一些开源项目的代码中，这些代码给人的感觉就是别人总能详细地掌控各种资源<br>（包括指针及其他变量）的使用情况。相比之下，公司隔壁组的老大则显得保守很多。他要<br>求我们几乎要对所有指针的使用进行空值判断（野指针也判断不了），当然，各种成员变量<br>也要进行即使现在看上去没多大用的初始化。 </font>
<p><font size=2>也许，这样做后程序是不会挂掉了。但是，就我们的观点来看，这样反而会隐藏一些BUG。<br>为什么我们不能详尽地去管理一个指针？一个指针变为空了，总是因为在这之前发生了错误<br>。当然，野指针本身就是愚蠢代码产生的东西，这里没必要讨论。空指针之所以为空，也是<br>因为在很多时候我们把空作为失败/错误/无效的标志。 </font>
<p><font size=2>恰好上周我的一些代码就真的在空指针上出现了问题。外网的服务器随时会因为玩家的一些<br>临界操作行为而崩溃掉。虽然我通过修改脚本来屏蔽这个问题（因为不能说停机维护就停机<br>维护），但是总感觉程序是不安全的。人不吃点教训绝对不学乖。 </font>
<p><font size=2>后来我对这个问题彻底思考了一下。很多程序员都自认聪明。在写C++程序时，我从来不提<br>供没用的public接口，尤其是set/get。我也从来不对没必要的成员变量进行初始化。我给<br>的理由是对于这些东西我都有很清晰的把握，我为什么要做stupid的事情？ </font>
<p><font size=2>但是，我几乎从来没有界定，指针在哪些情况下需要去判断为空？函数的参数绝对不需要。<br>假如函数的参数就是个空指针，那是client程序员的责任。仅供模块内使用的指针（包含其<br>他资源）在内部使用时也不需要去判断。如果去判断了，那说明你对你自己写的模块都缺乏<br>精确的把握，证明你的设计思维不够清晰。 </font>
<p><font size=2>什么时候需要判断？当指针依赖于外部环境时，例如读配置文件、载入资源，因为外部因素<br>不确定不在自己控制范围内，那么进行判断。同样，当使用了其他模块返回的指针值时，也<br>需要判断。这个其实和&#8220;外部环境&#8221;属于同一种情况。因为我们对其他模块也不清楚，更为<br>隐蔽的是（随着其他模块的改变，将来会在你的模块里爆发崩溃错误），其他模块由别人维<br>护，其变化更不受自己控制。之前我对这一点界定不是很清楚，这也是我犯错的原因。 </font>
<p><font size=2>现在想想，像游戏服务器这种程序，里面塞着各种各样的游戏功能。无论是哪一个模块出现<br>个空指针访问出错的问题，都会直接让服务器崩掉。关键是这个结果经常伴随着玩家的损失<br>。所以理想状态下，把每一个模块都放置在单独的进程里，确实是很有好处的。 </font></p>
<img src ="http://www.cppblog.com/kevinlynx/aggbug/88711.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2009-06-28 19:35 <a href="http://www.cppblog.com/kevinlynx/archive/2009/06/28/88711.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>最近的两个问题：less for std::map，静态变量初始化顺序</title><link>http://www.cppblog.com/kevinlynx/archive/2008/11/11/66623.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Tue, 11 Nov 2008 09:55:00 GMT</pubDate><guid>http://www.cppblog.com/kevinlynx/archive/2008/11/11/66623.html</guid><wfw:comment>http://www.cppblog.com/kevinlynx/comments/66623.html</wfw:comment><comments>http://www.cppblog.com/kevinlynx/archive/2008/11/11/66623.html#Feedback</comments><slash:comments>13</slash:comments><wfw:commentRss>http://www.cppblog.com/kevinlynx/comments/commentRss/66623.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kevinlynx/services/trackbacks/66623.html</trackback:ping><description><![CDATA[<p style="FONT-SIZE: 10pt"><br>说下最近自己遇到的两个值得让人注意的问题。<br>其一是关于自己给std::map写less predicate，std::map第三个参数是一个典型的functor。map内部将使用<br>这个functor去判定两个元素是否相等，默认使用的是std::less。但是为什么传入的是一个判断第一个参数<br>小于第二个参数的functor，而不是一个判断两个参数是否相等的functor？按照STL文档的说法，当检查两<br>个参数没有小于也没有大于的关系时，就表示两个参数相等。不管怎样，我遇到了需要自己写这个functor<br>的需求，于是：</p>
<p style="FONT-SIZE: 10pt">struct MyLess<br>{<br>&nbsp;&nbsp;&nbsp; bool operator() ( long left, long right )<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //...<br>&nbsp;&nbsp;&nbsp; }<br>};</p>
<p style="FONT-SIZE: 10pt">DEBUG模式下编译没问题，RELEASE模式下却出现C3848的错误。这就有点奇怪了，如果确实存在语法错误，<br>那么DEBUG和RELASE应该一样才对。查了下MSDN，C3848的错误是因为const限定符造成的，如：</p>
<p style="FONT-SIZE: 10pt">const MyLess pr;<br>pr(); // C3848</p>
<p style="FONT-SIZE: 10pt">于是，在operator()后加上const，就OK了。看了下VC std::map相关代码，以为是DEBUG和RELEASE使用了不<br>同的代码造成。但是我始终没找到不同点。另一方面，就STL内部的风格来看，应该不会把predicator处理<br>成const &amp;之类的东西，全部是value形式的。奇怪了。</p>
<p style="FONT-SIZE: 10pt">第二个问题，涉及到静态变量。这个东西给我的印象特别深刻，因为以前去一家外企应聘时被问到，当时<br>觉得那个LEADER特别厉害。回来后让我反思，是不是过多地关注了C++里的花哨，而漏掉了C里的朴素？导致<br>我至今对纯C存在偏好。</p>
<p style="FONT-SIZE: 10pt">说正题，我现在有如下的文件关系：</p>
<p style="FONT-SIZE: 10pt">// def.h<br>struct Obj<br>{<br>&nbsp;&nbsp;&nbsp; Obj()<br>&nbsp;{<br>&nbsp;&nbsp;ObjMgr::AddObj( id, this );<br>&nbsp;}<br>&nbsp;int id;<br>};</p>
<p style="FONT-SIZE: 10pt">struct ObjMgr<br>{<br>&nbsp;&nbsp;&nbsp; static void AddObj( int id, Obj *t )<br>&nbsp;{<br>&nbsp;&nbsp;ObjTable[id] = t;<br>&nbsp;}<br>&nbsp;static std::map&lt;int, Obj*&gt; ObjTable;<br>};</p>
<p style="FONT-SIZE: 10pt">static Obj _t;</p>
<p style="FONT-SIZE: 10pt">// ObjMgr.cpp<br>#include "def.h"</p>
<p style="FONT-SIZE: 10pt">static std::map&lt;int, Obj*&gt;::ObjMgr ObjTable;</p>
<p style="FONT-SIZE: 10pt">// main.cpp<br>#include "def.h"</p>
<p style="FONT-SIZE: 10pt">这里举的例子可能有点不恰当，我在一台没有编译器的机器上写的这篇文章。忽略掉这些旁支末节。我的意思，<br>就是想让Obj自己自动向ObjMgr里添加自己。我们都知道静态变量将在程序启动时被初始化，先于main执行之前。</p>
<p style="FONT-SIZE: 10pt">上面代码有两个问题：</p>
<p style="FONT-SIZE: 10pt">一、<br>代码没有按照我预期地执行，如果你按照我的意思做个测试，你的程序甚至在进main之前就crash了。我假定你<br>用的是VC，因为我没在其他编译器上试验过。问题就在于，Obj的构造依赖于ObjTable这个map对象。在调试过程<br>中我发现，虽然ObjTable拥有了内存空间，其this指针有效，但是，map对象并没有得到构造。我的意思是，Obj<br>的构造先于ObjTable构造（下几个断点即可轻易发现），那么在执行map::operator[]时，就出错了，因为这个时候<br>map里相关数据还没准备好。</p>
<p style="FONT-SIZE: 10pt">那是否存在某种机制可以手动静态变量的初始化顺序呢？不知道。我最后怎样解决这个问题的？</p>
<p style="FONT-SIZE: 10pt">二、<br>在还没有想到解决办法之前（不改变我的设计），我发现了这段代码的另一个问题：我在头文件里定义了静态<br>变量：static Obj _t; 这有什么问题？想想预编译这个过程即可知道，头文件在预编译阶段被文本展开到CPP<br>文件里，然后，ObjMgr.cpp和main.cpp文件里都将出现static Obj _t;代码。也就是说，ObjMgr.obj和main.obj<br>里都有一个文件静态变量_t。</p>
<p style="FONT-SIZE: 10pt">看来，在头文件里放这个静态变量是肯定不对的。于是，我将_t移动到ObjMgr.cpp里：</p>
<p style="FONT-SIZE: 10pt">// ObjMgr.cpp<br>#include "def.h"</p>
<p style="FONT-SIZE: 10pt">static std::map&lt;int, Obj*&gt;::ObjMgr ObjTable;<br>static Obj _t;</p>
<p style="FONT-SIZE: 10pt">按照这样的顺序定义后，_t的构造居然晚于ObjTable了。也就是说，放置于前面的变量定义，就意味着它将被<br>首先构造初始化。这样两个问题都解决了。</p>
<p style="FONT-SIZE: 10pt">但是，谁能保证这一点特性？C标准文档里？还是VC编译器自己？</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt">&nbsp;</p>
<p style="FONT-SIZE: 10pt"><br>&nbsp;</p>
<img src ="http://www.cppblog.com/kevinlynx/aggbug/66623.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2008-11-11 17:55 <a href="http://www.cppblog.com/kevinlynx/archive/2008/11/11/66623.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Proactor和Reactor模式_继续并发系统设计的扫盲</title><link>http://www.cppblog.com/kevinlynx/archive/2008/06/06/52356.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Fri, 06 Jun 2008 05:25:00 GMT</pubDate><guid>http://www.cppblog.com/kevinlynx/archive/2008/06/06/52356.html</guid><wfw:comment>http://www.cppblog.com/kevinlynx/comments/52356.html</wfw:comment><comments>http://www.cppblog.com/kevinlynx/archive/2008/06/06/52356.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cppblog.com/kevinlynx/comments/commentRss/52356.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kevinlynx/services/trackbacks/52356.html</trackback:ping><description><![CDATA[<p><font size=2>6.6.2008 </font>
<p><font size=2>Kevin Lynx </font>
<p><font size=2>Proactor和<a href="http://en.wikipedia.org/wiki/Reactor_pattern" target=_blank>Reactor</a>都是并发编程中的设计模式。在我看来，他们都是用于派发/分离IO操作事件的。这里所谓的<br>IO事件也就是诸如read/write的IO操作。"派发/分离"就是将单独的IO事件通知到上层模块。两个模式不同的地方<br>在于，Proactor用于异步IO，而Reactor用于同步IO。 </font>
<p><font size=2>摘抄一些关键的东西： </font>
<p><font size=2>"<br>Two patterns that involve event demultiplexors are called Reactor and Proactor [1]. The Reactor patterns <br>involve synchronous I/O, whereas the Proactor pattern involves asynchronous I/O.<br>" </font>
<p><font size=2>关于两个模式的大致模型，从以下文字基本可以明白： </font>
<p><font size=2>"<br>An example will help you understand the difference between Reactor and Proactor. We will focus on the read <br>operation here, as the write implementation is similar. Here's a read in Reactor: </font>
<p><font size=2>* An event handler declares interest in I/O events that indicate readiness for read on a particular socket ;<br>* The event demultiplexor waits for events ;<br>* An event comes in and wakes-up the demultiplexor, and the demultiplexor calls the appropriate handler; <br>* The event handler performs the actual read operation, handles the data read, declares renewed interest in <br>&nbsp; I/O events, and returns control to the dispatcher . </font>
<p><font size=2>By comparison, here is a read operation in Proactor (true async): </font>
<p><font size=2>* A handler initiates an asynchronous read operation (note: the OS must support asynchronous I/O). In this <br>&nbsp; case, the handler does not care about I/O readiness events, but is instead registers interest in receiving <br>&nbsp; completion events;<br>* The event demultiplexor waits until the operation is completed ;<br>* While the event demultiplexor waits, the OS executes the read operation in a parallel kernel thread, puts <br>&nbsp; data into a user-defined buffer, and notifies the event demultiplexor that the read is complete ;<br>* The event demultiplexor calls the appropriate handler; <br>* The event handler handles the data from user defined buffer, starts a new asynchronous operation, and returns<br>&nbsp; control to the event demultiplexor. </font>
<p><font size=2>" </font>
<p><font size=2>可以看出，两个模式的相同点，都是对某个IO事件的事件通知(即告诉某个模块，这个IO操作可以进行或已经完成)。在结构<br>上，两者也有相同点：demultiplexor负责提交IO操作(异步)、查询设备是否可操作(同步)，然后当条件满足时，就回调handler。<br>不同点在于，异步情况下(Proactor)，当回调handler时，表示IO操作已经完成；同步情况下(Reactor)，回调handler时，表示<br>IO设备可以进行某个操作(can read or can write)，handler这个时候开始提交操作。 </font>
<p><font size=2>用select模型写个简单的reactor，大致为： </font>
<p><font size=2></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 id=Codehighlighter1_0_3_Open_Image onclick="this.style.display='none'; Codehighlighter1_0_3_Open_Text.style.display='none'; Codehighlighter1_0_3_Closed_Image.style.display='inline'; Codehighlighter1_0_3_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_0_3_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_0_3_Closed_Text.style.display='none'; Codehighlighter1_0_3_Open_Image.style.display='inline'; Codehighlighter1_0_3_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top><span id=Codehighlighter1_0_3_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">/**/</span><span id=Codehighlighter1_0_3_Open_Text><span style="COLOR: #808080">///</span></span><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;handler<br><img id=Codehighlighter1_18_124_Open_Image onclick="this.style.display='none'; Codehighlighter1_18_124_Open_Text.style.display='none'; Codehighlighter1_18_124_Closed_Image.style.display='inline'; Codehighlighter1_18_124_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_18_124_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_18_124_Closed_Text.style.display='none'; Codehighlighter1_18_124_Open_Image.style.display='inline'; Codehighlighter1_18_124_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_18_124_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_18_124_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;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;onRead()&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</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;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;onWrite()&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</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;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;onAccept()&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;&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></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;dispatch<br><img id=Codehighlighter1_144_804_Open_Image onclick="this.style.display='none'; Codehighlighter1_144_804_Open_Text.style.display='none'; Codehighlighter1_144_804_Closed_Image.style.display='inline'; Codehighlighter1_144_804_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_144_804_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_144_804_Closed_Text.style.display='none'; Codehighlighter1_144_804_Open_Image.style.display='inline'; Codehighlighter1_144_804_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_144_804_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_144_804_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">void</span><span style="COLOR: #000000">&nbsp;poll()<br><img id=Codehighlighter1_174_696_Open_Image onclick="this.style.display='none'; Codehighlighter1_174_696_Open_Text.style.display='none'; Codehighlighter1_174_696_Closed_Image.style.display='inline'; Codehighlighter1_174_696_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_174_696_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_174_696_Closed_Text.style.display='none'; Codehighlighter1_174_696_Open_Image.style.display='inline'; Codehighlighter1_174_696_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_174_696_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_174_696_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;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;add&nbsp;fd&nbsp;in&nbsp;the&nbsp;set.<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/dot.gif"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;poll&nbsp;every&nbsp;fd</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;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;c&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;select(&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">read_fd,&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">write_fd,&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(&nbsp;c&nbsp;</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;)<br><img id=Codehighlighter1_329_690_Open_Image onclick="this.style.display='none'; Codehighlighter1_329_690_Open_Text.style.display='none'; Codehighlighter1_329_690_Closed_Image.style.display='inline'; Codehighlighter1_329_690_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_329_690_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_329_690_Closed_Text.style.display='none'; Codehighlighter1_329_690_Open_Image.style.display='inline'; Codehighlighter1_329_690_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_329_690_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_329_690_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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;each&nbsp;fd&nbsp;</span><span style="COLOR: #0000ff">in</span><span style="COLOR: #000000">&nbsp;the&nbsp;read_fd_set<br><img id=Codehighlighter1_386_533_Open_Image onclick="this.style.display='none'; Codehighlighter1_386_533_Open_Text.style.display='none'; Codehighlighter1_386_533_Closed_Image.style.display='inline'; Codehighlighter1_386_533_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_386_533_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_386_533_Closed_Text.style.display='none'; Codehighlighter1_386_533_Open_Image.style.display='inline'; Codehighlighter1_386_533_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_386_533_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_386_533_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;fd&nbsp;can&nbsp;read<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_handler</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">onRead();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;fd&nbsp;can&nbsp;accept<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_handler</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">onAccept();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">&nbsp;each&nbsp;fd&nbsp;</span><span style="COLOR: #0000ff">in</span><span style="COLOR: #000000">&nbsp;the&nbsp;write_fd_set<br><img id=Codehighlighter1_593_680_Open_Image onclick="this.style.display='none'; Codehighlighter1_593_680_Open_Text.style.display='none'; Codehighlighter1_593_680_Closed_Image.style.display='inline'; Codehighlighter1_593_680_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_593_680_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_593_680_Closed_Text.style.display='none'; Codehighlighter1_593_680_Open_Image.style.display='inline'; Codehighlighter1_593_680_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_593_680_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_593_680_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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;fd&nbsp;can&nbsp;write<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_handler</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">onWrite();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;<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;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;setHandler(&nbsp;handler&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">_h&nbsp;)<br><img id=Codehighlighter1_739_768_Open_Image onclick="this.style.display='none'; Codehighlighter1_739_768_Open_Text.style.display='none'; Codehighlighter1_739_768_Closed_Image.style.display='inline'; Codehighlighter1_739_768_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_739_768_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_739_768_Closed_Text.style.display='none'; Codehighlighter1_739_768_Open_Image.style.display='inline'; Codehighlighter1_739_768_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_739_768_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_739_768_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;&nbsp;_handler&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;_h;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;<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">private</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;handler&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">_handler;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_809_824_Open_Image onclick="this.style.display='none'; Codehighlighter1_809_824_Open_Text.style.display='none'; Codehighlighter1_809_824_Closed_Image.style.display='inline'; Codehighlighter1_809_824_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_809_824_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_809_824_Closed_Text.style.display='none'; Codehighlighter1_809_824_Open_Image.style.display='inline'; Codehighlighter1_809_824_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_809_824_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">/**/</span><span id=Codehighlighter1_809_824_Open_Text><span style="COLOR: #808080">///</span><span style="COLOR: #008000">&nbsp;application</span><span style="COLOR: #808080"></span></span><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;MyHandler&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;handler<br><img id=Codehighlighter1_858_965_Open_Image onclick="this.style.display='none'; Codehighlighter1_858_965_Open_Text.style.display='none'; Codehighlighter1_858_965_Closed_Image.style.display='inline'; Codehighlighter1_858_965_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_858_965_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_858_965_Closed_Text.style.display='none'; Codehighlighter1_858_965_Open_Image.style.display='inline'; Codehighlighter1_858_965_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_858_965_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_858_965_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">void</span><span style="COLOR: #000000">&nbsp;onRead()<br><img id=Codehighlighter1_890_896_Open_Image onclick="this.style.display='none'; Codehighlighter1_890_896_Open_Text.style.display='none'; Codehighlighter1_890_896_Closed_Image.style.display='inline'; Codehighlighter1_890_896_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_890_896_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_890_896_Closed_Text.style.display='none'; Codehighlighter1_890_896_Open_Image.style.display='inline'; Codehighlighter1_890_896_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_890_896_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_890_896_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;<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;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;onWrite()<br><img id=Codehighlighter1_923_929_Open_Image onclick="this.style.display='none'; Codehighlighter1_923_929_Open_Text.style.display='none'; Codehighlighter1_923_929_Closed_Image.style.display='inline'; Codehighlighter1_923_929_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_923_929_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_923_929_Closed_Text.style.display='none'; Codehighlighter1_923_929_Open_Image.style.display='inline'; Codehighlighter1_923_929_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_923_929_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_923_929_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;<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;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;onAccept()<br><img id=Codehighlighter1_957_963_Open_Image onclick="this.style.display='none'; Codehighlighter1_957_963_Open_Text.style.display='none'; Codehighlighter1_957_963_Closed_Image.style.display='inline'; Codehighlighter1_957_963_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_957_963_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_957_963_Closed_Text.style.display='none'; Codehighlighter1_957_963_Open_Image.style.display='inline'; Codehighlighter1_957_963_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_957_963_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_957_963_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;&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></span></div>
<p><br>在网上找了份Proactor模式比较正式的<a href="http://www.cppblog.com/Files/kevinlynx/proactor2.rar" target=_blank>文档</a>，其给出了一个总体的UML类图，比较全面： </font>
<p><a href="http://www.cppblog.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/ProactorReactor__BCB1/proactor_uml.jpg"><img style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px" height=317 alt=proactor_uml src="http://www.cppblog.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/ProactorReactor__BCB1/proactor_uml_thumb.jpg" width=692 border=0></a>
<p><font size=2>根据这份图我随便写了个例子代码： </font>
<p><font size=2></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: #0000ff">class</span><span style="COLOR: #000000">&nbsp;AsyIOProcessor<br><img id=Codehighlighter1_21_227_Open_Image onclick="this.style.display='none'; Codehighlighter1_21_227_Open_Text.style.display='none'; Codehighlighter1_21_227_Closed_Image.style.display='inline'; Codehighlighter1_21_227_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_21_227_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_21_227_Closed_Text.style.display='none'; Codehighlighter1_21_227_Open_Image.style.display='inline'; Codehighlighter1_21_227_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_21_227_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_21_227_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">void</span><span style="COLOR: #000000">&nbsp;do_read()<br><img id=Codehighlighter1_54_189_Open_Image onclick="this.style.display='none'; Codehighlighter1_54_189_Open_Text.style.display='none'; Codehighlighter1_54_189_Closed_Image.style.display='inline'; Codehighlighter1_54_189_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_54_189_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_54_189_Closed_Text.style.display='none'; Codehighlighter1_54_189_Open_Image.style.display='inline'; Codehighlighter1_54_189_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_54_189_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_54_189_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;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/dot.gif">send&nbsp;read&nbsp;operation&nbsp;to&nbsp;OS<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;read&nbsp;io&nbsp;finished.and&nbsp;dispatch&nbsp;notification</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;&nbsp;_proactor</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">dispatch_read();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;<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">private</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Proactor&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">_proactor;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;&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></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Proactor<br><img id=Codehighlighter1_247_369_Open_Image onclick="this.style.display='none'; Codehighlighter1_247_369_Open_Text.style.display='none'; Codehighlighter1_247_369_Closed_Image.style.display='inline'; Codehighlighter1_247_369_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_247_369_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_247_369_Closed_Text.style.display='none'; Codehighlighter1_247_369_Open_Image.style.display='inline'; Codehighlighter1_247_369_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_247_369_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_247_369_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">void</span><span style="COLOR: #000000">&nbsp;dispatch_read()<br><img id=Codehighlighter1_286_323_Open_Image onclick="this.style.display='none'; Codehighlighter1_286_323_Open_Text.style.display='none'; Codehighlighter1_286_323_Closed_Image.style.display='inline'; Codehighlighter1_286_323_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_286_323_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_286_323_Closed_Text.style.display='none'; Codehighlighter1_286_323_Open_Image.style.display='inline'; Codehighlighter1_286_323_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_286_323_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_286_323_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;&nbsp;_handlerMgr</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">onRead();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;<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">private</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;HandlerManager&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">_handlerMgr;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;&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></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;HandlerManager<br><img id=Codehighlighter1_395_634_Open_Image onclick="this.style.display='none'; Codehighlighter1_395_634_Open_Text.style.display='none'; Codehighlighter1_395_634_Closed_Image.style.display='inline'; Codehighlighter1_395_634_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_395_634_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_395_634_Closed_Text.style.display='none'; Codehighlighter1_395_634_Open_Image.style.display='inline'; Codehighlighter1_395_634_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_395_634_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_395_634_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;typedef&nbsp;std::list</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">Handler</span><span style="COLOR: #000000">*&gt;</span><span style="COLOR: #000000">&nbsp;HandlerList;&nbsp;<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">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">void</span><span style="COLOR: #000000">&nbsp;onRead()<br><img id=Codehighlighter1_482_593_Open_Image onclick="this.style.display='none'; Codehighlighter1_482_593_Open_Text.style.display='none'; Codehighlighter1_482_593_Closed_Image.style.display='inline'; Codehighlighter1_482_593_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_482_593_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_482_593_Closed_Text.style.display='none'; Codehighlighter1_482_593_Open_Image.style.display='inline'; Codehighlighter1_482_593_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_482_593_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_482_593_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;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;notify&nbsp;all&nbsp;the&nbsp;handlers.</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;&nbsp;std::for_each(&nbsp;_handlers.begin(),&nbsp;_handlers.end(),&nbsp;onRead&nbsp;);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000">&nbsp;<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">private</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;HandlerList&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">_handlers;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;&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></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Handler<br><img id=Codehighlighter1_653_694_Open_Image onclick="this.style.display='none'; Codehighlighter1_653_694_Open_Text.style.display='none'; Codehighlighter1_653_694_Closed_Image.style.display='inline'; Codehighlighter1_653_694_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_653_694_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_653_694_Closed_Text.style.display='none'; Codehighlighter1_653_694_Open_Image.style.display='inline'; Codehighlighter1_653_694_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_653_694_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_653_694_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;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;onRead()&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;&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></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;application&nbsp;level&nbsp;handler.</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;MyHandler&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Handler<br><img id=Codehighlighter1_762_815_Open_Image onclick="this.style.display='none'; Codehighlighter1_762_815_Open_Text.style.display='none'; Codehighlighter1_762_815_Closed_Image.style.display='inline'; Codehighlighter1_762_815_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_762_815_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_762_815_Closed_Text.style.display='none'; Codehighlighter1_762_815_Open_Image.style.display='inline'; Codehighlighter1_762_815_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_762_815_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_762_815_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">void</span><span style="COLOR: #000000">&nbsp;onRead()&nbsp;<br><img id=Codehighlighter1_795_813_Open_Image onclick="this.style.display='none'; Codehighlighter1_795_813_Open_Text.style.display='none'; Codehighlighter1_795_813_Closed_Image.style.display='inline'; Codehighlighter1_795_813_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_795_813_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_795_813_Closed_Text.style.display='none'; Codehighlighter1_795_813_Open_Image.style.display='inline'; Codehighlighter1_795_813_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_795_813_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_795_813_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;&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/ExpandedSubBlockEnd.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;&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></span></div>
<p><br>Reactor通过某种变形，可以将其改装为Proactor，在某些不支持异步IO的系统上，也可以隐藏底层的实现，利于编写跨平台<br>代码。我们只需要在dispatch(也就是demultiplexor)中封装同步IO操作的代码，在上层，用户提交自己的缓冲区到这一层，<br>这一层检查到设备可操作时，不像原来立即回调handler，而是开始IO操作，然后将操作结果放到用户缓冲区(读)，然后再<br>回调handler。这样，对于上层handler而言，就像是proactor一样。详细技法参见<a href="http://www.artima.com/articles/io_design_patterns2.html" target=_blank>这篇文章</a>。 </font>
<p><font size=2>其实就设计模式而言，我个人觉得某个模式其实是没有完全固定的结构的。不能说某个模式里就肯定会有某个类，类之间的<br>关系就肯定是这样。在实际写程序过程中也很少去特别地实现某个模式，只能说模式会给你更多更好的架构方案。 </font>
<p><font size=2>最近在看spserver的代码，看到别人提各种并发系统中的模式，有点眼红，于是才来扫扫盲。知道什么是<a href="http://www.cppblog.com/kevinlynx/archive/2008/06/04/52127.html" target=_blank>leader follower模式</a>，<br>reactor, proactor，multiplexing，对于心中的那个网络库也越来越清晰。 </font>
<p><font size=2>最近还干了些离谱的事，写了传说中的字节流编码，用模板的方式实现，不但保持了扩展性，还少写很多代码；处于效率考虑，<br>写了个static array容器(其实就是template &lt;typename _Tp, std::size_t size&gt; class static_array { _Tp _con[size])，<br>加了iterator，遵循STL标准，可以结合进STL的各个generic algorithm用，自我感觉不错。基础模块搭建完毕，解析了公司<br>服务器网络模块的消息，我是不是真的打算用自己的网络模块重写我的验证服务器？在另一个给公司写的工具里，因为实在厌恶<br>越来越多的重复代码，索性写了几个宏，还真的做到了代码的自动生成:D。 </font>
<p><font size=2>对优雅代码的追求真的成了种癖好.&nbsp; = =| </font></p>
<img src ="http://www.cppblog.com/kevinlynx/aggbug/52356.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2008-06-06 13:25 <a href="http://www.cppblog.com/kevinlynx/archive/2008/06/06/52356.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>半同步半异步模式以及Leader_Follwer模式</title><link>http://www.cppblog.com/kevinlynx/archive/2008/06/04/52127.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Wed, 04 Jun 2008 02:40:00 GMT</pubDate><guid>http://www.cppblog.com/kevinlynx/archive/2008/06/04/52127.html</guid><wfw:comment>http://www.cppblog.com/kevinlynx/comments/52127.html</wfw:comment><comments>http://www.cppblog.com/kevinlynx/archive/2008/06/04/52127.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/kevinlynx/comments/commentRss/52127.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kevinlynx/services/trackbacks/52127.html</trackback:ping><description><![CDATA[<p><font size="2">这里提到的两个设计模式都是用于高并发系统(例如一个高性能的网络服务器)的。这里我只是简单地提一下： </font> <p><font size="2"><strong>1.</strong><a href="http://www.cppblog.com/Files/kevinlynx/hh_lf.rar" target="_blank"><strong>半同步/半异步（half-sync/half-async</strong></a><strong>）：</strong> </font> <p><font size="2">在网<a href="http://www.javaeye.com/topic/60414" target="_blank">上一份资料</a>中引用了一本貌似很<a href="http://www.china-pub.com/14109" target="_blank">经典的书</a>里的比喻：<br>” <br>许多餐厅使用 半同步/半异步 模式的变体。例如，餐厅常常雇佣一个领班负责迎接顾客，并在餐厅繁忙时留意给顾客安排桌位，<br>为等待就餐的顾客按序排队是必要的。领班由所有顾客“共享”，不能被任何特定顾客占用太多时间。当顾客在一张桌子入坐后，<br>有一个侍应生专门为这张桌子服务。 <br>“ </font> <p><font size="2">按照另一份似乎比较权威的文档的描述，要实现半同步/半异步模式，需要实现三层：异步层、同步层、队列层。因为很多操作<br>采用异步方式会比较有效率(例如高效率的网络模型似乎都采用异步IO)，但是异步操作的复杂度比较高，不利于编程。而同步<br>操作相对之下编程要简单点。为了结合两者的优点，就提出了这个模式。而为了让异步层和同步层互相通信(模块间的通信)，系<br>统需要加入一个通信队列。异步层将操作结果放入队列，同步层从队列里获取操作结果。 </font> <p><font size="2">回过头来看看我之前写的那个select网络模型代码，个人认为基本上算是一个半同步半异步模式的简单例子：Buffer相当于通信<br>队列，网络底层将数据写入Buffer，上层再同步地从该队列里获取出数据。这样看来似乎也没什么难度。 = = </font> <p>关于例子代码，直接引用iunknown给的：  <p>//这就是一个典型的循环队列的定义，iget 是队列头，iput 是队列尾&lt;/STRONG&gt;&nbsp;&nbsp; <br>int clifd[MAXNCLI], iget, iput;&nbsp;&nbsp;&nbsp; <br>int main( int argc, char * argv[] )&nbsp;&nbsp; <br>{&nbsp;&nbsp; <br>&nbsp; ......&nbsp;&nbsp; <br>&nbsp; int listenfd = Tcp_listen( NULL, argv[ 1 ], &amp;addrlen );&nbsp;&nbsp; <br>&nbsp; ......&nbsp;&nbsp; <br>&nbsp; iget = iput = 0;&nbsp;&nbsp; <br>&nbsp; for( int i = 0; i &lt; nthreads; i++ ) {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; pthread_create( &amp;tptr[i].thread_tid, NULL, &amp;thread_main, (void*)i );&nbsp;&nbsp; <br>&nbsp; for( ; ; ) {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; connfd = accept( listenfd, cliaddr,, &amp;clilen );&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; clifd[ iput ] = connfd;&nbsp;&nbsp;&nbsp;&nbsp; // 接受到的连接句柄放入队列&lt;/STRONG&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; if( ++iput == MAXNCLI ) iput = 0;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp; }&nbsp;&nbsp; <br>}&nbsp;&nbsp; <br>void * thread_main( void * arg )&nbsp;&nbsp; <br>{&nbsp;&nbsp; <br>&nbsp; for( ; ; ) {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; while( iget == iput ) pthread_cond_wait( ...... );&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; connfd = clifd[ iget ];&nbsp;&nbsp;&nbsp;&nbsp; // 从队列中获得连接句柄&lt;/STRONG&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; if( ++iget == MAXNCLI ) iget = 0;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ......&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; web_child( connfd );&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; close( connfd );&nbsp;&nbsp; <br>&nbsp; }&nbsp;&nbsp; <br>}&nbsp; <p><font size="2"><strong>2</strong><a href="http://www.cppblog.com/Files/kevinlynx/hh_lf.rar" target="_blank"><strong>.领导者/追随者（Leader/Followers）：</strong></a> </font> <p><font size="2">同样，给出别人引用的比喻：<br>”<br>在日常生活中，领导者/追随者模式用于管理许多飞机场出租车候车台。在该用例中，出租车扮演“线程”角色，排在第一辆的出<br>租车成为领导者，剩下的出租车成为追随者。同样，到达出租车候车台的乘客构成了必须被多路分解给出租车的事件，一般以先进<br>先出排序。一般来说，如果任何出租车可以为任何顾客服务，该场景就主要相当于非绑定句柄/线程关联。然而，如果仅仅是某些<br>出租车可以为某些乘客服务，该场景就相当于绑定句柄/线程关联。 <br>“ </font> <p><font size="2">其实这个更简单，我记得&lt;unix网络编程&gt;中似乎提到过这个。总之有一种网络模型(connection-per-thread?)里，一个线程用于<br>accept连接。当接收到一个新的连接时，这个线程就转为connection thread，而这个线程后面的线程则上升为accept线程。这里，<br>accept线程就相当于领导者线程，而其他线程则属于追随者线程。 </font> <p>iunknown 的例子代码：  <p>int listenfd;&nbsp;&nbsp; <br>int main( int argc, char * argv[] )&nbsp;&nbsp; <br>{&nbsp;&nbsp; <br>&nbsp; ......&nbsp;&nbsp; <br>&nbsp; listenfd = Tcp_listen( NULL, argv[ 1 ], &amp;addrlen );&nbsp;&nbsp; <br>&nbsp; ......&nbsp;&nbsp; <br>&nbsp; for( int i = 0; i &lt; nthreads; i++ ){&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; pthread_create( &amp;tptr[i].thread_tid, NULL, &amp;thread_main, (void*)i );&nbsp;&nbsp; <br>&nbsp; }&nbsp;&nbsp; <br>&nbsp; ......&nbsp;&nbsp; <br>}&nbsp;&nbsp; <br>void * thread_main( void * arg )&nbsp;&nbsp; <br>{&nbsp;&nbsp; <br>&nbsp; for( ; ; ){&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ......&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; // 多个线程同时阻塞在这个 accept 调用上，依靠操作系统的队列&lt;/STRONG&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; connfd = accept( listenfd, cliaddr, &amp;clilen );&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ......&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; web_child( connfd );&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; close( connfd );&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ......&nbsp;&nbsp; <br>&nbsp; }&nbsp;&nbsp; <br>}&nbsp; <p><font size="2"></font></p><img src ="http://www.cppblog.com/kevinlynx/aggbug/52127.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2008-06-04 10:40 <a href="http://www.cppblog.com/kevinlynx/archive/2008/06/04/52127.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>