<?xml version="1.0" encoding="gb2312"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>云风的 BLOG</title>
    <link rel="alternate" type="text/html" href="http://blog.codingnow.com/" />
    <link rel="self" type="application/atom+xml" href="http://blog.codingnow.com/atom.xml" />
   <id>tag:blog.codingnow.com,2010://1</id>
    <link rel="service.post" type="application/atom+xml" href="http://linode.codingnow.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=1" title="云风的 BLOG" />
    <updated>2010-03-15T13:14:05Z</updated>
    <subtitle>思绪来得快去得也快，偶尔会在这里停留</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 3.2b5</generator>
 
<entry>
    <title>我诅咒帮网易做 OA 系统的公司</title>
    <link rel="alternate" type="text/html" href="http://blog.codingnow.com/2010/03/netease_oa.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://linode.codingnow.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=552" title="我诅咒帮网易做 OA 系统的公司" />
    <id>tag:blog.codingnow.com,2010://1.552</id>
    
    <published>2010-03-15T13:01:27Z</published>
    <updated>2010-03-15T13:14:05Z</updated>
    
    <summary>据说公司的 OA 系统是买来的。不知道是谁做的，反正一刹那，我想把这帮人拖出来打一顿。好吧，我不够淡定。 一直以来，这套 OA 系统只支持 IE ，还需要装个 ActiveX 控件才能得到完整的特性。怨声载道啊。这也就忍了。https 的证书没配置好，每次都要求确认一下。我觉得吧，公司还不至于花不了这点钱弄个正式的安全证书。罢了，这也忍忍。 这两天做招聘面试的流程。我的面试记录是写在纸上的。辛辛苦苦的把几份都录入到 OA 系统里。然后电子流程走了一圈。因为到某个环节的流程错误，被退回了。 结果，我输入的面试记录全部被清空了 ！现在要重新敲一遍。...</summary>
    <author>
        <name>云风</name>
        <uri>http://www.codingnow.com</uri>
    </author>
            <category term="网易" />
            <category term="杂记" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.codingnow.com/">
        <![CDATA[<p>据说公司的 OA 系统是买来的。不知道是谁做的，反正一刹那，我想把这帮人拖出来打一顿。好吧，我不够淡定。</p>

<p>一直以来，这套 OA 系统只支持 IE ，还需要装个 ActiveX 控件才能得到完整的特性。怨声载道啊。这也就忍了。https 的证书没配置好，每次都要求确认一下。我觉得吧，公司还不至于花不了这点钱弄个正式的安全证书。罢了，这也忍忍。</p>

<p>这两天做招聘面试的流程。我的面试记录是写在纸上的。辛辛苦苦的把几份都录入到 OA 系统里。然后电子流程走了一圈。因为到某个环节的流程错误，被退回了。</p>

<p>结果，我输入的面试记录全部被清空了 ！现在要重新敲一遍。</p>
]]>
        <![CDATA[<p>然后 popo 、打电话跟人抱怨这个事情，花得精力已经比重敲一次多了。明天等人从数据库里把原来输入的数据找回来。</p>

<p>怪不得杭州这边分公司报销还在用纸的单子，不走电子的 OA 。尽管不那么环保。</p>
]]>
    </content>
</entry>
<entry>
    <title>我所偏爱的 C 语言面向对象编程范式</title>
    <link rel="alternate" type="text/html" href="http://blog.codingnow.com/2010/03/object_oriented_programming_in_c.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://linode.codingnow.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=551" title="我所偏爱的 C 语言面向对象编程范式" />
    <id>tag:blog.codingnow.com,2010://1.551</id>
    
    <published>2010-03-13T08:23:43Z</published>
    <updated>2010-03-13T08:36:37Z</updated>
    
    <summary>面向对象编程不是银弹。大部分场合，我对面向对象的使用非常谨慎，能不用则不用。相关的讨论就不展开了。 但是，某些场合下，采用面向对象的确是比较好的方案。比如 UI 框架，又比如 3d 渲染引擎中的场景管理。C 语言对面向对象编程并没有原生支持，但没有原生支持并不等于不适合用 C 写面向对象程序。反而，我们对具体实现方式有更多的选择。 大部分用 C 写面向对象程序的程序员受 C++ 影响颇深。企图用宏模拟出一个常见 C++ 编译器已经实现的对象模型。于我愚见，这并不是一个好的方向。C++ 的对象模型，本质上是为了追求实现层的性能，并直接体现出来。就有如在 C++ 中被滥用的 inline ，的确有效，却破坏了分离原则。C++ 的继承是过紧的耦合。 我所理解的面向对象，是让不同的数据元有共同的操作方式，适合成组的处理。根据操作方式的不同，我们会对数据元做不同的分组。一个数据可能出现在这个组里，也可以出现在那个组里。这取决于你从不同的方面提取的共性。这些可供统一操作的共性称之为接口（Interface），接口在 C 语言中，表现为一组函数指针的集合。放在 C++ 中，即为虚表。 我所偏爱的面向对象实现方式（使用 C 语言）是这样的：...</summary>
    <author>
        <name>云风</name>
        <uri>http://www.codingnow.com</uri>
    </author>
            <category term="语言与设计" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.codingnow.com/">
        <![CDATA[<p>面向对象编程不是银弹。大部分场合，我对面向对象的使用非常谨慎，能不用则不用。相关的讨论就不展开了。</p>

<p>但是，某些场合下，采用面向对象的确是比较好的方案。比如 UI 框架，又比如 3d 渲染引擎中的场景管理。C 语言对面向对象编程并没有原生支持，但没有原生支持并不等于不适合用 C 写面向对象程序。反而，我们对具体实现方式有更多的选择。</p>

<p>大部分用 C 写面向对象程序的程序员受 C++ 影响颇深。企图用宏模拟出一个常见 C++ 编译器已经实现的对象模型。于我愚见，这并不是一个好的方向。C++ 的对象模型，本质上是为了追求实现层的性能，并直接体现出来。就有如在 C++ 中被滥用的 inline ，的确有效，却破坏了分离原则。C++ 的继承是过紧的耦合。</p>

<p>我所理解的面向对象，是让不同的数据元有共同的操作方式，适合成组的处理。根据操作方式的不同，我们会对数据元做不同的分组。一个数据可能出现在这个组里，也可以出现在那个组里。这取决于你从不同的方面提取的共性。这些可供统一操作的共性称之为接口（Interface），接口在 C 语言中，表现为一组函数指针的集合。放在 C++ 中，即为虚表。</p>

<p>我所偏爱的面向对象实现方式（使用 C 语言）是这样的：</p>
]]>
        <![CDATA[<p>若有一组数据，我们需要让他们看起来都有一种叫作 foo 的共性。把符合这样的数据都称为 <code>foo_object</code> 。通常，我们会有如下 api 去操控 <code>foo_object</code> 。</p>

<pre class="mtc_block"><span class="c_KeywordANSI def_Keyword">struct</span> foo_object<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

<span class="c_KeywordANSI def_Keyword">struct</span> foo_object <span class="c_Symbol def_Symbol">*</span> foo_create<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> foo_release<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_KeywordANSI def_Keyword">struct</span> foo_object <span class="c_Symbol def_Symbol">*</span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> foo_dosomething<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_KeywordANSI def_Keyword">struct</span> foo_object <span class="c_Symbol def_Symbol">*</span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span></pre>

<p>在具体实现时，会在一个叫 foo.c 的实现文件中，定义出 <code>foo_object</code> 结构，里面有一些 <code>foo_dosomething</code> 所需的数据成员。</p>

<p>但是，以上还不能满足要求。因为，我们会有不同的数据，他们只是表现出 <code>foo_object</code> 某些方面的特性。对于不同的数据，它们在 dosomething 时，实际所做的操作也有所区别。这时，我们需要定义出一个接口，供 foo.c 内部使用。那么，以上的头文件就需要做一些修改，把接口 <code>i_foo</code> 的定义加进去，并修改 create 函数。</p>

<pre class="mtc_block"><span class="c_KeywordANSI def_Keyword">struct</span> <span class="c_StructOutline def_Outlined def_Special">i_foo </span><span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> <span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol">*</span>foobar<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> <span class="c_Symbol def_Symbol">*</span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

<span class="c_KeywordANSI def_Keyword">struct</span> foo_object <span class="c_Symbol def_Symbol">*</span> foo_create<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_KeywordANSI def_Keyword">struct</span> i_foo <span class="c_Symbol def_Symbol">*</span>iface<span class="c_Symbol def_Symbol">,</span> <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> <span class="c_Symbol def_Symbol">*</span>data<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span></pre>

<p>这里稍做解释。<code>i_foo</code> 是供 <code>foo_dosomething</code> 内部使用的一组接口。构造 <code>foo_object</code> 时，我们把一个外部数据 data 和为 <code>foo_object</code> 相关特性定义出的 <code>i_foo</code> 接口捆绑在一起，传入构造函数 <code>foo_create</code> 。一般，我还会会每个符合 <code>foo_object</code> 特性的对象实现一个方法来得到对应的 <code>i_foo</code> ，如：</p>

<pre class="mtc_block"><span class="c_KeywordANSI def_Keyword">struct</span> foobar<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

<span class="c_KeywordANSI def_Keyword">struct</span> i_foo <span class="c_Symbol def_Symbol">*</span> foobar_foo<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="c_KeywordANSI def_Keyword">struct</span> foobar <span class="c_Symbol def_Symbol">*</span> foobar_create<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> foobar_release<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_KeywordANSI def_Keyword">struct</span> foobar <span class="c_Symbol def_Symbol">*</span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span></pre>

<p>创建一个 <code>foo_object</code> 对象的代码看起来是这样：</p>

<pre class="mtc_block"><span class="c_KeywordANSI def_Keyword">struct</span> foobar <span class="c_Symbol def_Symbol">*</span>foobar <span class="c_Symbol def_Symbol">=</span> foobar_create<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
  <span class="c_KeywordANSI def_Keyword">struct</span> foo_object <span class="c_Symbol def_Symbol">*</span> fobj <span class="c_Symbol def_Symbol">=</span> foo_create<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>foobar_foo<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="c_Symbol def_Symbol">,</span> foobar<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span></pre>

<p><code>struct foo_object</code> 的定义中，必然要记录 <code>i_foo</code> 的接口指针和 data 数据指针。从 C++ 的观点看，<code>foo_object</code> 是基类，它也会有一些基类成员和非虚的成员函数。具体的派生类在实现时，改写了虚表 <code>i_foo</code> 的内容（重载了虚函数）。data 数据是在对基类 <code>foo_object</code> 继承时扩展的数据成员。但，在这里，我们使用了组合的方式来扩展成员。这增加了一层间接性，但提供了更低的耦合。其中的优劣暂且不讨论了。</p>

<p>通常看起来会是这样：</p>

<pre class="mtc_block"><span class="c_KeywordANSI def_Keyword">struct</span> <span class="c_StructOutline def_Outlined def_Special">foo_object </span><span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    <span class="c_KeywordANSI def_Keyword">struct</span> i_foo <span class="c_Symbol def_Symbol">*</span> vtbl<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> <span class="c_Symbol def_Symbol">*</span> data<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> <span class="c_Symbol def_Symbol">*</span> others<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

<span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span>
<span class="c_FuncOutline def_Outlined def_Special">foo_dosomething</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_KeywordANSI def_Keyword">struct</span> foo_object <span class="c_Symbol def_Symbol">*</span>fobj<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    fobj<span class="c_Symbol def_Symbol">-</span><span class="c_Symbol def_Symbol">&gt;</span>vtbl<span class="c_Symbol def_Symbol">-</span><span class="c_Symbol def_Symbol">&gt;</span>foobar<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>fobj<span class="c_Symbol def_Symbol">-</span><span class="c_Symbol def_Symbol">&gt;</span>data<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    <span class="c_LineComment def_LineComment def_Comment def_Syntax">// do something else</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span></pre>

<p>此处还有另一个问题：data 的生命期该由谁来负责？</p>

<p>生命期管理是个很大的课题。也是大多数使用 C/C++ 开发的软件的复杂度重要来源。我个人倾向于把生命期管理独立出来解决。所以 <code>foo_object</code> 模块一般并不负责 data 的生命期管理。它只负责 <code>struct foo_object</code> 的资源释放。</p>

<p>自己经营自己，是我的 C 语言软件开发的观点之一。我倾向于采用混合语言编程来更好的解决这个问题。比如 C 和 Lua ，或者 C 和 C++ 。如果不采用混合语言编程，那么也可以在之后，增加一个同样用 C 语言编写的层次来管理。这个话题，留到下次来讲。</p>

<p>剥离出生命期管理，代码量可以减少很多，也不容易犯错误。</p>

<p>ps. C 语言是一个弱类型的语言。至少比 C++ 要弱一些。这表现在：</p>

<p>void * 在 C 语言中可以指代任意数据指针。你可以把任意数据指针赋值给一个 void * 变量，也可以把一个 void * 变量赋给特定的指针类型变量。（这在 C++ 中不推荐，并会被编译器警告）</p>

<p>C 语言中的函数指针也比较有趣。通常，不同类型的函数指针相互赋值是会引起编译器警告的（类型不同）。当然，我们可以用一个 void * 来解决问题。但有时候，我们期望让类型检查严格一些，至少我们不希望把一个数据指针赋值给一个函数指针。但希望编译器不要理会函数参数的差异。</p>

<p>在 C 语言中，void (*foo)() 可以被赋予任意返回 void 的函数指针。即，你可以把 void foobar(int) 的地址赋予前面的 foo 变量（这是由 C 标准的参数传递规则保证的）。</p>

<p>所以，在 C 语言编程中需要注意。如果你想定义一个不接受参数的函数，并让编译器帮你检查出那些错误的多传递了参数的语句。你必须在 .h 文件中严格定义 void foo(void) 以示 foo 函数不接受参数。</p>

<p>在传统的 C 语言中，对结构初始化需要非常小心。这里，我们的 <code>i_foo</code> 接口定义就使用了 C 里的结构。这需要非常谨慎小心。（没有 C++ 编译器帮你做这件事）</p>

<p>C99 新增加的语法增强了这点（在初始化结构时，可以不依赖次序，而写出成员的名字）。值得采用。</p>
]]>
    </content>
