﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-创的技术博客-随笔分类-CGL</title><link>http://www.cppblog.com/converse/category/3609.html</link><description>C++对我而言就是有STL带class能处理多态,继承的C.</description><language>zh-cn</language><lastBuildDate>Wed, 21 May 2008 09:24:07 GMT</lastBuildDate><pubDate>Wed, 21 May 2008 09:24:07 GMT</pubDate><ttl>60</ttl><item><title>CGL开发手记之三--CGL中的"函数对象"</title><link>http://www.cppblog.com/converse/archive/2007/05/07/23566.html</link><dc:creator>创</dc:creator><author>创</author><pubDate>Mon, 07 May 2007 08:53:00 GMT</pubDate><guid>http://www.cppblog.com/converse/archive/2007/05/07/23566.html</guid><wfw:comment>http://www.cppblog.com/converse/comments/23566.html</wfw:comment><comments>http://www.cppblog.com/converse/archive/2007/05/07/23566.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/converse/comments/commentRss/23566.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/converse/services/trackbacks/23566.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 需要注意的是,本节题目中"函数对象"四字是加了双引号的,因为C语言中没有办法做到类C++中函数对象的做法,CGL中采用的替代手段是使用函数指针.<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 首先需要短暂回顾STL中的函数对象以及函数对象适配器等概念.<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; STL中的最基本的函数对象分为三类:<font style="BACKGROUND-COLOR: #ffffff">generator, unary function,binary function,其中的generator是无参数函数,unary function是单参数函数,binary function是双参数函数.注意,以上只是提到的三者的传入参数的数量,还没有涉及到它们所要返回的参数类型.一般的,三者都是以template参数作为自己返回参数的类型,但是当unary function和binary function返回参数是bool型的时候,分别称它们为:predicate和binary predicate,这是因为STL中很多范型参数的调用需要传入一个函数对象进行元素的比较.如sort,find_if等函数.<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 函数对象适配器分为两类:一类是绑定器(binder),另外一类是取反器(negator),绑定器用于绑定函数对象中的某个参数,取反器用于将函数对象的返回值进行翻转,一般的,可以使用取反器的函数对象都是那些返回值为bool型的函数对象.<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CGL中不能实现函数适配器,因为绑定器在绑定参数的时候是通过将所需要绑定的参数作为模版参数传递给函数对象类进行参数绑定的,如:<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">template&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">class&nbsp;Operation</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>class&nbsp;binder2nd<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;unary_function</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">typename</span><span style="COLOR: #000000">&nbsp;Operation::first_argument_type,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">typename</span><span style="COLOR: #000000">&nbsp;Operation::result_type</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>protected:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;Operation&nbsp;op;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">typename</span><span style="COLOR: #000000">&nbsp;Operation::second_argument_type&nbsp;value;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;binder2nd(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Operation</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;x,<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">typename</span><span style="COLOR: #000000">&nbsp;Operation::second_argument_type</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;y)&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;op(x),&nbsp;value(y)&nbsp;{}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">typename</span><span style="COLOR: #000000">&nbsp;Operation::result_type<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;operator()(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">typename</span><span style="COLOR: #000000">&nbsp;Operation::first_argument_type</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;x)&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;op(x,&nbsp;value);&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>};<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>template&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">class&nbsp;Operation,&nbsp;class&nbsp;T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>inline&nbsp;binder2nd</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">Operation</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;bind2nd(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Operation</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;op,&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;T</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;x)&nbsp;{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;typedef&nbsp;</span><span style="COLOR: #0000ff">typename</span><span style="COLOR: #000000">&nbsp;Operation::second_argument_type&nbsp;arg2_type;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;return&nbsp;binder2nd</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">Operation</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">(op,&nbsp;arg2_type(x));<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
以上是绑定器bind2nd函数的实现,你可以看到这个函数是返回一个binder2nd的函数对象类,而所需要绑定的参数作为binder2nd的value参数存储起来,在调用binder2nd的operator()时再使用value参数,由于C中没有办法做到重载operator()函数,所以不能实现binder.<br><br>同样的,C中也没有办法实现negator函数对象适配器,见代码:<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">template&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">class&nbsp;Predicate</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>class&nbsp;unary_negate<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;unary_function</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">typename</span><span style="COLOR: #000000">&nbsp;Predicate::argument_type,&nbsp;bool</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>protected:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;Predicate&nbsp;pred;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">explicit</span><span style="COLOR: #000000">&nbsp;unary_negate(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Predicate</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;x)&nbsp;:&nbsp;pred(x)&nbsp;{}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;bool&nbsp;operator()(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">typename</span><span style="COLOR: #000000">&nbsp;Predicate::argument_type</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;x)&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;!pred(x);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>};<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>template&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">class&nbsp;Predicate</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>inline&nbsp;unary_negate</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">Predicate</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;not1(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;Predicate</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;pred)&nbsp;{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;return&nbsp;unary_negate</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">Predicate</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">(pred);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
以上是negator函数not1函数的实现.可以看到这个函数返回一个unary_negate函数对象,而在这个函数对象重载的operator()中对pred函数的返回值进行取反以达到negator函数对象适配器的作用,同样的,用于C中不能做到重载operator(),所以没有办法实现negator函数对象适配器.<br><br>STL中还有一些预定义的函数对象如plus,equal_to等,见代码:<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">template&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">class&nbsp;T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>struct&nbsp;plus&nbsp;:&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;binary_function</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T,&nbsp;T,&nbsp;T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">&nbsp;{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;operator()(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;T</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;x,&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;T</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">&nbsp;y)&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;{&nbsp;return&nbsp;x&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;y;&nbsp;}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>};<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
plus的函数参数是通过模版参数T传入的,任何想要采用plus的类型都需要提供operator + 操作符.因为这个特点,C中也没有办法实现这些预定义的函数对象.<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 鉴于以上的原因,CGL中的"函数对象"被定义为几种函数指针:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">typedef&nbsp;bool_t&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">binary_predicate)(data_t&nbsp;tData1,&nbsp;data_t&nbsp;tData2);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>typedef&nbsp;void&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">binary_func)(data_t&nbsp;tData1,&nbsp;data_t&nbsp;tData2,&nbsp;data_t&nbsp;tResult);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>typedef&nbsp;void&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">binary_func2)(data_t&nbsp;tData1,&nbsp;data_t&nbsp;tData2);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>typedef&nbsp;bool_t&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">unary_predicate)(data_t&nbsp;tData);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>typedef&nbsp;void&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">unary_func)(data_t&nbsp;tData,&nbsp;data_t&nbsp;tResult);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>typedef&nbsp;void&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">unary_func2)(data_t&nbsp;tData);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>typedef&nbsp;void&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">generator_func)(data_t&nbsp;tResult);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>typedef&nbsp;void&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">generator_func2)();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
&nbsp;&nbsp;&nbsp;&nbsp; 这些函数指针的返回值只有两种,bool_t和void,当需要返回除了boot_t之外的返回值时,将保存返回值的指针tResult传入函数中保存返回值,所有CGL中使用的函数指针都只可能是以上的几种函数指针类型.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><br><br>
<img src ="http://www.cppblog.com/converse/aggbug/23566.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/converse/" target="_blank">创</a> 2007-05-07 16:53 <a href="http://www.cppblog.com/converse/archive/2007/05/07/23566.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CGL开发手记之二--CGL中的数据类型</title><link>http://www.cppblog.com/converse/archive/2007/05/02/23311.html</link><dc:creator>创</dc:creator><author>创</author><pubDate>Tue, 01 May 2007 16:59:00 GMT</pubDate><guid>http://www.cppblog.com/converse/archive/2007/05/02/23311.html</guid><wfw:comment>http://www.cppblog.com/converse/comments/23311.html</wfw:comment><comments>http://www.cppblog.com/converse/archive/2007/05/02/23311.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/converse/comments/commentRss/23311.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/converse/services/trackbacks/23311.html</trackback:ping><description><![CDATA[为了做到能操作所有类型的数据，我参看了几个类似的C语言的库，基本上就是两种做法：一是使用宏，二是使用void*指针。最后我选择了后者，原因很简单，我不是一个很推崇在代码中大量使用宏的人，一方面觉得这样作会让代码的可读性降低，另一方面我也确实不是写宏的高手。<br><br>在CGL中，有以下的几个typedef都把void*定义为某种类型:<br>typedef void*&nbsp;container_t;<br>typedef&nbsp;void*&nbsp;point_t;<br>typedef void*&nbsp;data_t;<br><br>分别作一个解释，container_t表示的是指向容器的指针，point_t表示的是通用指向某容器的指针，不论是指向数组成员的指针还是一个链表结点的指针都可以"泛化"的表示为"pos_t",而data_t表示的是存放数据的指针，之所以要对同样可以表示为是void*的指针分三个类型的typedef，目的是为了在代码中一目了然，看到类型的名字就能知道是作什么用的了。<br><br>container_t的含义很好理解，现在对后面两种类型作一下解释。<br><br>原本pos_t不叫pos_t的，而是被定义为iter_t，因为在STL中迭代器其实就是一个行为很像指针的东东，可以解引用，可以递增指向下一个元素，递减指向前一个元素，等等。但是需要注意的时候，由于C++中可以重载操作符，如*,++,--这样的操作符都可以被重载以至于一个iterator的行为看上去和一个普通的指针没有什么区别。但是在CGL中，是完全采用的C语言实现的，没有办法做到重载这些操作符，所以我专门提供了一个叫做iteraotr_t的结构体，里面有函数指针成员可以实现以上这些重载操作符所需要作的事情(后面会有专门的一节来讲述这个结构体以及CGL中迭代器的设计)，所以如果有一个类型为iter_t一个类型为iterator_t会不会让人混淆呢？至少我偶尔回头看我的代码的时候是会弄混的，因此我决定把iter_t更名为pos_t也就是位置的意思。<br><br>data_t用于保存存放数据的指针，这里有几个问题需要交待一下。首先是这样作的弊端，虽然这样避免前面提到的大量使用宏的缺点，但是却浪费了存储的空间以及会带来一些使用上的不方便。先说浪费了存储空间，以往存放一个数据只需要一个与该数据相同大小的空间就可以了，但是现在还需要多使用一个data_t指针指向分配好的空间，无形之中浪费了一个指针的空间。再说使用的不方便，以往处理数据的时候如果没有特别的要求可以直接传值，而现在必须传指针，因为CGL的函数不认什么int,double,char类型，只处理指针。换句话说，假如f是CGL中的一个函数，如果要调用传入一个整型参数5，你必须这样作:<br>int nVal = 5;<br>f(&amp;nVal);<br>而一般传值就可以做到的调用是f(5)就可以了，这样会造成使用上的不方便。<br>至于数据的赋值，我采用的C库中memcpy函数，只要传入指向数据的指针和数据的尺寸就可以，比较数据是否相等则采用C库中的memcmp函数，所需要知道的参数和memcpy一样，而当需要比较数据的大小时，这个比较头疼，因为C库中没有根据指针和数据的大小进行比较的函数，我在后面会解释我现在处理此类问题的办法。<br><br>再来说说其他的两个typedef:<br>typedef char*&nbsp;base_t;<br>typedef char &nbsp;bool_t;<br>最后的一个bool_t很好理解，就是一般的bool型嘛，之所以用char很简单，char类型所需要的字节数最少，省空间。而base_t这个类型的含义是一个系统中最基本的数据类型，或者可以这么理解,别的数据类型所占有的字节数都可以表示为这个类型的算术操作，以上的言语也许晦涩了一些，我用例子来说明。<br>看CGL中一个函数的实现：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">static&nbsp;point_t&nbsp;cgls_iter_advance(piterator_t&nbsp;pIter,&nbsp;size_t&nbsp;n)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;base_t&nbsp;tTmp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;CGL_ASSERT(</span><span style="COLOR: #0000ff">NULL</span><span style="COLOR: #000000">&nbsp;!</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;pIter);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;CGL_ASSERT(</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&lt;=</span><span style="COLOR: #000000">&nbsp;n);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;tTmp&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(base_t)(pIter</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">tPoint);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;pIter</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">tPoint&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;tTmp&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;pIter</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">nValSize&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;n;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;pIter</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">tPoint;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>}<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
这个函数的作用是把迭代器pIter中保存的指向容器中数据的指针tPoint向前移动n个位置，大家知道指针的移动和它所指向的数据类型的大小有密切的关系，换句话说一个指针向前走n个位置所要移动的字节数为n * 它所指向的数据的尺寸，在上面的函数中,tPoint这个指针所指向的数据的尺寸存放在pIter的成员变量nValSize中，你也许会问直接使用sizeof(*tPoint)不就可以得到这个数值了么？别忘了我们前面说过所有的指针类型都是void*，而对void*指针是不能进行解引用操作的，所以我们需要一个变量来存放数据的尺寸。<br>注意到函数中的两个操作:<br>&nbsp;tTmp = (base_t)(pIter-&gt;tPoint);<br>&nbsp;pIter-&gt;tPoint = tTmp + pIter-&gt;nValSize * n;<br>结合着base_t的定义，可以解释为把void*指针tPoint强制转化为char*，而tPoint向前走的位置为tTmp +&nbsp; nValSize*n，对于tTmp而言，它的类型是base_t也即是char*，sizeof(char) = 1，因此采用char*来保存以及进行指针的加减操作是最自然的操作，只要我们知道需要前进的步数(n),每部的幅度(nValSize)，就可以通过把指针强制转化为base_t也就是char*来达到我们所要到达的位置。<br><br>以上，是我对目前CGL中几个typedef的解释。可以看到的是，设计中总是存在着这样那样的折中，很多地方的处理也是不完美的，我选择的是不向宏妥协而是自己对指针进行处理和操作。<br>
<img src ="http://www.cppblog.com/converse/aggbug/23311.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/converse/" target="_blank">创</a> 2007-05-02 00:59 <a href="http://www.cppblog.com/converse/archive/2007/05/02/23311.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CGL编码规范V1.0</title><link>http://www.cppblog.com/converse/archive/2007/04/28/23148.html</link><dc:creator>创</dc:creator><author>创</author><pubDate>Sat, 28 Apr 2007 15:48:00 GMT</pubDate><guid>http://www.cppblog.com/converse/archive/2007/04/28/23148.html</guid><wfw:comment>http://www.cppblog.com/converse/comments/23148.html</wfw:comment><comments>http://www.cppblog.com/converse/archive/2007/04/28/23148.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/converse/comments/commentRss/23148.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/converse/services/trackbacks/23148.html</trackback:ping><description><![CDATA[<p>之前虽然在写代码的时候自己心中有一个编码的规范，但是毕竟没有述之文字，现在回头看了看发现还是有很多地方不够规范的，花了一个晚上扫了一下原有的代码，制定出这个规范，毕竟是写出来白纸黑字的，以后有依可循，这并不是最后的规范版本，我把它命名为V1.0，会根据需要不断的补充完善，并且会check in到SF的SVN中去，有可能的话再写一份E文版的规范，而每次对规范的补充完善相应的都会进行对代码的重构。<br><br>这是一个好的习惯，希望我以后不管是作商业上的开发还是自己下面作着玩儿写的代码都按照这些流程走下来，我相信，好的习惯和风格会带来很多积极的影响。<br><br></p>
<p>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">CGL编码命名规范V1.</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">(</span><span style="COLOR: #000000">2007</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">04</span><span style="COLOR: #000000">-</span><span style="COLOR: #000000">29</span><span style="COLOR: #000000">)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">.变量命名采用匈牙利命名法，如下：<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">）整型变量加前缀n<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">）指针变量加前缀p<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">)自定义也就是typedef声明的新类型变量加前缀t，而这些类型的定义后面加_t后缀，如iter_t<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">）char类型加前缀c，char数组加类型sz<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">）变量的命名一般为以上的前缀加上相应的描述名词，同时名词第一个字母大写，如piterator_t&nbsp;pIter<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">.宏一律大写，并且加上前缀CGL_<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">.函数名称加前缀cgl_，如果是某类型的接口函数加上类型名称，其后命名基本参照对应的STL中函数的命名，<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;如cgl_list_clear与STL中list容器的clear函数对应<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;但是还需要注意的是，如果是在某个文件中的static函数，也就是外部不能使用的函数，前缀改为cgls_<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;而对于某个结构体内定义的函数指针类型不需要加上cgl前缀，只需要对函数功能进行说明就可以了，一般为<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;动词</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">名词的形式命名。<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;如iterator中的函数指针&nbsp;&nbsp;&nbsp;&nbsp;data_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">get_value)(piterator_t&nbsp;pIter);就是得到这个iterator<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;值的函数。<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;有了这个规则，那些在CGL中出现的没有这些前缀的函数都是C库中提供的库函数。<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">.进行比较操作时把常量放在比较操作符左边，如if(</span><span style="COLOR: #0000ff">NULL</span><span style="COLOR: #000000">&nbsp;!</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;pIter)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">.自定义的数据类型以及结构体的命名习惯为描述该类型的名词&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">_t</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">，如iterator_t，如果是指向该类型<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;变量的指针类型则在前面加上p前缀，如piterator_t<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">6</span><span style="COLOR: #000000">.头文件中为防止重复包含所声明的宏命名规范为该头文件的去掉</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">后缀之后的文件名再加上</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">_H</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">后缀，<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;同时这个组合的前后都要加上</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">__</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">，如cgl_commondef.h头文件中的宏为__CGL_COMMONDEF_H__<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">7</span><span style="COLOR: #000000">.每个文件都要以&#8220;CGL_BEGIN&#8221;开始，以&#8220;CGL_END&#8221;结尾<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">8</span><span style="COLOR: #000000">.不可忽略编译时的警告信息，如果在操作中需要强制转换的要明确写出来，不应依赖于编译器隐式的转换。<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">9</span><span style="COLOR: #000000">.文件的命名为cgl_前缀加上该文件的描述，一般的，这个后缀与STL中对应的文件名相同，如STL中的list文件<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;其在CGL中的对应头文件就是cgl_list.h，c文件就是cgl_list.c<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">10</span><span style="COLOR: #000000">.所有函数的定义前面一律加上对函数功能，输入，输出参数的注释说明&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p><br><br>&nbsp;</p>
<img src ="http://www.cppblog.com/converse/aggbug/23148.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/converse/" target="_blank">创</a> 2007-04-28 23:48 <a href="http://www.cppblog.com/converse/archive/2007/04/28/23148.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CGL开发手记之一--参考资料</title><link>http://www.cppblog.com/converse/archive/2007/03/18/20083.html</link><dc:creator>创</dc:creator><author>创</author><pubDate>Sun, 18 Mar 2007 11:40:00 GMT</pubDate><guid>http://www.cppblog.com/converse/archive/2007/03/18/20083.html</guid><wfw:comment>http://www.cppblog.com/converse/comments/20083.html</wfw:comment><comments>http://www.cppblog.com/converse/archive/2007/03/18/20083.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/converse/comments/commentRss/20083.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/converse/services/trackbacks/20083.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 有关CGL写作中经常参考到的资料.&nbsp;&nbsp;<a href='http://www.cppblog.com/converse/archive/2007/03/18/20083.html'>阅读全文</a><img src ="http://www.cppblog.com/converse/aggbug/20083.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/converse/" target="_blank">创</a> 2007-03-18 19:40 <a href="http://www.cppblog.com/converse/archive/2007/03/18/20083.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CGL开发记录(一)</title><link>http://www.cppblog.com/converse/archive/2007/02/11/18659.html</link><dc:creator>创</dc:creator><author>创</author><pubDate>Sun, 11 Feb 2007 08:59:00 GMT</pubDate><guid>http://www.cppblog.com/converse/archive/2007/02/11/18659.html</guid><wfw:comment>http://www.cppblog.com/converse/comments/18659.html</wfw:comment><comments>http://www.cppblog.com/converse/archive/2007/02/11/18659.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/converse/comments/commentRss/18659.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/converse/services/trackbacks/18659.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 通过svn向SF提交了CGL的第一份代码~~&nbsp;&nbsp;<a href='http://www.cppblog.com/converse/archive/2007/02/11/18659.html'>阅读全文</a><img src ="http://www.cppblog.com/converse/aggbug/18659.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/converse/" target="_blank">创</a> 2007-02-11 16:59 <a href="http://www.cppblog.com/converse/archive/2007/02/11/18659.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>