</entry>
<entry>
    <title>感谢各位投递简历和参加面试的同学</title>
    <link rel="alternate" type="text/html" href="http://blog.codingnow.com/2010/03/iioauiioaeoaein.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://linode.codingnow.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=550" title="感谢各位投递简历和参加面试的同学" />
    <id>tag:blog.codingnow.com,2010://1.550</id>
    
    <published>2010-03-12T06:47:38Z</published>
    <updated>2010-03-12T07:32:12Z</updated>
    
    <summary>昨天，我们工作室这次的编辑器一职的程序招聘工作结束了。 比我预期的时间和人选上都超过了预期。谢谢大家的支持。 原来我的计划是找到两个合适的人来做这些事情，但实际上，这次来面试的数十位同学中达到我们心目中要求的人远远超过了这个数字。我想我也是非常细致的做了这一系列面试工作的，每个来我们办公室面试的同学，都做了一个半小时到两个半小时的沟通交流。 直到最后，依旧纠结于在五六个合适人选中该如何选择。虽然我们最终多安排了一个职位，但还是很遗憾不能与各位想来我们这里的朋友在未来一起共事。...</summary>
    <author>
        <name>云风</name>
        <uri>http://www.codingnow.com</uri>
    </author>
            <category term="杂记" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.codingnow.com/">
        <![CDATA[<p>昨天，我们工作室这次的编辑器一职的程序招聘工作结束了。</p>

<p>比我预期的时间和人选上都超过了预期。谢谢大家的支持。</p>

<p>原来我的计划是找到两个合适的人来做这些事情，但实际上，这次来面试的数十位同学中达到我们心目中要求的人远远超过了这个数字。我想我也是非常细致的做了这一系列面试工作的，每个来我们办公室面试的同学，都做了一个半小时到两个半小时的沟通交流。</p>

<p>直到最后，依旧纠结于在五六个合适人选中该如何选择。虽然我们最终多安排了一个职位，但还是很遗憾不能与各位想来我们这里的朋友在未来一起共事。</p>
]]>
        <![CDATA[<p>之前有些地理位置上比较远的同学，过年时曾经去 email 说安排一次面试。之后考虑到路途遥远，而我们已经收到了很多附近的同学的面试请求。这段时间又的确找到了合适的人选。顾而没能有机会邀请你们来杭州一叙，很是抱歉。</p>

<p>另，我们在北京和广州的工作室也在招聘。如果愿意，我可以代为转交简历。</p>

<p>我已经给所有参加面试的和投递简历的同学回复了邮件。但还是有可能遗漏。在此致歉。希望能够谅解。</p>

<p>btw, gameres 上有一则招聘帖”杭州网易风云诚聘各类游戏人才“ ，最近几天好多人问起。其实跟我这里没有关系的 :) </p>
]]>
    </content>
</entry>
<entry>
    <title>为什么一定要有密码?</title>
    <link rel="alternate" type="text/html" href="http://blog.codingnow.com/2010/02/no_password.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://linode.codingnow.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=549" title="为什么一定要有密码?" />
    <id>tag:blog.codingnow.com,2010://1.549</id>
    
    <published>2010-02-27T16:04:53Z</published>
    <updated>2010-02-27T16:29:37Z</updated>
    
    <summary>以前写过一篇 可不可以只有密码没有用户名？ 。里面提过一个让用户使用 email 做用户名，不设置密码的方案。今天想细化一下。 不设置密码有时候比设置密码，给用户的安全方面的感觉更好。因为，有些服务用户并不在乎帐户数据的私密性，也不在乎被人冒充。（比如在我的 blog 的留言，并不需要注册）要求输入一个密码，对用户反而是件很纠结的事情。用自己常用密码吧，若被服务商恶意记录的话，自己别的位置的帐户变得不太安全。随便选个新密码吧，很可能忘记。输入个简单的统一密码吧，基本行同虚设，跟没有密码区别不大。反而提供了虚假的安全感。这种安全感比没有更差。 而服务提供商在乎的只是用帐户名去标识一个用户，制作用户注册的流程，即费时，又费力，还提高了新用户进入的门槛。 我个人认为这样会好一些。...</summary>
    <author>
        <name>云风</name>
        <uri>http://www.codingnow.com</uri>
    </author>
            <category term="杂记" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.codingnow.com/">
        <![CDATA[<p>以前写过一篇 <a href="http://blog.codingnow.com/2006/10/password.html">可不可以只有密码没有用户名？</a> 。里面提过一个让用户使用 email 做用户名，不设置密码的方案。今天想细化一下。</p>

<p>不设置密码有时候比设置密码，给用户的安全方面的感觉更好。因为，有些服务用户并不在乎帐户数据的私密性，也不在乎被人冒充。（比如在我的 blog 的留言，并不需要注册）要求输入一个密码，对用户反而是件很纠结的事情。用自己常用密码吧，若被服务商恶意记录的话，自己别的位置的帐户变得不太安全。随便选个新密码吧，很可能忘记。输入个简单的统一密码吧，基本行同虚设，跟没有密码区别不大。反而提供了虚假的安全感。这种安全感比没有更差。</p>

<p>而服务提供商在乎的只是用帐户名去标识一个用户，制作用户注册的流程，即费时，又费力，还提高了新用户进入的门槛。</p>

<p>我个人认为这样会好一些。</p>
]]>
        <![CDATA[<ol>
<li><p>用户使用仅仅需要输入一个他使用的 email 地址（鉴于中国国情，另兼容输入 QQ 号也可以）</p></li>
<li><p>当发现用户第一次使用这个服务，触发注册确认的流程。提示用户激活，从 email 中收取激活链接。在这步，如果用户是误输入帐号（比如他曾经注册过，就会发现自己输入错误），可以取消。这样不会对他人造成骚扰。ps. 这个步骤也可以酌情取消或可选（并不阻止用户进行下面的服务体验），毕竟让用户通过 email 确认也有一定门槛。</p></li>
<li><p>用户登陆后，可以选择给帐号加上密码，但不是必须。可以根据用户的使用情况，采集用户在帐户里使用的服务种类、数量和时间，向用户推荐加上密码保护。或者建议用户不要加密码。</p></li>
<li><p>在用户不采用密码保护期间，收集用户登陆的资料，例如 ip 地址和登陆时间。对异常登陆做一些猜测。并结合用户帐号的安全性需求，定期发 email 通知用户。或是定期向用户 email 发送帐号登陆记录（以不骚扰用户的频率），比如长期没有使用服务，某天登陆了，就发一封 email 通知用户。</p></li>
</ol>
]]>
    </content>
</entry>
<entry>
    <title>在 C++ 中引入 gc 后的对象初始化</title>
    <link rel="alternate" type="text/html" href="http://blog.codingnow.com/2010/02/cpp_ctor.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://linode.codingnow.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=548" title="在 C++ 中引入 gc 后的对象初始化" />
    <id>tag:blog.codingnow.com,2010://1.548</id>
    
    <published>2010-02-24T13:04:24Z</published>
    <updated>2010-02-24T13:20:19Z</updated>
    
    <summary>这几天白天都在安排面试，其实还是有点累的。晚上就随便写点程序，好久没摸 C++ ，有点生疏。也算是娱乐一下吧。 主要工作其实是在 C 库的基础上做一个 C++ 的中间层。跟在 C 库的基础上做 lua 中间层差不太多。前几天加入了 gc 后，发现了一些有趣的用法。 比如对于构造对象。 C 的 api 中，如果创建一个对象失败，就会返回空指针。但是对于 C++ 就不一样了，new 是不应返回空指针的。书本上的推荐做法是在构造函数里抛异常。但是我又不太想进一步的引入异常机智，怎么办呢？...</summary>
    <author>
        <name>云风</name>
        <uri>http://www.codingnow.com</uri>
    </author>
            <category term="语言与设计" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.codingnow.com/">
        <![CDATA[<p>这几天白天都在安排面试，其实还是有点累的。晚上就随便写点程序，好久没摸 C++ ，有点生疏。也算是娱乐一下吧。</p>

<p>主要工作其实是在 C 库的基础上做一个 C++ 的中间层。跟在 C 库的基础上做 lua 中间层差不太多。前几天加入了 gc 后，发现了一些有趣的用法。</p>

<p>比如对于构造对象。 C 的 api 中，如果创建一个对象失败，就会返回空指针。但是对于 C++ 就不一样了，new 是不应返回空指针的。书本上的推荐做法是在构造函数里抛异常。但是我又不太想进一步的引入异常机智，怎么办呢？</p>
]]>
        <![CDATA[<p>简单的方法是让 C++ 的封装类的构造函数什么都不干。btw, 我听 google 的 Mike Burrows 也讲过 popular C++ constructs can be bad for abstraction 。</p>

<p>然后加一个 init 函数来初始化这个对象，成功则返回 this 指针，失败则返回 NULL。</p>

<p>如果没有 gc 的时候，我需要这样做：</p>

<pre>
A *a = new A;
if (!a->init()) {
  delete a;
  a = NULL;
}
</pre>

<p>有了 gc 后很方便，只需要</p>

<pre>
A *a = (new A)->init();
</pre>

<p>嘿嘿，有 gc 还是方便很多呀。只是 new 的操作优先级让我有点不爽。</p>

<p>ps. 我知道即使没有 gc ，我也可以用很现代的 template 技术做到同样的事情。而且代码看起来更有品味。不过我感觉自己越来越老土了，写 C++ 也越来越 C Style 了。完全没有 10 多年前对 C++ 的火热激情。</p>
]]>
    </content>
</entry>
<entry>
    <title>C++ 中的接口继承与实现继承</title>
    <link rel="alternate" type="text/html" href="http://blog.codingnow.com/2010/02/cpp_inherit.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://linode.codingnow.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=547" title="C++ 中的接口继承与实现继承" />
    <id>tag:blog.codingnow.com,2010://1.547</id>
    
    <published>2010-02-23T12:55:38Z</published>
    <updated>2010-02-23T12:57:41Z</updated>
    
    <summary>为这篇 blog 打腹稿的时候，觉得自己很贱，居然玩弄 C++ 起来了。还用了 template 这种很现代、很有品味的东西。写完后一定要检讨。 起因是昨天写的那篇关于 gc 的框架。里面用了虚继承和虚的析构函数。这会导致 ABI 不统一，就是这个原因，COM 就不用这些。 说起 COM ，我脑子里就浮现出各种条条框框。对用 COM 搭建起来的 Windows 这种巨无霸，那可真是高山仰止。套 dingdang 的 popo 签名：虽不能至，心向往之。 好吧，我琢磨了一下如何解决下面的问题，又不把虚继承啦，虚析构函数啦之类的暴露在接口中。 简单说，我有几个接口是一层层继承下来的，唤作 iA iB 。iA 是基类，iB 继承至 iA 。 然后，我写了一个 cA 类，实现了 iA 接口；接下来我希望再写一个 cB 类，实现...</summary>
    <author>
        <name>云风</name>
        <uri>http://www.codingnow.com</uri>
    </author>
            <category term="语言与设计" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.codingnow.com/">
        <![CDATA[<p>为这篇 blog 打腹稿的时候，觉得自己很贱，居然玩弄 C++ 起来了。还用了 template 这种很现代、很有品味的东西。写完后一定要检讨。</p>

<p>起因是昨天写的那篇<a href="http://blog.codingnow.com/2010/02/cpp_gc.html">关于 gc 的框架</a>。里面用了虚继承和虚的析构函数。这会导致 ABI 不统一，就是这个原因，COM 就不用这些。</p>

<p>说起 COM ，我脑子里就浮现出各种条条框框。对用 COM 搭建起来的 Windows 这种巨无霸，那可真是高山仰止。套 dingdang 的 popo 签名：虽不能至，心向往之。</p>

<p>好吧，我琢磨了一下如何解决下面的问题，又不把虚继承啦，虚析构函数啦之类的暴露在接口中。</p>

<p>简单说，我有几个接口是一层层继承下来的，唤作 iA iB 。iA 是基类，iB 继承至 iA 。</p>

<p>然后，我写了一个 cA 类，实现了 iA 接口；接下来我希望再写一个 cB 类，实现 iB 接口。但是，iB 接口的基类 iA 部分，希望复用已经写好的 cA 类。我想这并不是一个过分的需求。正如当年手写 COM 组件时，我对手写那些 AddRef Release QueryInterface 深恶痛绝。</p>

<p>用虚继承可以简单的满足这个需求：</p>
]]>
        <![CDATA[<pre class="mtc_block"><span class="c_Preproc def_Directive">#<span class="c_PreprocWord def_DirectiveContent def_Directive">define</span> <span class="c_DefineOutline def_Outlined def_Special">interface</span> </span>

interface iA <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> foo<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="c_Symbol def_Symbol">=</span> <span class="def_NumberDec def_Number">0</span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

interface iB <span class="c_StructureSymbol def_SymbolStrong def_Symbol">:</span> virtual public iA <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> bar<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="c_Symbol def_Symbol">=</span> <span class="def_NumberDec def_Number">0</span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

class cA <span class="c_StructureSymbol def_SymbolStrong def_Symbol">:</span> virtual public iA <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> foo<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    <span class="c_LineComment def_LineComment def_Comment def_Syntax">// etc...</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

class cB <span class="c_StructureSymbol def_SymbolStrong def_Symbol">:</span> virtual cA <span class="c_Symbol def_Symbol">,</span> virtual public iB <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> bar<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    <span class="c_LineComment def_LineComment def_Comment def_Syntax">// etc...</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span></pre>

<p>每当我创建一个 cB 对象，并返回 iB 接口指针时，cB 对象内部的继承关系，可以用个简单的图表示如下：</p>

<pre>
iB  +- cB
|      |
+      +
iA  +- cA
</pre>

<p>但是，我们在公开的 iX 接口定义中，使用了虚继承。这在不同编译器上可能有一些差异。如果组件写好后，动态库想拿给别人用，无法预知别人用的编译器，就会有问题。</p>

<p>嗯，这可能是个伪命题。或许不需要解决。但感觉最近有点犯贱。那么下面就讨论一下：怎么不在接口定义中使用 virtual 继承，而达到同样的目的呢？</p>

<p>我的方法是用 template 做一个中间层，然后手工写一些转发代码：</p>

<pre class="mtc_block"><span class="c_Preproc def_Directive">#<span class="c_PreprocWord def_DirectiveContent def_Directive">define</span> <span class="c_DefineOutline def_Outlined def_Special">interface</span> struct</span>

interface iA <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> foo<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="c_Symbol def_Symbol">=</span> <span class="def_NumberDec def_Number">0</span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

interface iB <span class="c_StructureSymbol def_SymbolStrong def_Symbol">:</span> public iA <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> bar<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="c_Symbol def_Symbol">=</span> <span class="def_NumberDec def_Number">0</span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

class cA <span class="c_StructureSymbol def_SymbolStrong def_Symbol">:</span> public iA <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
<span class="c_Label def_Label">public:</span>
    virtual <span class="c_Symbol def_Symbol">~</span>cA<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> foo<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    <span class="c_LineComment def_LineComment def_Comment def_Syntax">// etc...</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

template<span class="c_Symbol def_Symbol">&lt;</span> typename IF <span class="c_Symbol def_Symbol">&gt;</span>
class tA <span class="c_StructureSymbol def_SymbolStrong def_Symbol">:</span> cA <span class="c_Symbol def_Symbol">,</span> public IF <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> <span class="c_FuncOutline def_Outlined def_Special">foo</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span> cA<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>foo<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

class cB <span class="c_StructureSymbol def_SymbolStrong def_Symbol">:</span> tA<span class="c_Symbol def_Symbol">&lt;</span>iB<span class="c_Symbol def_Symbol">&gt;</span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> bar<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    <span class="c_LineComment def_LineComment def_Comment def_Syntax">// etc...</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span></pre>

<p>这样，模板 tA 解决了多继承后，接口实现的转发问题。（因为手工转发了 foo 的调用）</p>

<p>既然要转发，为什么要用多继承而不用组合呢？因为我需要 ~cA 正确的发挥作用。比如在 cA::foo 中可以正确的 delete this 。</p>

<p>下一个问题：如果还有一个 iC 继承于 iB ，然后在实现 cC 的时候，想复用 cB ，同时不想写太多的 api 转发代码。怎么办？</p>

<p>我初步的想法是，把 tA 模板的实现都改成虚继承，然后做一个 tB 模板。转发 cB 扩展的几个 api 。然后让 cC 从 tA tB 虚继承出来。随手写了一个，但编译有点问题，不想深入研究了。弄出个模板虚拟多继承，绝对是蛋痛啊。</p>

<p>研究 C++ 果然是浪费生命。</p>
]]>
    </content>
</entry>
<entry>
    <title>在 C++ 中实现一个轻量的标记清除 gc 系统</title>
    <link rel="alternate" type="text/html" href="http://blog.codingnow.com/2010/02/cpp_gc.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://linode.codingnow.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=546" title="在 C++ 中实现一个轻量的标记清除 gc 系统" />
    <id>tag:blog.codingnow.com,2010://1.546</id>
    
    <published>2010-02-22T11:34:30Z</published>
    <updated>2010-02-25T17:39:44Z</updated>
    
    <summary>最近想把 engine 做一个简单 C++ 封装，结合 QT 使用。engine 本身是用纯 C 实现的，大部分应用基于 lua 开发。对对象生命期管理也依赖 lua 的 gc 系统。关于这部分的设计，可以参考我以前写的一篇 为 lua 封装 C 对象的生存期管理问题 。 当我们把中间层搬到 C++ 中时，遇到的问题之一就是，C++ 没有原生的 gc 支持。我也曾经写过一个 gc 库。但在特定应用下还不够简洁。这几天过年休息，仔细考虑了一下相关的需求，尝试实现了一个更简单的 gc 框架。不到 200 行代码吧，我直接列在这篇 blog 里。 这些尚是一些玩具代码，我花了一天时间来写。有许多考虑不周的地方，以及不完整的功能。但可以阐明一些基本思路。...</summary>
    <author>
        <name>云风</name>
        <uri>http://www.codingnow.com</uri>
    </author>
            <category term="语言与设计" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.codingnow.com/">
        <![CDATA[<p>最近想把 engine 做一个简单 C++ 封装，结合 QT 使用。engine 本身是用纯 C 实现的，大部分应用基于 lua 开发。对对象生命期管理也依赖 lua 的 gc 系统。关于这部分的设计，可以参考我以前写的一篇 <a href="http://blog.codingnow.com/2009/03/lua_c_wrapper.html">为 lua 封装 C 对象的生存期管理问题</a> 。</p>

<p>当我们把中间层搬到 C++ 中时，遇到的问题之一就是，C++ 没有原生的 gc 支持。我也曾经<a href="http://blog.codingnow.com/2008/06/gc_for_c.html">写过一个 gc 库</a>。但在特定应用下还不够简洁。这几天过年休息，仔细考虑了一下相关的需求，尝试实现了一个更简单的 gc 框架。不到 200 行代码吧，我直接列在这篇 blog 里。</p>

<p>这些尚是一些玩具代码，我花了一天时间来写。有许多考虑不周的地方，以及不完整的功能。但可以阐明一些基本思路。</p>
]]>
        <![CDATA[<p>首先我需要一个标记清除的 gc 系统，用来解决引用记数不容易解决的循环引用问题。它的实现不想比引用记数复杂太多，并有相同甚至更高的性能。</p>

<p>我不想使用复杂的 template 技术，利用太多的语法糖让使用看起来简单。如果需要让这些 C++ 代码看起来更现代，更有“品味”，我想也不是很难的事情。</p>

<p>接口和实现希望尽量分离，对用的人少暴露细节。但不拘泥于教条，强求做成类似 COM 那样的通用 ABI 。还是尽量利用 C++ 语言本身提供的机制，不滥用。</p>

<p>使用尽量简单，不要让使用人员有太大负担。</p>

<p>功能满足最低需求即可。代码容易阅读，使用人员可以很快理解原理，不至于误用。也方便日后扩展以适应新的需求。</p>

<p>代码如下：（<a href="http://blog.codingnow.com/file/cppgc0.1.zip">可打包下载</a>）</p>

<pre class="mtc_block"><span class="c_Comment def_Comment def_Syntax"><span class="def_PairStart def_Special">/*</span>
 *  filename:  i_gcobject.h
 *  Copyright (c) 2010 ,
 *      Cloud Wu . All rights reserved.
 *
 *      <span class="def_URL def_URI">http://www.codingnow.com</span>
 *
 *  Use, modification and distribution are subject to the &quot;New BSD License&quot;
 *  as listed at &lt;url: <span class="def_URL def_URI">http://www.opensource.org/licenses/bsd-license.php</span> &gt;.
 <span class="def_PairEnd def_Special">*/</span></span>

<span class="c_Preproc def_Directive">#<span class="c_PreprocWord def_DirectiveContent def_Directive">ifndef</span> interfacce_gcobject_h</span>
<span class="c_Preproc def_Directive">#<span class="c_PreprocWord def_DirectiveContent def_Directive">define</span> <span class="c_DefineOutline def_Outlined def_Special">interfacce_gcobject_h</span></span>

<span class="c_Preproc def_Directive">#<span class="c_PreprocWord def_DirectiveContent def_Directive">define</span> <span class="c_DefineOutline def_Outlined def_Special">interface</span> struct</span>

interface i_gcobject <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    virtual <span class="c_FuncOutline def_Outlined def_Special"><span class="c_Symbol def_Symbol">~</span>i_gcobject</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span><span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>
    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> <span class="c_FuncOutline def_Outlined def_Special">touch</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span><span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>
    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> mark<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="c_Symbol def_Symbol">=</span> <span class="def_NumberDec def_Number">0</span> <span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> grab<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="c_Symbol def_Symbol">=</span> <span class="def_NumberDec def_Number">0</span> <span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> release<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="c_Symbol def_Symbol">=</span> <span class="def_NumberDec def_Number">0</span> <span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

    <span class="c_KeywordANSI def_Keyword">static</span> <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> collect<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

<span class="c_Preproc def_Directive">#<span class="c_PreprocWord def_DirectiveContent def_Directive">endif</span></span></pre>

<p>所有支持 gc 管理的接口都继承至 <code>i_gcobject</code> ，提供三个方法，</p>

<ol>
<li><p>mark 可以把这个对象打上标记，被标记的对象将不会被 collect 回收。</p></li>
<li><p>grab 将对象挂接到一个被称呼为 root 的特殊 gcobject 上。</p></li>
<li><p>release 将对象从 root 上取掉。</p></li>
</ol>

<p>另提供 touch 的模板方法供 mark 回调，用来标记同一对象中的不同部分。</p>

<p>mark 方法一般在 touch 方法中使用，另外，collect 方法将主动调用  root 的 mark 。</p>

<hr />

<pre class="mtc_block"><span class="c_Comment def_Comment def_Syntax"><span class="def_PairStart def_Special">/*</span>
 *  filename:  i_gcholder.h
 *  Copyright (c) 2010 ,
 *      Cloud Wu . All rights reserved.
 *
 *      <span class="def_URL def_URI">http://www.codingnow.com</span>
 *
 *  Use, modification and distribution are subject to the &quot;New BSD License&quot;
 *  as listed at &lt;url: <span class="def_URL def_URI">http://www.opensource.org/licenses/bsd-license.php</span> &gt;.
 <span class="def_PairEnd def_Special">*/</span></span>

<span class="c_Preproc def_Directive">#<span class="c_PreprocWord def_DirectiveContent def_Directive">ifndef</span> interfacce_gcholder_h</span>
<span class="c_Preproc def_Directive">#<span class="c_PreprocWord def_DirectiveContent def_Directive">define</span> <span class="c_DefineOutline def_Outlined def_Special">interfacce_gcholder_h</span></span>

<span class="c_Preproc def_Directive">#<span class="c_PreprocInclude def_Path def_URI">include <span class="c_IncludeOutline def_Outlined def_Special"><span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairStart def_Special">&quot;</span></span>i_gcobject.h<span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairEnd def_Special">&quot;</span></span></span></span></span>

interface i_gcholder <span class="c_StructureSymbol def_SymbolStrong def_Symbol">:</span> virtual i_gcobject <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> hold<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>i_gcobject <span class="c_Symbol def_Symbol">*</span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="c_Symbol def_Symbol">=</span> <span class="def_NumberDec def_Number">0</span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> unhold<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>i_gcobject <span class="c_Symbol def_Symbol">*</span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="c_Symbol def_Symbol">=</span> <span class="def_NumberDec def_Number">0</span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

    <span class="c_KeywordANSI def_Keyword">static</span> i_gcholder <span class="c_Symbol def_Symbol">*</span> create<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

<span class="c_Preproc def_Directive">#<span class="c_PreprocWord def_DirectiveContent def_Directive">endif</span></span></pre>

<p><code>i_gcholder</code> 为 root 的接口，提供 hold 和 unhold 方法来挂接需要持久保留的 gcobject 。</p>

<hr />

<pre class="mtc_block"><span class="c_Comment def_Comment def_Syntax"><span class="def_PairStart def_Special">/*</span>
 *  filename:  gcobject.h
 *  Copyright (c) 2010 ,
 *      Cloud Wu . All rights reserved.
 *
 *      <span class="def_URL def_URI">http://www.codingnow.com</span>
 *
 *  Use, modification and distribution are subject to the &quot;New BSD License&quot;
 *  as listed at &lt;url: <span class="def_URL def_URI">http://www.opensource.org/licenses/bsd-license.php</span> &gt;.
 <span class="def_PairEnd def_Special">*/</span></span>

<span class="c_Preproc def_Directive">#<span class="c_PreprocWord def_DirectiveContent def_Directive">ifndef</span> gc_object_h</span>
<span class="c_Preproc def_Directive">#<span class="c_PreprocWord def_DirectiveContent def_Directive">define</span> <span class="c_DefineOutline def_Outlined def_Special">gc_object_h</span></span>

<span class="c_Preproc def_Directive">#<span class="c_PreprocInclude def_Path def_URI">include <span class="c_IncludeOutline def_Outlined def_Special"><span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairStart def_Special">&quot;</span></span>i_gcobject.h<span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairEnd def_Special">&quot;</span></span></span></span></span>

class gcobject <span class="c_StructureSymbol def_SymbolStrong def_Symbol">:</span> virtual i_gcobject <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    bool marked<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="c_Label def_Label">public:</span>
    gcobject<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> mark<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> grab<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> release<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    <span class="c_KeywordANSI def_Keyword">struct</span> f_unmarked<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

<span class="c_Preproc def_Directive">#<span class="c_PreprocWord def_DirectiveContent def_Directive">endif</span></span></pre>

<pre class="mtc_block"><span class="c_Comment def_Comment def_Syntax"><span class="def_PairStart def_Special">/*</span>
 *  filename:  gcobject.cpp
 *  Copyright (c) 2010 ,
 *      Cloud Wu . All rights reserved.
 *
 *      <span class="def_URL def_URI">http://www.codingnow.com</span>
 *
 *  Use, modification and distribution are subject to the &quot;New BSD License&quot;
 *  as listed at &lt;url: <span class="def_URL def_URI">http://www.opensource.org/licenses/bsd-license.php</span> &gt;.
 <span class="def_PairEnd def_Special">*/</span></span>

<span class="c_Preproc def_Directive">#<span class="c_PreprocInclude def_Path def_URI">include <span class="c_IncludeOutline def_Outlined def_Special"><span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairStart def_Special">&quot;</span></span>gcobject.h<span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairEnd def_Special">&quot;</span></span></span></span></span>
<span class="c_Preproc def_Directive">#<span class="c_PreprocInclude def_Path def_URI">include <span class="c_IncludeOutline def_Outlined def_Special"><span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairStart def_Special">&quot;</span></span>i_gcholder.h<span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairEnd def_Special">&quot;</span></span></span></span></span>

<span class="c_Preproc def_Directive">#<span class="c_PreprocInclude def_Path def_URI">include <span class="c_IncludeOutline def_Outlined def_Special"><span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairStart def_Special">&lt;</span></span>vector<span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairEnd def_Special">&gt;</span></span></span></span></span>
<span class="c_Preproc def_Directive">#<span class="c_PreprocInclude def_Path def_URI">include <span class="c_IncludeOutline def_Outlined def_Special"><span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairStart def_Special">&lt;</span></span>algorithm<span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairEnd def_Special">&gt;</span></span></span></span></span>

<span class="c_KeywordANSI def_Keyword">static</span> bool gc_trigger<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="c_KeywordANSI def_Keyword">static</span> std<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>vector<span class="c_Symbol def_Symbol">&lt;</span>gcobject <span class="c_Symbol def_Symbol">*</span><span class="c_Symbol def_Symbol">&gt;</span> gc_pool<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="c_KeywordANSI def_Keyword">static</span> i_gcholder <span class="c_Symbol def_Symbol">*</span> gc_root <span class="c_Symbol def_Symbol">=</span> i_gcholder<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>create<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

<span class="c_KeywordANSI def_Keyword">struct</span> <span class="c_StructOutline def_Outlined def_Special">gcobject<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>f_unmarked </span><span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    bool <span class="c_FuncOutline def_Outlined def_Special">operator</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>gcobject <span class="c_Symbol def_Symbol">*</span> value<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
        bool unmarked <span class="c_Symbol def_Symbol">=</span> value<span class="c_Symbol def_Symbol">-</span><span class="c_Symbol def_Symbol">&gt;</span>marked <span class="c_Symbol def_Symbol">!</span><span class="c_Symbol def_Symbol">=</span> gc_trigger<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
        <span class="c_KeywordANSI def_Keyword">if</span> <span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>unmarked<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
            delete value<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
        <span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>
        <span class="c_KeywordANSI def_Keyword">return</span> unmarked<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    <span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

<span class="c_FuncOutline def_Outlined def_Special">gcobject<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>gcobject</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="c_StructureSymbol def_SymbolStrong def_Symbol">:</span> marked<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol">!</span>gc_trigger<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> 
<span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    gc_pool<span class="c_Symbol def_Symbol">.</span>push_back<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_KeywordANSI def_Keyword">this</span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>

<span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> 
<span class="c_FuncOutline def_Outlined def_Special">gcobject<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>mark</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> 
<span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    <span class="c_KeywordANSI def_Keyword">if</span> <span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>marked <span class="c_Symbol def_Symbol">!</span><span class="c_Symbol def_Symbol">=</span> gc_trigger<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
        marked <span class="c_Symbol def_Symbol">=</span> gc_trigger<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
        touch<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    <span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>

<span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> 
<span class="c_FuncOutline def_Outlined def_Special">gcobject<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>grab</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    gc_root<span class="c_Symbol def_Symbol">-</span><span class="c_Symbol def_Symbol">&gt;</span>hold<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_KeywordANSI def_Keyword">this</span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>

<span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> 
<span class="c_FuncOutline def_Outlined def_Special">gcobject<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>release</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    gc_root<span class="c_Symbol def_Symbol">-</span><span class="c_Symbol def_Symbol">&gt;</span>unhold<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_KeywordANSI def_Keyword">this</span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>

<span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> 
<span class="c_FuncOutline def_Outlined def_Special">i_gcobject<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>collect</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> 
<span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    gc_root<span class="c_Symbol def_Symbol">-</span><span class="c_Symbol def_Symbol">&gt;</span>mark<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

    gc_pool<span class="c_Symbol def_Symbol">.</span>erase<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>remove_if<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>gc_pool<span class="c_Symbol def_Symbol">.</span>begin<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_Symbol def_Symbol">,</span> gc_pool<span class="c_Symbol def_Symbol">.</span>end<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="c_Symbol def_Symbol">,</span> gcobject<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>f_unmarked<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_Symbol def_Symbol">,</span> gc_pool<span class="c_Symbol def_Symbol">.</span>end<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

    gc_trigger <span class="c_Symbol def_Symbol">=</span> <span class="c_Symbol def_Symbol">!</span>gc_trigger<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span></pre>

<p>gcobject 为具体的 gc 实现，实现了 mark 、grab、release 和 collect 方法。</p>

<ol>
<li><p>mark 采用的直接向一 bool 变量设置标记。这个标记利用了 trigger 这个乒乓开关，每次  collect 都会切换状态。</p></li>
<li><p>grab 和 release 可以把对象挂接到 root 上，或从上取掉。</p></li>
<li><p>collect 会主动从 root 开始 mark ，并释放那些没有 mark 的对象。</p></li>
</ol>

<hr />

<pre class="mtc_block"><span class="c_Comment def_Comment def_Syntax"><span class="def_PairStart def_Special">/*</span>
 *  Copyright (c) 2010 ,
 *      Cloud Wu . All rights reserved.
 *
 *      <span class="def_URL def_URI">http://www.codingnow.com</span>
 *
 *  Use, modification and distribution are subject to the &quot;New BSD License&quot;
 *  as listed at &lt;url: <span class="def_URL def_URI">http://www.opensource.org/licenses/bsd-license.php</span> &gt;.
 <span class="def_PairEnd def_Special">*/</span></span>

<span class="c_Preproc def_Directive">#<span class="c_PreprocInclude def_Path def_URI">include <span class="c_IncludeOutline def_Outlined def_Special"><span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairStart def_Special">&quot;</span></span>i_gcholder.h<span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairEnd def_Special">&quot;</span></span></span></span></span>
<span class="c_Preproc def_Directive">#<span class="c_PreprocInclude def_Path def_URI">include <span class="c_IncludeOutline def_Outlined def_Special"><span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairStart def_Special">&quot;</span></span>gcobject.h<span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairEnd def_Special">&quot;</span></span></span></span></span>
<span class="c_Preproc def_Directive">#<span class="c_PreprocInclude def_Path def_URI">include <span class="c_IncludeOutline def_Outlined def_Special"><span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairStart def_Special">&lt;</span></span>vector<span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairEnd def_Special">&gt;</span></span></span></span></span>
<span class="c_Preproc def_Directive">#<span class="c_PreprocInclude def_Path def_URI">include <span class="c_IncludeOutline def_Outlined def_Special"><span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairStart def_Special">&lt;</span></span>algorithm<span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairEnd def_Special">&gt;</span></span></span></span></span>
<span class="c_Preproc def_Directive">#<span class="c_PreprocInclude def_Path def_URI">include <span class="c_IncludeOutline def_Outlined def_Special"><span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairStart def_Special">&lt;</span></span>cassert<span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairEnd def_Special">&gt;</span></span></span></span></span>

class gcholder <span class="c_StructureSymbol def_SymbolStrong def_Symbol">:</span> public virtual i_gcholder<span class="c_Symbol def_Symbol">,</span> virtual gcobject <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    std<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>vector<span class="c_Symbol def_Symbol">&lt;</span>i_gcobject <span class="c_Symbol def_Symbol">*</span><span class="c_Symbol def_Symbol">&gt;</span> hold_set<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    std<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>vector<span class="c_Symbol def_Symbol">&lt;</span>i_gcobject <span class="c_Symbol def_Symbol">*</span><span class="c_Symbol def_Symbol">&gt;</span> unhold_set<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    bool set_changed<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    bool hold_set_sorted<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    bool unhold_set_sorted<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> combine_set<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> touch<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> <span class="c_FuncOutline def_Outlined def_Special">hold</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>i_gcobject <span class="c_Symbol def_Symbol">*</span>obj<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
        hold_set<span class="c_Symbol def_Symbol">.</span>push_back<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>obj<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
        hold_set_sorted <span class="c_Symbol def_Symbol">=</span> false<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
        set_changed <span class="c_Symbol def_Symbol">=</span> true<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    <span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>
    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> <span class="c_FuncOutline def_Outlined def_Special">unhold</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>i_gcobject <span class="c_Symbol def_Symbol">*</span>obj<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
        unhold_set<span class="c_Symbol def_Symbol">.</span>push_back<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>obj<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
        unhold_set_sorted <span class="c_Symbol def_Symbol">=</span> false<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
        set_changed <span class="c_Symbol def_Symbol">=</span> true<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    <span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>
    <span class="c_KeywordANSI def_Keyword">struct</span> <span class="c_StructOutline def_Outlined def_Special">f_mark </span><span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
        <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> <span class="c_FuncOutline def_Outlined def_Special">operator</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>i_gcobject <span class="c_Symbol def_Symbol">*</span>obj<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
            obj<span class="c_Symbol def_Symbol">-</span><span class="c_Symbol def_Symbol">&gt;</span>mark<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
        <span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>
    <span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="c_Label def_Label">public:</span>
    <span class="c_FuncOutline def_Outlined def_Special">gcholder</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="c_StructureSymbol def_SymbolStrong def_Symbol">:</span> 
        <span class="c_FuncOutline def_Outlined def_Special">set_changed</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>false<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_Symbol def_Symbol">,</span> 
        <span class="c_FuncOutline def_Outlined def_Special">hold_set_sorted</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>true<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="c_Symbol def_Symbol">,</span> 
        <span class="c_FuncOutline def_Outlined def_Special">unhold_set_sorted</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>true<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span><span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

<span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> 
<span class="c_FuncOutline def_Outlined def_Special">gcholder<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>combine_set</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    <span class="c_KeywordANSI def_Keyword">if</span> <span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol">!</span>hold_set_sorted<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
        std<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>sort<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>hold_set<span class="c_Symbol def_Symbol">.</span>begin<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_Symbol def_Symbol">,</span>hold_set<span class="c_Symbol def_Symbol">.</span>end<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
        hold_set_sorted <span class="c_Symbol def_Symbol">=</span> true<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    <span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>
    <span class="c_KeywordANSI def_Keyword">if</span> <span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol">!</span>unhold_set_sorted<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
        std<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>sort<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>unhold_set<span class="c_Symbol def_Symbol">.</span>begin<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_Symbol def_Symbol">,</span>unhold_set<span class="c_Symbol def_Symbol">.</span>end<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
        unhold_set_sorted <span class="c_Symbol def_Symbol">=</span> true<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    <span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>
    <span class="c_KeywordANSI def_Keyword">if</span> <span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol">!</span>unhold_set<span class="c_Symbol def_Symbol">.</span>empty<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
        std<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>vector<span class="c_Symbol def_Symbol">&lt;</span>i_gcobject <span class="c_Symbol def_Symbol">*</span><span class="c_Symbol def_Symbol">&gt;</span><span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>iterator iter1 <span class="c_Symbol def_Symbol">=</span> hold_set<span class="c_Symbol def_Symbol">.</span>begin<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
        std<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>vector<span class="c_Symbol def_Symbol">&lt;</span>i_gcobject <span class="c_Symbol def_Symbol">*</span><span class="c_Symbol def_Symbol">&gt;</span><span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>iterator iter2 <span class="c_Symbol def_Symbol">=</span> unhold_set<span class="c_Symbol def_Symbol">.</span>begin<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
        <span class="c_KeywordANSI def_Keyword">while</span> <span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>iter1 <span class="c_Symbol def_Symbol">!</span><span class="c_Symbol def_Symbol">=</span> hold_set<span class="c_Symbol def_Symbol">.</span>end<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="c_Symbol def_Symbol">&amp;</span><span class="c_Symbol def_Symbol">&amp;</span> iter2 <span class="c_Symbol def_Symbol">!</span><span class="c_Symbol def_Symbol">=</span> unhold_set<span class="c_Symbol def_Symbol">.</span>end<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
            <span class="c_KeywordANSI def_Keyword">if</span> <span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol">*</span>iter1 <span class="c_Symbol def_Symbol">=</span><span class="c_Symbol def_Symbol">=</span> <span class="c_Symbol def_Symbol">*</span>iter2<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
                <span class="c_Symbol def_Symbol">*</span>iter1 <span class="c_Symbol def_Symbol">=</span> <span class="c_KeywordConstant def_Constant def_Keyword">NULL</span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
                <span class="c_Symbol def_Symbol">+</span><span class="c_Symbol def_Symbol">+</span>iter1<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
                <span class="c_Symbol def_Symbol">+</span><span class="c_Symbol def_Symbol">+</span>iter2<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
            <span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>
            <span class="c_KeywordANSI def_Keyword">else</span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
                assert<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol">*</span>iter1 <span class="c_Symbol def_Symbol">&lt;</span> <span class="c_Symbol def_Symbol">*</span>iter2<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
                <span class="c_Symbol def_Symbol">+</span><span class="c_Symbol def_Symbol">+</span>iter1<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
            <span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>
        <span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>
        i_gcobject <span class="c_Symbol def_Symbol">*</span> null <span class="c_Symbol def_Symbol">=</span> <span class="c_KeywordConstant def_Constant def_Keyword">NULL</span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
        hold_set<span class="c_Symbol def_Symbol">.</span>erase<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>std<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>remove<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>hold_set<span class="c_Symbol def_Symbol">.</span>begin<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_Symbol def_Symbol">,</span>hold_set<span class="c_Symbol def_Symbol">.</span>end<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_Symbol def_Symbol">,</span>null<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="c_Symbol def_Symbol">,</span> hold_set<span class="c_Symbol def_Symbol">.</span>end<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
        unhold_set<span class="c_Symbol def_Symbol">.</span>clear<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    <span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>

<span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> 
<span class="c_FuncOutline def_Outlined def_Special">gcholder<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>touch</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    <span class="c_KeywordANSI def_Keyword">if</span> <span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>set_changed<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
        combine_set<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
        set_changed <span class="c_Symbol def_Symbol">=</span> false<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    <span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>

    std<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>for_each<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>hold_set<span class="c_Symbol def_Symbol">.</span>begin<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_Symbol def_Symbol">,</span> hold_set<span class="c_Symbol def_Symbol">.</span>end<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_Symbol def_Symbol">,</span> f_mark<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>

i_gcholder <span class="c_Symbol def_Symbol">*</span> 
<span class="c_FuncOutline def_Outlined def_Special">i_gcholder<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>create</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    <span class="c_KeywordANSI def_Keyword">return</span> new gcholder<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span></pre>

<p>gcholder 理论上可以有多个实例，并相互挂接。（否则不需要继承至 <code>i_gcobject</code> ）这个设计可以用来模拟多级的堆栈。但实际上并不需要这么复杂。因为在大部分应用里，如果你的程序有一个周期性的主循环，就可以不在 gc 系统里模拟出一个多级的堆栈。我们只用在循环之外做 collect 即可。再堆栈调用的较深层次触发 collect 反而效果不佳，会导致许多临时 gc 对象无法回收。</p>

<hr />

<p>最后来看一个玩具代码，用 stl 里的 mutliset 实现了一个简单的树接口。可能没有什么使用价值，但它演示了一个较复杂的对象相互引用的关系。并可以展示 gc 如何正确工作。</p>

<pre class="mtc_block"><span class="c_Comment def_Comment def_Syntax"><span class="def_PairStart def_Special">/*</span>
 *  filename:  test.cpp
 *  Copyright (c) 2010 ,
 *      Cloud Wu . All rights reserved.
 *
 *      <span class="def_URL def_URI">http://www.codingnow.com</span>
 *
 *  Use, modification and distribution are subject to the &quot;New BSD License&quot;
 *  as listed at &lt;url: <span class="def_URL def_URI">http://www.opensource.org/licenses/bsd-license.php</span> &gt;.
 <span class="def_PairEnd def_Special">*/</span></span>

<span class="c_Preproc def_Directive">#<span class="c_PreprocInclude def_Path def_URI">include <span class="c_IncludeOutline def_Outlined def_Special"><span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairStart def_Special">&quot;</span></span>gcobject.h<span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairEnd def_Special">&quot;</span></span></span></span></span>

<span class="c_Preproc def_Directive">#<span class="c_PreprocInclude def_Path def_URI">include <span class="c_IncludeOutline def_Outlined def_Special"><span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairStart def_Special">&lt;</span></span>cstdio<span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairEnd def_Special">&gt;</span></span></span></span></span>
<span class="c_Preproc def_Directive">#<span class="c_PreprocInclude def_Path def_URI">include <span class="c_IncludeOutline def_Outlined def_Special"><span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairStart def_Special">&lt;</span></span>set<span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairEnd def_Special">&gt;</span></span></span></span></span>
<span class="c_Preproc def_Directive">#<span class="c_PreprocInclude def_Path def_URI">include <span class="c_IncludeOutline def_Outlined def_Special"><span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairStart def_Special">&lt;</span></span>algorithm<span class="c_PreprocIncludeEdge def_StringEdge def_String"><span class="def_PairEnd def_Special">&gt;</span></span></span></span></span>

interface i_tree <span class="c_StructureSymbol def_SymbolStrong def_Symbol">:</span> virtual i_gcobject <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> link<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>i_tree <span class="c_Symbol def_Symbol">*</span>p<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="c_Symbol def_Symbol">=</span> <span class="def_NumberDec def_Number">0</span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

    <span class="c_KeywordANSI def_Keyword">static</span> i_tree <span class="c_Symbol def_Symbol">*</span> create<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

class tree <span class="c_StructureSymbol def_SymbolStrong def_Symbol">:</span> public virtual i_tree <span class="c_Symbol def_Symbol">,</span> virtual gcobject <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    tree <span class="c_Symbol def_Symbol">*</span>parent<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    std<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>multiset<span class="c_Symbol def_Symbol">&lt;</span>tree <span class="c_Symbol def_Symbol">*</span><span class="c_Symbol def_Symbol">&gt;</span> children<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

    <span class="c_KeywordANSI def_Keyword">struct</span> <span class="c_StructOutline def_Outlined def_Special">f_mark </span><span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
        <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> <span class="c_FuncOutline def_Outlined def_Special">operator</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>tree <span class="c_Symbol def_Symbol">*</span>node<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
            node<span class="c_Symbol def_Symbol">-</span><span class="c_Symbol def_Symbol">&gt;</span>mark<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
        <span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>
    <span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> <span class="c_FuncOutline def_Outlined def_Special">touch</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
        <span class="c_KeywordANSI def_Keyword">if</span> <span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>parent<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span>
            parent<span class="c_Symbol def_Symbol">-</span><span class="c_Symbol def_Symbol">&gt;</span>mark<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

        std<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>for_each<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>children<span class="c_Symbol def_Symbol">.</span>begin<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_Symbol def_Symbol">,</span> children<span class="c_Symbol def_Symbol">.</span>end<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_Symbol def_Symbol">,</span> f_mark<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    <span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>

    <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> unlink<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

    virtual <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> link<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>i_tree <span class="c_Symbol def_Symbol">*</span>parent<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="c_Label def_Label">public:</span>
    <span class="c_FuncOutline def_Outlined def_Special">tree</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="c_StructureSymbol def_SymbolStrong def_Symbol">:</span> parent<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_KeywordConstant def_Constant def_Keyword">NULL</span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
        printf<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_String def_String">&quot;create node <span class="c_StringEscape def_StringContent def_String">%p</span><span class="c_StringEscape def_StringContent def_String">\n</span>&quot;</span><span class="c_Symbol def_Symbol">,</span><span class="c_KeywordANSI def_Keyword">this</span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    <span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>
    <span class="c_FuncOutline def_Outlined def_Special"><span class="c_Symbol def_Symbol">~</span>tree</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
        printf<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_String def_String">&quot;release node <span class="c_StringEscape def_StringContent def_String">%p</span><span class="c_StringEscape def_StringContent def_String">\n</span>&quot;</span><span class="c_Symbol def_Symbol">,</span><span class="c_KeywordANSI def_Keyword">this</span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    <span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

<span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span>
<span class="c_FuncOutline def_Outlined def_Special">tree<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>unlink</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    <span class="c_KeywordANSI def_Keyword">if</span> <span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>parent<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
        parent<span class="c_Symbol def_Symbol">-</span><span class="c_Symbol def_Symbol">&gt;</span>children<span class="c_Symbol def_Symbol">.</span>erase<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_KeywordANSI def_Keyword">this</span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

        parent <span class="c_Symbol def_Symbol">=</span> <span class="c_KeywordConstant def_Constant def_Keyword">NULL</span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    <span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>

<span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> 
<span class="c_FuncOutline def_Outlined def_Special">tree<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>link</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>i_tree <span class="c_Symbol def_Symbol">*</span>p<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    unlink<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    <span class="c_KeywordANSI def_Keyword">if</span> <span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>p<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
        tree <span class="c_Symbol def_Symbol">*</span> cp <span class="c_Symbol def_Symbol">=</span> dynamic_cast<span class="c_Symbol def_Symbol">&lt;</span>tree <span class="c_Symbol def_Symbol">*</span><span class="c_Symbol def_Symbol">&gt;</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>p<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
        cp<span class="c_Symbol def_Symbol">-</span><span class="c_Symbol def_Symbol">&gt;</span>children<span class="c_Symbol def_Symbol">.</span>insert<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_KeywordANSI def_Keyword">this</span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
        parent <span class="c_Symbol def_Symbol">=</span> cp<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    <span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>

i_tree <span class="c_Symbol def_Symbol">*</span>
<span class="c_FuncOutline def_Outlined def_Special">i_tree<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>create</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    <span class="c_KeywordANSI def_Keyword">return</span> new tree<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>

<span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">int</span> 
<span class="c_FuncOutline def_Outlined def_Special"><span class="c_KeywordLibFunctions def_FunctionKeyword def_Keyword">main</span></span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
    i_tree <span class="c_Symbol def_Symbol">*</span>root <span class="c_Symbol def_Symbol">=</span> i_tree<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>create<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

    root<span class="c_Symbol def_Symbol">-</span><span class="c_Symbol def_Symbol">&gt;</span>grab<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

    i_tree <span class="c_Symbol def_Symbol">*</span>node<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

    node <span class="c_Symbol def_Symbol">=</span> i_tree<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>create<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    node<span class="c_Symbol def_Symbol">-</span><span class="c_Symbol def_Symbol">&gt;</span>link<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>root<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

    node <span class="c_Symbol def_Symbol">=</span> i_tree<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>create<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    node<span class="c_Symbol def_Symbol">-</span><span class="c_Symbol def_Symbol">&gt;</span>link<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span>root<span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

    i_gcobject<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>collect<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

    printf<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_String def_String">&quot;collected<span class="c_StringEscape def_StringContent def_String">\n</span>&quot;</span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
    node<span class="c_Symbol def_Symbol">-</span><span class="c_Symbol def_Symbol">&gt;</span>link<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_KeywordConstant def_Constant def_Keyword">NULL</span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

    i_gcobject<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>collect<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

    printf<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_String def_String">&quot;finalize<span class="c_StringEscape def_StringContent def_String">\n</span>&quot;</span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

    root<span class="c_Symbol def_Symbol">-</span><span class="c_Symbol def_Symbol">&gt;</span>release<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

    i_gcobject<span class="c_PrefixSymbol def_SymbolStrong def_Symbol">::</span>collect<span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

    <span class="c_KeywordANSI def_Keyword">return</span> <span class="def_NumberDec def_Number">0</span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span></pre>

<hr />

<p>我们在实现一个基于 gc 的对象时，可以先定义出需要的接口，让接口从 <code>i_gcobject</code> 继承。例如上例中的 <code>i_tree</code> 。</p>

<p>然后在实现这个接口时，可以虚继承 gcobject 。例如上例中的 <code>tree</code> 。</p>

<p>如果有需要，就重载 touch 方法，在 touch 方法中 mark 相关的 gcobject 。对于 tree 这个例子，就是调用父亲和孩子节点的 mark 。</p>

<p>对象依然可以写析构函数，相当于对象的 finalize 。在析构函数中，不要再释放和它相关的 gcobject ，那些留给 gc 系统去完成。（例如在 tree 里，就不要在 ~tree 中 delete children 容器中的变量，也不需要把自己从父亲节点上摘掉）</p>

<hr />

<p>如果仅仅只是使用那些接口，则不需要再包含 gcobject.h ，因为 gcobject 的细节只供实现 <code>i_gcobject</code> 时使用。</p>
]]>
    </content>
</entry>
<entry>
    <title>搬家</title>
    <link rel="alternate" type="text/html" href="http://blog.codingnow.com/2010/02/move.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://linode.codingnow.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=545" title="搬家" />
    <id>tag:blog.codingnow.com,2010://1.545</id>
    
    <published>2010-02-19T17:59:34Z</published>
    <updated>2010-02-19T18:29:43Z</updated>
    
    <summary>这个 blog 最初架设在我工作中管理的一台服务器上。感谢公司允许我这么干。（据说很多公司是不允许的） 前段时间，我管理的另一台服务器硬盘出了些硬件故障。据了解，这批机器已经超长服役，早该退休了。反正迟早要挪数据的，我就随便自己租了个 VPS ，把 blog 搬了过去。 跟其它独立 blog 比，我已经很幸运了。因为机器在公司自己的机房里。机房管理人员都是同事，关系也不错。甚至曾经有段时间，他们中有几人还直接挂在我的部门名下，名义上是我的下属。 早几年刚刚要备案时，是同事转告我一定要去办理那些手续，因为有人查到我的主页挂的 ip 来至于公司的机房。我也很快办理了手续。后来几年，除了接过一个电话，核对我的备案信息，一直相安无事。...</summary>
    <author>
        <name>云风</name>
        <uri>http://www.codingnow.com</uri>
    </author>
            <category term="杂记" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.codingnow.com/">
        <![CDATA[<p>这个 blog 最初架设在我工作中管理的一台服务器上。感谢公司允许我这么干。（据说很多公司是不允许的）</p>

<p>前段时间，我管理的另一台服务器硬盘出了些硬件故障。据了解，这批机器已经超长服役，早该退休了。反正迟早要挪数据的，我就随便自己租了个 <a href="http://www.linode.com/?r=538bab39bc1265a2ce54115d1f86e2bc81e4d133">VPS</a> ，把 blog 搬了过去。</p>

<p>跟其它独立 blog 比，我已经很幸运了。因为机器在公司自己的机房里。机房管理人员都是同事，关系也不错。甚至曾经有段时间，他们中有几人还直接挂在我的部门名下，名义上是我的下属。</p>

<p>早几年刚刚要备案时，是同事转告我一定要去办理那些手续，因为有人查到我的主页挂的 ip 来至于公司的机房。我也很快办理了手续。后来几年，除了接过一个电话，核对我的备案信息，一直相安无事。</p>
]]>
        <![CDATA[<p>网上最近风传查得严了，朋友也劝我在国内自己租个 VPS ，我想想也不错。</p>

<p>大部分人都向我推荐 linode 。我自己测试了一下速度，的确不坏。我下载可以达到 200KB/s ，ping 值也在 300ms 以下。</p>

<p>这个带宽够我翻墙看 youtube 了，非常不错，我已经很满意。</p>

<p>我选的是 linode 在 NJ 的 IDC 。听说 CA 的 IDC 要稍微更好一些。只是那天申请的时候没有空位。（第 2 天又有了）貌似现在换 IDC 也很方便。以后增加 IP 很容易，万一被墙了，应该可以换个 IP 的。</p>

<p>linode 的管理界面非常友好，我很喜欢。装系统也就是 3 秒钟的事情。各种设置都很贴心。一个月 20$ 的价格我觉得还是可以接受的。如果推荐朋友使用，可以拿到 20$ 的回扣。所以，如果还有朋友也有租 VPS 的念头，可以<a href="http://www.linode.com/?r=538bab39bc1265a2ce54115d1f86e2bc81e4d133">点这个链接</a>。或者填我的 referral  code : 538bab39bc1265a2ce54115d1f86e2bc81e4d133</p>

<p>这只是一个推荐 :) 如果有人填我的 referral code 我会很高兴。支付很方便，我用我的招行信用卡很顺利的就付了款。从申请到开通，装好系统，没超过五分钟。</p>

<hr />

<p>保险起见，我把我的域名也从万网转移到了国外。我选的是 <a href="http://www.name.com">name.com</a> ，支付同样方便快捷。</p>

<p>域名转移过程比网上朋友抱怨过的那些要稍微顺利一点。万网的同学还是比较积极的，服务我还算满意。在网上在线留言就解决了我所有问题。最后打过电话确认后，又用 email 沟通了两次，就搞定了。</p>

<p>不过中间快递过两份材料才把转移认证码发给我，这个流程让我有点不爽。转移搞定后，我登陆 name.com ，发现人家都是把 Auth Code 直接列出来的，不需要这么繁杂的手续去索取。</p>
]]>
    </content>
</entry>
<entry>
    <title>虚杯以待</title>
    <link rel="alternate" type="text/html" href="http://blog.codingnow.com/2010/02/eoo.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://linode.codingnow.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=544" title="虚杯以待" />
    <id>tag:blog.codingnow.com,2010://1.544</id>
    
    <published>2010-02-16T17:13:49Z</published>
    <updated>2010-02-16T17:38:04Z</updated>
    
    <summary>这次韩寒和刘谦各写了一篇 blog 而之后又隐掉的事情，我是在 greader 从和菜头那看来的。 我喜欢韩寒的直爽，如果有机会认识，我会想去交这样一个朋友。 这次看了刘谦写得这篇 blog ，我发现他也是一个很不错的人呐。 有人问起，“先把杯子里的水倒掉才行” 这个禅宗典故是从哪里来的。我也懒得自己敲了，转一段： 南隐是日本明治时代著名的禅师，他的一杯茶的故事常常为人所津津乐道并予以启发。有一天，一位大学教授特地来向南隐问禅，南隐以茶水招待，他将茶水注入这个访客的杯中，杯满之后他还继续注入，这位教授眼睁睁地看着茶水不停地溢出杯外，直到再也不能沉默下去了，终于说道：“已经满出来了，不要倒了。” &quot;你的心就像这只杯子一样，时面装满了你自己的看法和主张，你不先把自己的杯子倒空，叫我如何对你说禅？&quot;南隐意味深长地说。...</summary>
    <author>
        <name>云风</name>
        <uri>http://www.codingnow.com</uri>
    </author>
            <category term="随笔" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.codingnow.com/">
        <![CDATA[<p>这次韩寒和刘谦各写了一篇 blog 而之后又隐掉的事情，我是在 greader <a href="http://www.caobian.info/?p=7494">从和菜头那看来的</a>。</p>

<p>我喜欢韩寒的直爽，如果有机会认识，我会想去交这样一个朋友。</p>

<p>这次看了刘谦写得这篇 blog ，我发现他也是一个很不错的人呐。</p>

<p>有人问起，“先把杯子里的水倒掉才行” 这个禅宗典故是从哪里来的。我也懒得自己敲了，<a href="http://wenda.tianya.cn/wenda/thread?tid=65489688bc0c7942">转一段</a>：</p>

<p>南隐是日本明治时代著名的禅师，他的一杯茶的故事常常为人所津津乐道并予以启发。有一天，一位大学教授特地来向南隐问禅，南隐以茶水招待，他将茶水注入这个访客的杯中，杯满之后他还继续注入，这位教授眼睁睁地看着茶水不停地溢出杯外，直到再也不能沉默下去了，终于说道：“已经满出来了，不要倒了。” 
"你的心就像这只杯子一样，时面装满了你自己的看法和主张，你不先把自己的杯子倒空，叫我如何对你说禅？"南隐意味深长地说。</p>
]]>
        <![CDATA[<p>之前，我也写了一篇关于<a href="http://blog.codingnow.com/2010/02/magic.html">刘谦那个魔术的 blog</a> 。其实是没有任何立场的。</p>

<p>只是喜欢这个魔术，并且好奇，所以猜了一下怎么做到的。这种猜测，应该也是观赏魔术表演的乐趣之一。</p>

<p>如此而已。</p>
]]>
    </content>
</entry>
<entry>
    <title>缘分天注定</title>
    <link rel="alternate" type="text/html" href="http://blog.codingnow.com/2010/02/serendipity.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://linode.codingnow.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=543" title="缘分天注定" />
    <id>tag:blog.codingnow.com,2010://1.543</id>
    
    <published>2010-02-15T14:20:40Z</published>
    <updated>2010-02-15T14:30:59Z</updated>
    
    <summary>昨晚睡不着，随便找了本老片子看。 Serendipity 情节很假，但是假得让人喜欢。 结尾的时候那段讣告，我震惊了。看来做字幕的大哥对这部片子相当有爱啊。 　　庄纳顿.卓加…… 　　有线体育台优秀监制 　　既失红颜，复破婚盟 　　肝肠寸断，遂于昨宵撒手尘寰 　　享年三十有五 　　庄君文质彬彬，公而忘私 　　平素言行，绝无痴态 　　孰料，阳寿将尽之际…… 　　流露鲜为人知的浪漫 　　刹那惊艳，化作萦回梦魂 　　遍觅芳踪，历尽一波三折 　　本性情怀，浮现无遗 　　呜呼，踏破铁鞋…… 　　方觉一番心事悉付东流 　　语云：匹夫可以夺其爱…… 　　不可夺其志 　　庄君依然坚信…… 　　人生际遇绝非偶然 　　冥冥中，上苍早已…… 　　安排周详，丝毫不爽 　　其友文坛巨擘…… 　　时报主笔甸恩谓…… 　　庄君晚年脱胎换骨 　　有所顿悟 　　一言以蔽之…… 　　欲臻天人合一…… 　　须坚信一字 　　此字古已有之 　　于今亦然，唯“缘”而已 被感动了。...</summary>
    <author>
        <name>云风</name>
        <uri>http://www.codingnow.com</uri>
    </author>
            <category term="随笔" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.codingnow.com/">
        <![CDATA[<p>昨晚睡不着，随便找了本老片子看。
<a href="http://www.douban.com/subject/1305541/">Serendipity</a></p>

<p>情节很假，但是假得让人喜欢。</p>

<p>结尾的时候那段讣告，我震惊了。看来做字幕的大哥对这部片子相当有爱啊。</p>

<pre>
　　庄纳顿.卓加…… 
　　有线体育台优秀监制 
　　既失红颜，复破婚盟 
　　肝肠寸断，遂于昨宵撒手尘寰 
　　享年三十有五 
　　庄君文质彬彬，公而忘私 
　　平素言行，绝无痴态 
　　孰料，阳寿将尽之际…… 
　　流露鲜为人知的浪漫 
　　刹那惊艳，化作萦回梦魂 
　　遍觅芳踪，历尽一波三折 
　　本性情怀，浮现无遗 
　　呜呼，踏破铁鞋…… 
　　方觉一番心事悉付东流 
　　语云：匹夫可以夺其爱…… 
　　不可夺其志 
　　庄君依然坚信…… 
　　人生际遇绝非偶然 
　　冥冥中，上苍早已…… 
　　安排周详，丝毫不爽 
　　其友文坛巨擘…… 
　　时报主笔甸恩谓…… 
　　庄君晚年脱胎换骨 
　　有所顿悟 
　　一言以蔽之…… 
　　欲臻天人合一…… 
　　须坚信一字 
　　此字古已有之 
　　于今亦然，唯“缘”而已
</pre>

<p>被感动了。</p>
]]>
        <![CDATA[<p>英文原文写得也很好：</p>

<p>Johnathan Trager, prominent television producer for ESPN, died last night from complications of losing his soul mate and his fiancee. </p>

<p>He was 35 years old. Soft-spoken and obsessive, Trager never looked the part of a hopeless romantic.</p>

<p>But, in the final days of his life, he revealed an unknown side of his psyche. This hidden quasi-Jungian persona surfaced during the Agatha Christie-like pursuit of his long-reputed soul mate, a woman whom he only spent a few precious hours with. </p>

<p>Sadly, the protracted search ended late Saturday night in complete and utter failure. Yet even in certain defeat, the courageous Trager secretly clung to the belief that life is not merely a series of meaningless accidents or coincidences. </p>

<p>Uh-uh. But rather, its a tapestry of events that culminate in an exquisite, sublime plan. Asked about the loss of his dear friend, Dean Kansky, the Pulitzer Prize-winning author and executive editor of the New York Times, described Jonathan as a changed man in the last days of his life. </p>

<p>“Things were clearer for him,” Kansky noted. Ultimately Johnathan concluded that if we are to live life in harmony with the universe, we must all possess a powerful faith in what the ancients used to call “fatum”, what we currently refer to as destiny. 
　　 </p>
]]>
    </content>
</entry>
<entry>
    <title>关于那个手穿玻璃</title>
    <link rel="alternate" type="text/html" href="http://blog.codingnow.com/2010/02/magic.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://linode.codingnow.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=542" title="关于那个手穿玻璃" />
    <id>tag:blog.codingnow.com,2010://1.542</id>
    
    <published>2010-02-13T17:45:58Z</published>
    <updated>2010-02-13T18:03:27Z</updated>
    
    <summary>今天很俗的看了春晚。抱着本连着 wifi 上着推看的。 刘谦的魔术不错，最后擦玻璃的时候预感要表演手穿玻璃了。但是看到了还是觉得很神奇。 仔细想了一下，玻璃上应该有洞的。肯定这一点，就对一开始为啥弄个圆桌子坐一圈恍然大悟了。 玻璃应该是双层的，可以梭动。这样才能一开始把洞藏起来。这样一大圈，就方便藏那个洞了。只要玻璃干净，转得时候就很难发现了。借助表演者的胳膊掩饰，就可以把洞从旁边梭过来。...</summary>
    <author>
        <name>云风</name>
        <uri>http://www.codingnow.com</uri>
    </author>
            <category term="杂记" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.codingnow.com/">
        <![CDATA[<p>今天很俗的看了春晚。抱着本连着 wifi 上着推看的。</p>

<p>刘谦的魔术不错，最后擦玻璃的时候预感要表演手穿玻璃了。但是看到了还是觉得很神奇。</p>

<p>仔细想了一下，玻璃上应该有洞的。肯定这一点，就对一开始为啥弄个圆桌子坐一圈恍然大悟了。</p>

<p>玻璃应该是双层的，可以梭动。这样才能一开始把洞藏起来。这样一大圈，就方便藏那个洞了。只要玻璃干净，转得时候就很难发现了。借助表演者的胳膊掩饰，就可以把洞从旁边梭过来。</p>
]]>
        <![CDATA[<p>一直都听人说，春晚赵本山的小品可以看看。这些年都没看，今年难得坐在电视机前看了。唉，都什么品位啊。</p>

<hr />

<p>最后，转个同事推的段子：</p>

<p>除夕已过，圣战日已到，诸君，不管你是魔法使， 高阶魔道士，步兵还是退役的骑兵， 为了团部, 勇敢的战斗吧，去死去死团万岁...</p>

<p>大家，节日快乐 :D</p>

<p>Live long and prosper ! \V/,</p>
]]>
    </content>
</entry>
<entry>
    <title>关于招聘</title>
    <link rel="alternate" type="text/html" href="http://blog.codingnow.com/2010/02/oeouo.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://linode.codingnow.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=541" title="关于招聘" />
    <id>tag:blog.codingnow.com,2010://1.541</id>
    
    <published>2010-02-07T17:31:00Z</published>
    <updated>2010-02-07T17:40:42Z</updated>
    
    <summary>承蒙大家厚爱，到现在，我已经通过 email 收到了 21 份简历。不过两天时间就能收到这么多，而且看得出大家都是很热情，大多数不仅仅附了简历，还专门写了好多文字。还真是受宠若惊啊。 很不好意思，我只回复了两份，别的都还没有动键盘回复。一是周末在打游戏（平时实在没空），二是需要和同事讨论一下才有结论。我们工作室 11 号放假，10 号晚上办公室就没人了。也就这两天会比较所有的简历吧。 嗯，已收到的简历我都看完了（真是花了不少时间呢），明天会发给工作室其他写程序的同事看。我想若安排面试，就是年后的事情了。我们大约在 21 号正式上班。 请原谅我这个周末的懈怠。接下来我会尽力回复 email 的。...</summary>
    <author>
        <name>云风</name>
        <uri>http://www.codingnow.com</uri>
    </author>
            <category term="杂记" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.codingnow.com/">
        <![CDATA[<p>承蒙大家厚爱，到现在，我已经通过 email 收到了 21 份简历。不过两天时间就能收到这么多，而且看得出大家都是很热情，大多数不仅仅附了简历，还专门写了好多文字。还真是受宠若惊啊。</p>

<p>很不好意思，我只回复了两份，别的都还没有动键盘回复。一是周末在打游戏（平时实在没空），二是需要和同事讨论一下才有结论。我们工作室 11 号放假，10 号晚上办公室就没人了。也就这两天会比较所有的简历吧。</p>

<p>嗯，已收到的简历我都看完了（真是花了不少时间呢），明天会发给工作室其他写程序的同事看。我想若安排面试，就是年后的事情了。我们大约在 21 号正式上班。</p>

<p>请原谅我这个周末的懈怠。接下来我会尽力回复 email 的。</p>
]]>
        

    </content>
</entry>
<entry>
    <title>FF13 剧情完成</title>
    <link rel="alternate" type="text/html" href="http://blog.codingnow.com/2010/02/ff13.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://linode.codingnow.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=540" title="FF13 剧情完成" />
    <id>tag:blog.codingnow.com,2010://1.540</id>
    
    <published>2010-02-07T16:38:59Z</published>
    <updated>2010-02-07T17:08:06Z</updated>
    
    <summary>终于盼到周末，把 FF13 熬夜完成了。 游戏时间大约在 50 小时左右，没看任何攻略，没有炼级，没有改武器，基本一路冲到底的。就是几个 boss 稍微难一点，retry 了几次，大体上对于熟练 RPG 玩家没什么难度。 然后接着就是回头做 64 个冥碑任务（现在完成了 20 多个，其中只做了一个 A 级的比较难），开传送点等等。我估计把盘走完，还需要至少五十小时吧。 这次剧情依旧不错，我比较喜欢，但不是最好。（FF 10 和 FF 7 我更喜欢一点）我的日文水平是入门级里的入门，理所当然的，好多地方没看明白。只能连蒙带猜了。生日那天，居然传出官方消息说是五月要出中文版，这算是今年的生日礼物吧 :D 一定会买来再玩一次的。 角色里三个 mm 都不错，任挑一个我都喜欢。不过感觉这次有点恶趣味。虽然没明白做百合向的，我想有几个镜头也是故意做的满邪恶了 :D...</summary>
    <author>
        <name>云风</name>
        <uri>http://www.codingnow.com</uri>
    </author>
            <category term="游戏" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.codingnow.com/">
        <![CDATA[<p>终于盼到周末，把 FF13 熬夜完成了。</p>

<p>游戏时间大约在 50 小时左右，没看任何攻略，没有炼级，没有改武器，基本一路冲到底的。就是几个 boss 稍微难一点，retry 了几次，大体上对于熟练 RPG 玩家没什么难度。</p>

<p>然后接着就是回头做 64 个冥碑任务（现在完成了 20 多个，其中只做了一个 A 级的比较难），开传送点等等。我估计把盘走完，还需要至少五十小时吧。</p>

<p>这次剧情依旧不错，我比较喜欢，但不是最好。（FF 10 和 FF 7 我更喜欢一点）我的日文水平是入门级里的入门，理所当然的，好多地方没看明白。只能连蒙带猜了。生日那天，居然传出官方消息说是五月要出中文版，这算是今年的生日礼物吧 :D 一定会买来再玩一次的。</p>

<p>角色里三个 mm 都不错，任挑一个我都喜欢。不过感觉这次有点恶趣味。虽然没明白做百合向的，我想有几个镜头也是故意做的满邪恶了 :D</p>
]]>
        <![CDATA[<p>战斗系统的进化我很欣赏。敢于放弃传统，把战斗的爽快感做出来而不失简洁和策略。强化 Break 系统真是让人拍案。虽然从里面可以看到 FFX / XI / XII / X-2 / VII CC 等等的影子，但放在一起再加一点点就是个全新的东西。融合的很好。</p>

<p>人物基本的可升级数值设定只留下 HP 物理 魔法 三个值（加上 ATB 槽和职业两个等级），我觉得是要莫大的勇气的。不过想想也够了。即可以做得丰富，又不多余。</p>

<p>我想 ATB 进化到这个样子，我们已经不能单纯把 RPG 游戏分成即时和回合制了。也并非如许多策划念叨的：回合的间隔缩小就成了即时。FF13 每次做出操作选择的时间间隔并不短，但流畅度，紧张感，爽快感却并不见少。</p>

<p>其实 FF13 里吸收的元素都不是新鲜东西，只是很融洽的组合在一起罢了。</p>
]]>
    </content>
</entry>
<entry>
    <title>招聘程序员</title>
    <link rel="alternate" type="text/html" href="http://blog.codingnow.com/2010/02/recruit.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://linode.codingnow.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=539" title="招聘程序员" />
    <id>tag:blog.codingnow.com,2010://1.539</id>
    
    <published>2010-02-05T08:29:00Z</published>
    <updated>2010-02-05T08:55:49Z</updated>
    
    <summary>今天发个不太正式的招聘信息： 我们这里工作室，需要招聘两名程序员。在未来至少一年的工作是：专职制作维护 3d engine 中的模型编辑器和场景编辑器。（每个一人维护） 要求： 熟悉 C 语言，或 C++ 。至少有一门动态语言的经验，lua 最好，python 或其它也可以。 能够全心制作编辑器（至少一年），最好有相关经验（非必须）。 有 3d 方面编程经验优先，但不是必须。需要有学习 3d 编程的兴趣和动力。 有任意一款 GUI 框架编程经验者优先。（例如 QT ） 待遇方面，不会太高，但也不算低。所以特别牛的同学就免了，可能满足不了你的要求。就算愿意，我也心里不舒服。 完全抱着从头学习的想法的同学也需要考虑一下。我们还是需要有一点点经验的，不可能花半年时间慢慢培养到可以开始动手干活。（经验指：可以独立编写 GUI 程序） 有兴趣的同学可以给我发 email 附上简单的简历。...</summary>
    <author>
        <name>云风</name>
        <uri>http://www.codingnow.com</uri>
    </author>
            <category term="杂记" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.codingnow.com/">
        <![CDATA[<p>今天发个不太正式的招聘信息：</p>

<p>我们这里工作室，需要招聘两名程序员。在未来至少一年的工作是：专职制作维护 3d engine 中的模型编辑器和场景编辑器。（每个一人维护）</p>

<p>要求：</p>

<ol>
<li><p>熟悉 C 语言，或 C++ 。至少有一门动态语言的经验，lua 最好，python 或其它也可以。</p></li>
<li><p>能够全心制作编辑器（至少一年），最好有相关经验（非必须）。</p></li>
<li><p>有 3d 方面编程经验优先，但不是必须。需要有学习 3d 编程的兴趣和动力。</p></li>
<li><p>有任意一款 GUI 框架编程经验者优先。（例如 QT ）</p></li>
</ol>

<p>待遇方面，不会太高，但也不算低。所以特别牛的同学就免了，可能满足不了你的要求。就算愿意，我也心里不舒服。</p>

<p>完全抱着从头学习的想法的同学也需要考虑一下。我们还是需要有一点点经验的，不可能花半年时间慢慢培养到可以开始动手干活。（经验指：可以独立编写 GUI 程序）</p>

<p>有兴趣的同学可以给我发 email 附上简单的简历。</p>
]]>
        <![CDATA[<p>附：工作地点在杭州。一周五天工作，无强制加班。入职公司是网易（杭州）。</p>

<p>我们是小团队，工作室制。我是团队负责人，全权负责团队一切事务。工作室下属于网易游戏部门（网易互动娱乐）。</p>

<p>团队以研发为主，暂不涉及游戏运营等。</p>
]]>
    </content>
</entry>
<entry>
    <title>古怪的 C++ 问题</title>
    <link rel="alternate" type="text/html" href="http://blog.codingnow.com/2010/01/cpp_template.html" />
    <link rel="service.edit" type="application/atom+xml" href="http://linode.codingnow.com/cgi-bin/mt/mt-atom.cgi/weblog/blog_id=1/entry_id=522" title="古怪的 C++ 问题" />
    <id>tag:blog.codingnow.com,2010://1.522</id>
    
    <published>2010-01-28T15:59:58Z</published>
    <updated>2010-01-28T08:21:57Z</updated>
    
    <summary>我好多年没写 C++ 程序了，读 C++ 代码也是偶尔为之。 今天晚上就碰到这么一个诡异的问题，我觉得是我太久没摸 C++ 了，对那些奇怪的语法细则已经不那么熟悉了。有知道的同学给我解惑一下吧。 事情的起因是，我想安装一个 perl 模块唤作 Syntax::Highlight::Universal 。 本来用 CPAN 安装很方便的，直接 install 即可。 可是在我的机器上，make 死活通不过。我就仔细研究了一下编译出错信息。又读了一下源代码，自己感觉没错。纠结了半天，仔细模仿出错的地方写了一小段程序测试。...</summary>
    <author>
        <name>云风</name>
        <uri>http://www.codingnow.com</uri>
    </author>
            <category term="语言与设计" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.codingnow.com/">
        <![CDATA[<p>我好多年没写 C++ 程序了，读 C++ 代码也是偶尔为之。</p>

<p>今天晚上就碰到这么一个诡异的问题，我觉得是我太久没摸 C++ 了，对那些奇怪的语法细则已经不那么熟悉了。有知道的同学给我解惑一下吧。</p>

<p>事情的起因是，我想安装一个 perl 模块唤作 Syntax::Highlight::Universal 。</p>

<p>本来用 CPAN 安装很方便的，直接 install 即可。</p>

<p>可是在我的机器上，make 死活通不过。我就仔细研究了一下编译出错信息。又读了一下源代码，自己感觉没错。纠结了半天，仔细模仿出错的地方写了一小段程序测试。</p>
]]>
        <![CDATA[<pre class="mtc_block">template <span class="c_Symbol def_Symbol">&lt;</span>class T<span class="c_Symbol def_Symbol">&gt;</span>
class A <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
<span class="c_Label def_Label">protected:</span>
        <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">int</span> a<span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>

template <span class="c_Symbol def_Symbol">&lt;</span>class T<span class="c_Symbol def_Symbol">&gt;</span>
class B <span class="c_StructureSymbol def_SymbolStrong def_Symbol">:</span> public A<span class="c_Symbol def_Symbol">&lt;</span>T<span class="c_Symbol def_Symbol">&gt;</span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span>
<span class="c_Label def_Label">public:</span>
        <span class="c_KeywordANSI_typenames c_KeywordANSI def_Keyword">void</span> <span class="c_FuncOutline def_Outlined def_Special">foo</span><span class="c_Symbol def_Symbol"><span class="def_PairStart def_Special">(</span></span><span class="c_Symbol def_Symbol"><span class="def_PairEnd def_Special">)</span></span> <span class="def_SymbolStrong def_Symbol"><span class="def_PairStart def_Special">{</span></span> 
            a<span class="c_Symbol def_Symbol">=</span><span class="def_NumberDec def_Number">0</span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span>
        <span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span>
<span class="def_SymbolStrong def_Symbol"><span class="def_PairEnd def_Special">}</span></span><span class="c_StructureSymbol def_SymbolStrong def_Symbol">;</span></pre>

<p>各位同学觉得有问题么？我初看觉得没有。但是 gcc 一编译就出错。一开始是觉得 gcc 版本太高（4.x），可能语法检查更严格了。后来换了 gcc3 ，问题依旧。</p>

<p>出错信息如下：</p>

<p>a.cpp: In member function `void B<T>::foo()':</p>

<p>a.cpp:11: error: `a' was not declared in this scope</p>

<p>就是在 B 里找不到 A 定义的成员变量 a 。</p>

<p>如果 A 不是一个 template ，那么这个问题就没有。</p>

<p>我琢磨着这个问题跟编译器为 template 生成代码的行为有关，但是不确定。</p>

<p>注：这段代码在 VC6 里是可以正常编译的。</p>

<p>最后，我试了一下，把代码改成</p>

<pre><code>    void foo() { 
        this-&gt;a=0;
    }
</code></pre>

<p>那么是可以编译通过的了。可是，这是新标准规定的么？</p>

<p>btw, 其实我写 C++ 的最后一年，都养成了显式用 this 指针的习惯。这样比较少犯错误。</p>
]]>
    </content>
</entry>

</feed> 

