﻿<?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++博客-Welcome to ErranLi's Blog!-随笔分类-C &amp; C++</title><link>http://www.cppblog.com/erran/category/5344.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 19 May 2008 13:29:01 GMT</lastBuildDate><pubDate>Mon, 19 May 2008 13:29:01 GMT</pubDate><ttl>60</ttl><item><title>转：字节对齐详解</title><link>http://www.cppblog.com/erran/archive/2007/10/16/34383.html</link><dc:creator>erran</dc:creator><author>erran</author><pubDate>Tue, 16 Oct 2007 14:56:00 GMT</pubDate><guid>http://www.cppblog.com/erran/archive/2007/10/16/34383.html</guid><wfw:comment>http://www.cppblog.com/erran/comments/34383.html</wfw:comment><comments>http://www.cppblog.com/erran/archive/2007/10/16/34383.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/erran/comments/commentRss/34383.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/erran/services/trackbacks/34383.html</trackback:ping><description><![CDATA[
		<br />看了这篇（http://www.cppblog.com/Randy/archive/2007/10/15/34288.aspx）关于字节对其的随笔，觉得迷迷糊糊的，脑袋里只有字节对其这个概念，具体都忘的差不多了，又另外找了篇细读了下，总算理解了。<br /><br />来源：http://www.yuanma.org/data/2006/0723/article_1213.htm<br /><h3>一.什么是字节对齐,为什么要对齐?</h3><p>   
现代计算机中内存空间都是按照byte划分的，从理论上讲似乎对任何类型的变量的访问可以从任何地址开始，但实际情况是在访问特定类型变量的时候经常在特
定的内存地址访问，这就需要各种类型数据按照一定的规则在空间上排列，而不是顺序的一个接一个的排放，这就是对齐。<br />   
对齐的作用和原因：各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些架构的CPU在访问
一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐.其他平台可能没有这种情况，但是最常见的是如果不按照适合其平台要求对
数据存放进行对齐，会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始，如果一个int型（假设为32位系统）如果存放在偶地址开始的地方，那
么一个读周期就可以读出这32bit，而如果存放在奇地址开始的地方，就需要2个读周期，并对两次读出的结果的高低字节进行拼凑才能得到该32bit数
据。显然在读取效率上下降很多。</p><h3>二.字节对齐对程序的影响:</h3><p>    先让我们看几个例子吧(32bit,x86环境,gcc编译器):<br />设结构体如下定义：<br />struct A<br />{<br />    int a;<br />    char b;<br />    short c;<br />};<br />struct B<br />{<br />    char b;<br />    int a;<br />    short c;<br />};<br />现在已知32位机器上各种数据类型的长度如下:<br />char:1(有符号无符号同)    <br />short:2(有符号无符号同)    <br />int:4(有符号无符号同)    <br />long:4(有符号无符号同)    <br />float:4    double:8<br />那么上面两个结构大小如何呢?<br />结果是:<br />sizeof(strcut A)值为8<br />sizeof(struct B)的值却是12</p><p>结构体A中包含了4字节长度的int一个，1字节长度的char一个和2字节长度的short型数据一个,B也一样;按理说A,B大小应该都是7字节。<br />之所以出现上面的结果是因为编译器要对数据成员在空间上进行对齐。上面是按照编译器的默认设置进行对齐的结果,那么我们是不是可以改变编译器的这种默认对齐设置呢,当然可以.例如:<br />#pragma pack (2) /*指定按2字节对齐*/<br />struct C<br />{<br />    char b;<br />    int a;<br />    short c;<br />};<br />#pragma pack () /*取消指定对齐，恢复缺省对齐*/<br />sizeof(struct C)值是8。<br />修改对齐值为1：<br />#pragma pack (1) /*指定按1字节对齐*/<br />struct D<br />{<br />    char b;<br />    int a;<br />    short c;<br />};<br />#pragma pack () /*取消指定对齐，恢复缺省对齐*/<br />sizeof(struct D)值为7。<br />后面我们再讲解#pragma pack()的作用.</p><h3>三.编译器是按照什么样的原则进行对齐的?</h3><p>    先让我们看四个重要的基本概念：<br /><font color="#0000ff">1.数据类型自身的对齐值：<br /></font>  对于char型数据，其自身对齐值为1，对于short型为2，对于int,float,double类型，其自身对齐值为4，单位字节。<br /><font color="#3300ff">2.结构体或者类的自身对齐值：</font>其成员中自身对齐值最大的那个值。<br /><font color="#0000ff">3.指定对齐值</font>：#pragma pack (value)时的指定对齐值value。<br /><font color="#0000ff">4.数据成员、结构体和类的有效对齐值：</font>自身对齐值和指定对齐值中小的那个值。<br />有
了这些值，我们就可以很方便的来讨论具体数据结构的成员和其自身的对齐方式。有效对齐值N是最终用来决定数据存放地址方式的值，最重要。有效对齐N，就是
表示“对齐在N上”，也就是说该数据的"存放起始地址%N=0".而数据结构中的数据变量都是按定义的先后顺序来排放的。第一个数据变量的起始地址就是数
据结构的起始地址。结构体的成员变量要对齐排放，结构体本身也要根据自身的有效对齐值圆整(就是结构体成员变量占用总长度需要是对结构体有效对齐值的整数
倍，结合下面例子理解)。这样就不能理解上面的几个例子的值了。<br />例子分析：<br />分析例子B；<br />struct B<br />{<br />    char b;<br />    int a;<br />    short c;<br />};<br />假
设B从地址空间0x0000开始排放。该例子中没有定义指定对齐值，在笔者环境下，该值默认为4。第一个成员变量b的自身对齐值是1，比指定或者默认指定
对齐值4小，所以其有效对齐值为1，所以其存放地址0x0000符合0x0000%1=0.第二个成员变量a，其自身对齐值为4，所以有效对齐值也为4，
所以只能存放在起始地址为0x0004到0x0007这四个连续的字节空间中，复核0x0004%4=0,且紧靠第一个变量。第三个变量c,自身对齐值为
2，所以有效对齐值也是2，可以存放在0x0008到0x0009这两个字节空间中，符合0x0008%2=0。所以从0x0000到0x0009存放的
都是B内容。再看数据结构B的自身对齐值为其变量中最大对齐值(这里是b）所以就是4，所以结构体的有效对齐值也是4。根据结构体圆整的要求，
0x0009到0x0000=10字节，（10＋2）％4＝0。所以0x0000A到0x000B也为结构体B所占用。故B从0x0000到0x000B
共有12个字节,sizeof(struct B)=12;<font color="#3300ff">其实如果就这一个就来说它已将满足字节对齐了,
因为它的起始地址是0,因此肯定是对齐的,之所以在后面补充2个字节,是因为编译器为了实现结构数组的存取效率,试想如果我们定义了一个结构B的数组,那
么第一个结构起始地址是0没有问题,但是第二个结构呢?按照数组的定义,数组中所有元素都是紧挨着的,如果我们不把结构的大小补充为4的整数倍,那么下一
个结构的起始地址将是0x0000A,这显然不能满足结构的地址对齐了,因此我们要把结构补充成有效对齐大小的整数倍.其实诸如:对于char型数据，其
自身对齐值为1，对于short型为2，对于int,float,double类型，其自身对齐值为4，这些已有类型的自身对齐值也是基于数组考虑的,只
是因为这些类型的长度已知了,所以他们的自身对齐值也就已知了.<br /></font>同理,分析上面例子C：<br />#pragma pack (2) /*指定按2字节对齐*/<br />struct C<br />{<br />    char b;<br />    int a;<br />    short c;<br />};<br />#pragma pack () /*取消指定对齐，恢复缺省对齐*/<br />第
一个变量b的自身对齐值为1，指定对齐值为2，所以，其有效对齐值为1，假设C从0x0000开始，那么b存放在0x0000，符合0x0000%1=
0;第二个变量，自身对齐值为4，指定对齐值为2，所以有效对齐值为2，所以顺序存放在0x0002、0x0003、0x0004、0x0005四个连续
字节中，符合0x0002%2=0。第三个变量c的自身对齐值为2，所以有效对齐值为2，顺序存放<br />在0x0006、0x0007中，符合
0x0006%2=0。所以从0x0000到0x00007共八字节存放的是C的变量。又C的自身对齐值为4，所以C的有效对齐值为2。又8%2=0,C
只占用0x0000到0x0007的八个字节。所以sizeof(struct C)=8.</p><h3>四.如何修改编译器的默认对齐值?</h3><p>1.在VC IDE中，可以这样修改：[Project]|[Settings],c/c++选项卡Category的Code Generation选项的Struct Member Alignment中修改，默认是8字节。<br />2.在编码时，可以这样动态修改：#pragma pack .<font color="#ff0000">注意:是pragma而不是progma.</font></p><h3>五.针对字节对齐,我们在编程中如何考虑?</h3><p><br />   
如果在编程的时候要考虑节约空间的话,那么我们只需要假定结构的首地址是0,然后各个变量按照上面的原则进行排列即可,基本的原则就是把结构中的变量按照
类型大小从小到大声明,尽量减少中间的填补空间.还有一种就是为了以空间换取时间的效率,我们显示的进行填补空间进行对齐,比如:有一种使用空间换时间做
法是显式的插入reserved成员：<br />         struct A{<br />           char a;<br />           char reserved[3];//使用空间换时间<br />           int b;<br />}<br /><br />reserved成员对我们的程序没有什么意义,它只是起到填补空间以达到字节对齐的目的,当然即使不加这个成员通常编译器也会给我们自动填补对齐,我们自己加上它只是起到显式的提醒作用.</p><h3>六.字节对齐可能带来的隐患:</h3><p>    代码中关于对齐的隐患，很多是隐式的。比如在强制类型转换的时候。例如：<br />unsigned int i = 0x12345678;<br />unsigned char *p=NULL;<br />unsigned short *p1=NULL;</p><p>p=&amp;i;<br />*p=0x00;<br />p1=(unsigned short *)(p+1);<br />*p1=0x0000;<br />最后两句代码，从奇数边界去访问unsignedshort型变量，显然不符合对齐的规定。<br />在x86上，类似的操作只会影响效率，但是在MIPS或者sparc上，可能就是一个error,因为它们要求必须字节对齐.</p><h3>七.如何查找与字节对齐方面的问题:</h3><p>如果出现对齐或者赋值问题首先查看<br />1. 编译器的big little端设置<br />2. 看这种体系本身是否支持非对齐访问<br />3. 如果支持看设置了对齐与否,如果没有则看访问时需要加某些特殊的修饰来标志其特殊访问操作。</p><p>八.相关文章:转自<a href="http://blog.csdn.net/goodluckyxl/archive/2005/10/17/506827.aspx"><u>http://blog.csdn.net/goodluckyxl/archive/2005/10/17/506827.aspx</u></a></p><quote></quote><p> ARM下的对齐处理 <br />from DUI0067D_ADS1_2_CompLib </p><p>3.13 type  qulifiers </p><p>有部分摘自ARM编译器文档对齐部分</p><p>对齐的使用:<br />1.__align(num)<br />   这个用于修改最高级别对象的字节边界。在汇编中使用LDRD或者STRD时<br />   就要用到此命令__align(8)进行修饰限制。来保证数据对象是相应对齐。<br />   这个修饰对象的命令最大是8个字节限制,可以让2字节的对象进行4字节<br />   对齐,但是不能让4字节的对象2字节对齐。<br />   __align是存储类修改,他只修饰最高级类型对象不能用于结构或者函数对象。<br />   <br />2.__packed <br />  __packed是进行一字节对齐<br />  1.不能对packed的对象进行对齐<br />  2.所有对象的读写访问都进行非对齐访问<br />  3.float及包含float的结构联合及未用__packed的对象将不能字节对齐<br />  4.__packed对局部整形变量无影响<br />  5.强制由unpacked对象向packed对象转化是未定义,整形指针可以合法定<br />  义为packed。<br />     __packed int* p;  //__packed int 则没有意义<br />  6.对齐或非对齐读写访问带来问题<br />  __packed struct STRUCT_TEST<br /> {<br />  char a;<br />  int b;<br />  char c;<br /> }  ;    //定义如下结构此时b的起始地址一定是不对齐的<br />         //在栈中访问b可能有问题,因为栈上数据肯定是对齐访问[from CL]<br />//将下面变量定义成全局静态不在栈上 <br />static char* p;<br />static struct STRUCT_TEST a;<br />void Main()<br />{<br /> __packed int* q;  //此时定义成__packed来修饰当前q指向为非对齐的数据地址下面的访问则可以</p><p> p = (char*)&amp;a;          <br /> q = (int*)(p+1);      <br /> <br /> *q = 0x87654321; <br />/*   <br />得到赋值的汇编指令很清楚<br />ldr      r5,0x20001590 ; = #0x12345678<br />[0xe1a00005]   mov      r0,r5<br />[0xeb0000b0]   bl       __rt_uwrite4  //在此处调用一个写4byte的操作函数 <br />      <br />[0xe5c10000]   strb     r0,[r1,#0]   //函数进行4次strb操作然后返回保证了数据正确的访问<br />[0xe1a02420]   mov      r2,r0,lsr #8<br />[0xe5c12001]   strb     r2,[r1,#1]<br />[0xe1a02820]   mov      r2,r0,lsr #16<br />[0xe5c12002]   strb     r2,[r1,#2]<br />[0xe1a02c20]   mov      r2,r0,lsr #24<br />[0xe5c12003]   strb     r2,[r1,#3]<br />[0xe1a0f00e]   mov      pc,r14<br />*/</p><p>/*<br />如果q没有加__packed修饰则汇编出来指令是这样直接会导致奇地址处访问失败<br />[0xe59f2018]   ldr      r2,0x20001594 ; = #0x87654321<br />[0xe5812000]   str      r2,[r1,#0]<br />*/</p>//这样可以很清楚的看到非对齐访问是如何产生错误的<br />//以及如何消除非对齐访问带来问题<br />//也可以看到非对齐访问和对齐访问的指令差异导致效率问题<br />}<br /><img src ="http://www.cppblog.com/erran/aggbug/34383.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/erran/" target="_blank">erran</a> 2007-10-16 22:56 <a href="http://www.cppblog.com/erran/archive/2007/10/16/34383.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：C++对象内存布局</title><link>http://www.cppblog.com/erran/archive/2007/10/14/34184.html</link><dc:creator>erran</dc:creator><author>erran</author><pubDate>Sat, 13 Oct 2007 16:37:00 GMT</pubDate><guid>http://www.cppblog.com/erran/archive/2007/10/14/34184.html</guid><wfw:comment>http://www.cppblog.com/erran/comments/34184.html</wfw:comment><comments>http://www.cppblog.com/erran/archive/2007/10/14/34184.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/erran/comments/commentRss/34184.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/erran/services/trackbacks/34184.html</trackback:ping><description><![CDATA[
		<br />引用：http://www.cppblog.com/stdyh/archive/2007/01/08/17442.html<br /><br />C++对象内存布局<br /><br /><br />
			写这个文章完全是因为想要搞清楚 vc 怎么布局每个 c++ 对象,以及怎样完成指针的转换的过程.<br />　　先问一个问题,两个不同类型的指针相互转换以后,他们在数值上是一样的吗?比如:<br /><br />　　　　<font color="#000066">int nValue = 10;<br />　　　　int *pInt = &amp;nValue;<br />　　　　void *pVoid = pInt;<br />　　　　char *pChar = (char*)pInt;</font><br /><br />　
　这些指针的值(不是说指针指向的内存的内容)是一样的吗? 如果你的回答是
yes,那如果是一个类的继承体系呢?在继承类向基类转换的过程中,指针的数值还是不变化的么?如果你的回答是"不一定会变化,要看类的体系是怎么设计的
"的话,那恭喜你,不用看下去了.如果你还不确定究竟变还是不变,究竟哪些变,哪些不变,究竟为什么要变为什么不变的话,接着看下来.<br /><br />　
　c++ 标准不规定 c++ 实现的时候的对象的具体的内存布局,除了在某些方面有小的限制以外,c++
对象在内存里面的布局完全是由编译器自行决定,这里我也只是讨论 vc++ .net 2003 build 7.1.3091
的实现方式,我并没有在 vc5 vc6 vc.net 2002 以及其他的 2003 build
上面做过测试,结论也许不适合那些编译平台.这些属于编译器具体实现,ms 保留有在不通知你我的情况下作出更改的权利.废话这么多,马上开始.<br /><br />　　对于 c 的内建指针的转换,结果是不用多讨论的,我们只是讨论 c++ 的对象.从最简单的开始.<br /><br />　　　　<font color="#000066">class CBase<br />　　　　{<br />　　　　public:<br />　　　　　　int m_nBaseValue;<br />　　　　};</font><br /><br />　　这样的一个类在内存里放置是非常简单的,他占有4个 bytes 的空间,不用多说,我们从他派生一个类出来.<br /><br />　　　　<font color="#000066">class CDerive1 : public CBase<br />　　　　{<br />　　　　public:<br />　　　　　　int m_nDerive1Value;<br />　　　　};</font><br /><br />　
　CDerive1 的对象在内存里面是怎么放的呢? 也很简单,占有8个 bytes 的空间,前4个 bytes 属于 CBase 类,后四个
bytes 属于自己.一个CDerive1 的指针转换成一个 CBase 的指针,结果是一样的.下面我们加上多重继承看看.<br /><br />　　　　<font color="#000066">class CFinal : public CDerive,public CBase <font color="#ff0000">// 这里的 CDerive 是一个和 CBase 差不多的基类</font><br />　　　　{<br />　　　　public:<br />　　　　　　int m_nFinalValue;<br />　　　　}; </font><br /><br />　
　CFinal 的对象在内存里面的布局稍微复杂一点,但是也很容易想象,他占有 12 个 bytes 的空间,前4个属于
CDerive,中间4个属于 CBase,后面4个才是自己的.那一个 CFinal 的指针转换成一个 CDerive 指针,数值会变么?
转换成一个 CBase 指针呢?又会变化么?答案是,前一个不变,后一个要变化,道理非常的明显,CFinal 对象的开头刚好是一个
CDerive 对象,而 CBase 对象却在 CFinal 对象的中间,自然是要变化的了,具体怎么变化呢? 加 4 就
ok(自然要检查是否是空指针).<br /><br />　　　　<font color="#ff0000">CBase *pBase = pFinal ? (CBase*)((char*)pFinal + sizeof(CDerive)) : 0;// 当你写下 pBase = pFinal 的时候,其实是这样的</font><br /><br />　　这种不带 virtual 的继承就这么简单,只是加上一个 offset 而已.下面我们看看如果加上 virtual function 的时候是什么样子的呢?<br />还是从简单类开始.<br /><br />　　　　<font color="#000066">class CBase<br />　　　　{<br />　　　　public:<br />　　　　　　virtual void VirtualBaseFunction(){}<br />　　　　　　int m_nBaseValue;<br />　　　　}; </font><br /><br />　
　这里刻意没有使用 virtual destructor,因为这个函数稍微有些不同.还是同样的问题,CBase 类在内存上占多大的空间?还是
4 bytes 么? 答案是 no, 在我的编译器上面是 8 bytes,多出来的 4 bytes 是 __vfptr(watch
窗口看见的名字),他是一个指针,指向了类的 vtable,那什么是 vtable 呢,他是用来干什么的呢? vtable 是用来支援
virtual function
机制的,他其实是一个函数指针数组(并不等同于c/c++语言里面的指针数组,因为他们的类型并不一定是一样的.)他的每一个元素都指向了一个你定义的
virtual
function,这样通过一个中间层来到达动态连编的效果,这些指针是在程序运行的时候准备妥当的,而不是在编译的时候准备妥当的,这个就是动态联编的
目的,具体是由谁来设置这些指针的呢?constructor/destructor/copy constructor/assignment
operator他们完成的,不用奇怪,编译器会在你写的这些函数里面安插些必要的代码用来设置 vtable
的值,如果你没有写这些函数,编译器会在适当的时候帮你生成这些函数.明白一点, vtable 是用来支持 virtual function
机制的,而需要 virtual 机制的类基本上都会由一个 __vfptr 指向他自己的 vtable.在调用 virtual
function的时候,编译器这样完成:<br /><br />　　　<font color="#000099">pBase-&gt;VirtualBaseFunction(); =&gt; pBase-&gt;__vfptr[0]();</font><font color="#ff0000">// 0 是你的virtual function 在 vtable 中的 slot number,编译器决定</font><br /><br />　
　现在应该很想象 CBase 的大小了吧,那这个 __vfptr 是放到什么位置的呢? 在 m_nBaseValue 之前还是之后呢?
在我的编译器上看来,是在之前,为什么要放到之前,是因为在通过 指向类成员函数的指针调用 virtual function
的时候能少些代码(指汇编代码),这个原因这里就不深入讨论了,有兴趣的同学可以看看 inside the c++ object model 一书.<br />　　接下来,我们加上继承来看看.<br /><br />　　　　<font color="#000099">class CDerive1 : public CBase<br />　　　　{<br />　　　　public:<br />　　　　　　virtual void VirtualDerive1Function();<br />　　　　};</font><br /><br />　
　这个时候你也许要说,内存布局跟没有 virtual 是一样的,只不过每个类多了一个 __vfptr
而已,呃...这个是不对的,在我的编译器上面 两个类共享同一个 __vfptr, vtable
里面放有两个指针,一个是两个类共享的,一个只属于 CDerive1 类,调用的时候如何呢?<br /><br />　　　<font color="#000099">pDerive1-&gt;VirtualDerive1Function() =&gt; pDerive1-&gt;__vfptr[1]();<br />　　　pDerive1-&gt;VirtualBaseFunction() =&gt; pDerive1-&gt;__vfptr[0]();</font><br /><br />　　至于指针的相互转换,数值还是没有变化的(也正是追求这种效果,所以把 __vfptr 放到类的开头,因为调整 this 指针也是要占有运行时的时间的).<br /><br />　
　现在加上多重继承瞧瞧,代码我不写上来了,就跟上面的 CFinal, CDerive, CBase
体系一样,只是每个类多一个VirtualxxxFunction出来,这个时候的指针调整还是没有什么变化,所以我们只是看看 vtable
的情况,你会说 CDerive 和 CFinal 共享一个 __vfptr,而 CBase 有一个自己的 __vfptr,而 CFinal 的
__vfptr 有 2 个slot,这个结论是正确的. 同时你也会说 通过 CFinal 类调用 CBase 的函数是要进行指针调整的,yes
you'r right,不仅仅是 this 指针调整(呃,this 指针会成为 function 的一个参数),还要调整 vtable 的值:<br /><br />　　　<font color="#0000cc">pFinal-&gt;VirtualBaseFunction() =&gt; (CBase*)((char*)pFinal + sizeof(CDerive))-&gt;__vfptr[0]();</font><br /><br />　　　转换成 asm 的代码大约是这样的:<br /><br /><font color="#000099">　　　mov eax,[pFinal] <font color="#ff00ff">; pFinal is a local object,pFinal will be epb - xx</font><br />　　　add eax,8 <font color="#ff00ff">; 8 = sizeof(CDerive)</font><br />　　　mov ecx,eax <font color="#ff00ff">; ecx is this pointer</font><br />　　　mov edx,[eax] <font color="#ff00ff">; edx = vtable address</font><br />　　　call [edx] <font color="#ff00ff">; call vtable[0]</font></font><br /><br />　　写到这里也就明白this指针是怎么调整的.带 virtual function 的继承也不复杂,this指针调整也是很简单的,下面看最复杂的部分 virtual inheritance.<br /><br />　
　我的编译器支持虚拟继承的方式和虚函数的方式差不多,都是通过一个 table 完成,只是这个就看不到 vc 赋予的名字了,我们叫他
vbtable 吧,编译器同样在类里面加入一个指向 vbtable 的指针,我们叫他 __vbptr 吧,这个指针指向了 vbtable ,而
vbtable 里面的每一项对应了一个基类,vbtable
记录了每个基类的某一个偏移量,通过这个偏移量就能计算出具体类的指针的位置.看个简单的例子:<br /><br />　　　<font color="#000099">class CBase<br />　　　{<br />　　　public:<br />　　　　　virtual ~CBase(){}<br />　　　}; <br /><br />　　　class CMid1 : public virtual CBase<br />　　　{<br />　　　public:<br />　　　　　virtual ~CMid1(){}<br />　　　　　int m_nMid1;<br />　　　}; <br /><br />　　　class CMid2 : public virtual CBase<br />　　　{<br />　　　public:<br />　　　　　virtual ~CMid2(){}<br />　　　　　int m_nMid2;<br />　　　}; <br /><br />　　　class CFinal : public CMid1,public CMid2<br />　　　{<br />　　　public:<br />　　　　　virtual ~CFinal(){}<br />　　　　　int m_nFinal;<br />　　　}; <br /><br />　　　CFinal final;<br />　　　CFinal *pFinal = &amp;final;    <font color="#ff00ff">// pFinal = 0x0012feb4;</font><br />　　　CBase *pBase = pFinal; <font color="#ff00ff">// pBase = 0x0012fec8 = pFinal + 0x14;</font><br />　　　CMid1 *pMid1 = pFinal; <font color="#ff00ff">// pMid1 = 0x0012feb4 = pFinal;</font><br />　　　CMid2 *pMid2 = pFinal; <font color="#ff00ff">// pMid2 = 0x004210b4 = pFinal;</font></font><br /><br />　
　结果让你吃惊吗? 最奇怪的地方居然是 CMid2 和 CMid1 的地址居然是一样的,这个是因为 vc 把 vbtable 放到了
CFinal 类的开头的原因,而CMid1 和 CMid2 也同样要使用这个 vbtable, 所以 这个三个的地址也就必须相同了.那
CBase 的地址是怎么出来的呢? 呃...刚刚我们说了 vbtable 放到了CFinal 的开头(vc
一定会放在开头吗?答案是不一定,这个稍后解释).在我的机器上面 final 对应内存的第一个 dword 是
0x00426030,查看这个地址,第一个dword 是 0 ,第二个就是 0x14,刚好和 pBase
的偏移相同,这个只是巧合,也许你换个类的继承体系就完全不同了,但是我只是想说明一点,基类的偏移计算是和 vbtable
的值相关联的.下面我们就来看看 vc 是怎么计算这些偏移的.<br />　　vc 在分析我们的代码的时候,生成了一份类的继承体系信息,其中有一个叫 thisDisplacement 的_PMD结构:<br /><br />　　　　<font color="#000099">struct _PMD <font color="#ff00ff">// total undocumented</font><br />　　　　{<br />　　　　　　int mdisp; <font color="#ff00ff">// i think the meaning is Multiinheritance DISPlacement</font><br />　　　　　　int pdisp; <font color="#ff00ff">// Pointer to vbtable DISPlacement</font><br />　　　　　　int vdisp; <font color="#ff00ff">// Vbtable DISPlacement</font><br />　　　　}; </font><br /><br />　
　结构的名字和成员变量的名字确确实实是 vc 的名字(在 watch 窗口输入 (_PMD*)0
就能看到这个结构的详细信息),每个字段的含义却是我自己猜测出来的.mdisp 大概用来表示多重继承(包括单一继承)的时候的偏移量,pdisp
表示 vbtable 的偏移量,而 vdisp 表示类在 vbtable
里面的下标.那么有了这个结构怎样才能完成指针的转换呢?假如我们有一个派生类指针
pFinal,要转换成一个特定的基础类,我们首先要知道和这个基类对应的 _PMD
结构的信息(这个信息的获取,我暂时没有找到一个非常方便的方法,现在我使用的方法下面会有描述),有了这个信息以后,转换就方便了.首先找到
vbtabel 的地址 *(pFinal + pdisp),然后找到基类的偏移 *(*(pFinal + pdisp) + vdisp)
这个偏移值是相对vbtable的,所以还要加上 vbtable的偏移,最后加上 mdisp的偏移,如下:<br /><br />　　<font color="#000099">char *pFinal = xxx; <font color="#ff00ff">// need a init value</font><br />　　char *pBase; <font color="#ff00ff">// we must calc</font><br />　　pBase = pFinal + mdisp + *(int *)(*(int *)(pFinal + pdisp) + vdisp) + pdisp;</font><br /><br />　　<font color="#ff0000">注意: 当 pdisp &lt; 0 的时候就表示这个类没有 vbtable 直接使用 pFinal + mdisp 就得到结果了.<br />　　<font color="#00ff00">所以这个结构是一个通用的结构,专门用作类型转换,不管是有无虚继承都能使用这个结构进行类型转换.</font></font><br />　　通过这个结构,我们也能看到 vc 是怎样布局这个 object 的.<br /><br />　　看到这里,也许你要大呼一口气,妈妈呀,一个类型转换要这么的麻烦吗?我直接写 pBase = pFinal 不就可以了吗? 恭喜你还没有被我忽悠得晕头转向,哈哈.其实你写下那行语句的时候,编译器在帮你做这个转换,大约生成下面的代码<br /><br />　　　　<font color="#000099">mov eax,[pFinal] <font color="#ff00ff">;final address</font><br />　　　　mov ecx,[eax] <font color="#ff00ff">; vbtable address *(int *)(pFinal + pdisp)</font><br />　　　　mov edx,eax <font color="#ff00ff">; save to edx</font><br />　　　　add edx,[ecx + 4] <font color="#ff00ff">; ecx + 4 is (*(int *)(pFinal + pdisp) + vdisp)</font><br />　　　　mov [pBase],edx <font color="#ff00ff">; edx = pFinal + mdisp + *(int *)(*(int *)(pFinal + pdisp) + vdisp) + pdisp;</font><br />　　　　<font color="#ff00ff">; here mdisp = 0, pdisp = 0, vdisp = 4</font></font><br /><br />　
　也许你要说了,我要这些东西来干什么?要转换的时候直接转换就好了,编译器会帮做,的确,大多数的时候确实是这样,但是,在某些时候却并不如此,现在你
要实现一个功能,输入一个指针,输入一个 _PMD 结构,你要实现一个AdjustPointer
的函数来生成另一个指针.这个时候你也只能这样完成了,因为我没有给你两个指针的名字,就算给了你字符串形式的名字也没有用,呃....你也许会说,办法
是有的,的确是有,模板就能实现这种功能,呵..这个我们暂时不讨论具体的实现细节.也许你要问了,究竟什么时候会去实现这种听都没有听过的功能,其实这
个函数是真正存在的,只不过不是由你来实现的,而是 ms 的人实现的,你只用写一个 带有 c++ 异常的程序,使用 ida
反汇编,然后查找函数,就能找到这个函数了,他用来在异常处理时创建 catch 所需要的
object.至于这个详细的信息,请期待.我会最快速度写出关于 vc 是怎样实现 c++ 异常的文章来.<br /><br />　　最后了,说说那个
_PMD 结构的获取方式.看的时候不要吃惊,方法比较的麻烦,比如我想知道和 CFinal 类相关的 _PMD 信息,先新建工作,写下
throw pFinal 这样的语句,编译,在这个语句的地方设置断点,运行,转到反汇编,进入 __CxxThrowException@8
函数,这个时候不出意外你能看到一个叫 pThrowInfo 的东西(如果看不到,请打开"显示符号名"选项),在 watch
窗口里面输入pThrowInfo,展开他,看到一个pCatchableTypeArray,记录下他的
nCacthableTypes的值,然后在 watch 里面输入<br />pThrowInfo-&gt;pCatchableTypeArray-&gt;arrayOfCatchableTypes[0]
到 pThrowInfo-&gt;pCatchableTypeArray-&gt;arrayOfCatchableTypes[n], n
就是你刚刚记录的值减1,再展开他们,你就能看到一个 thisDisplacement 的数据,继续展开就是 mdisp
等等了,很是麻烦吧.哈..你已经猜到了,这个是和异常有关系的.<br /><br />　　后记:
这段时间,我一直在读些反汇编之后的代码,也颇有些心得,所以才有想法写一些文章,探讨 vc
编译器鲜为人知(太过狂妄了)的秘密,这个方面的文章也有人写过,那些文章也给我不少的启发,我不认为自己是第一个发现这些秘密的人,但是至少我自己知道
的,我是第一个把这些东西写出来的人.文章里面作墨多的部分都是自己发现的.就这个文章里面的内容来说,inside the c++ object
model 是有比较详细的描写,但是他并不是转换针对 vc 这个编译器的实现,而 _PMD 这个结构我也没有在什么地方见有人描述过,只是在
windows develop network
的2002年12月的杂志上看有人提到过这个结构,可惜他却没有了解(至少他在他发表文章的时候是如是说的)这个结构的用处(正是因为这个原因,我才有写
这个文章以及后续文章的冲动).所以,这个文章也算是我自己的原创吧.这个文件虽然和游戏制造没有太大的关系,但是小 T
自视清高,不愿意自己的文章被一帮不懂的人评价来评价去的,所以也没有发到那些著名的 xxx 网站,只发 goldpoint.转载请注明出处(小 T 对自己的第一个原创文章比较珍惜,比较重视,谢谢).<br /><br /><br /><img src ="http://www.cppblog.com/erran/aggbug/34184.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/erran/" target="_blank">erran</a> 2007-10-14 00:37 <a href="http://www.cppblog.com/erran/archive/2007/10/14/34184.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：关于调用约定(cdecl、fastcall、、thiscall) 的一点知识</title><link>http://www.cppblog.com/erran/archive/2007/10/14/34182.html</link><dc:creator>erran</dc:creator><author>erran</author><pubDate>Sat, 13 Oct 2007 16:33:00 GMT</pubDate><guid>http://www.cppblog.com/erran/archive/2007/10/14/34182.html</guid><wfw:comment>http://www.cppblog.com/erran/comments/34182.html</wfw:comment><comments>http://www.cppblog.com/erran/archive/2007/10/14/34182.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/erran/comments/commentRss/34182.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/erran/services/trackbacks/34182.html</trackback:ping><description><![CDATA[
		<div class="postbody">
				<div class="tit">引用：http://www.cppblog.com/oosky/archive/2007/01/08/17422.html<br /><br />函数调用规范<br /><br /><div class="cnt"><p align="left">当高级语言函数被编译成机器码时，有一个问题就必须解决：因为CPU没有办法知道一个函数调用需要多少个、什么样的参数。即计算机不知道怎么给这个函数传递参数，<font color="#0000ff">传递参数的工作必须由函数调用者和函数本身来协调</font>。为此，计算机提供了一种被称为栈的数据结构来支持参数传递。 </p><p align="left">   函数调用时，调用者依次把参数压栈，然后调用函数，函数被调用以后，在堆栈中取得数据，并进行计算。函数计算结束以后，或者调用者、或者函数本身修改堆栈，使堆栈恢复原装。在参数传递中，有两个很重要的问题必须得到明确说明：</p><p align="left">
            																  1) 当参数个数多于一个时，按照什么顺序把参数压入堆栈；<br />2) 函数调用后，由谁来把堆栈恢复原装。<br /><font color="#0000ff" size="2">3）函数的返回值放在什么地方</font></p>在高级语言中，通过函数<font color="#0000ff">调用规范(Calling Conventions)</font>来说明这两个问题。常见的调用规范有： 
            <div align="left"><pre style="padding: 8pt; background: rgb(239, 239, 239) none repeat scroll 0% 50%; font-size: small; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 2em; margin-right: 10%; font-family: -Lucida Sans Typewriter-;"><font color="#800080">stdcall</font><br /><font color="#800080">cdecl<br /></font><font color="#800080">fastcall<br /></font><font color="#800080">thiscall<br /></font><font color="#800080">naked call</font></pre></div><h2 align="left"><font size="4">stdcall调用规范</font></h2><p align="left">stdcall
很多时候被称为pascal调用规范，因为pascal是早期很常见的一种教学用计算机程序设计语言，其语法严谨，使用的函数调用约定是stdcall。
在Microsoft C++系列的C/C++编译器中，常常用PASCAL宏来声明这个调用约定，类似的宏还有WINAPI和CALLBACK。 </p><p align="left">stdcall调用规范声明的语法为：</p><div align="left"><pre style="padding: 8pt; background: rgb(239, 239, 239) none repeat scroll 0% 50%; font-size: small; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 2em; margin-right: 10%; font-family: -Lucida Sans Typewriter-;"><font size="2"><font color="#0000ff">int</font> __stdcall function(<font color="#0000ff">int</font> a,<font color="#0000ff">int</font> b)</font><br /></pre></div><div align="left">stdcall的调用约定意味着： </div><div align="left"><pre style="padding: 8pt; background: rgb(239, 239, 239) none repeat scroll 0% 50%; font-size: medium; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 2em; margin-right: 10%; font-family: -Lucida Sans Typewriter-;"><font size="2"> 1）参数从右向左压入堆栈；<br /> 2）函数自身修改堆栈；<br /> 3) 函数名自动加前导的下划线，后面紧跟一个@符号，其后紧跟着参数的尺寸。</font><br /></pre></div><div align="left">以上述这个函数为例，参数b首先被压栈，然后是参数a，函数调用function(1,2)调用处翻译成汇编语言将变成： </div><div align="left"><pre style="padding: 8pt; background: rgb(239, 239, 239) none repeat scroll 0% 50%; font-size: small; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 2em; margin-right: 10%; font-family: -Lucida Sans Typewriter-;"><font size="2">  push 2          第二个参数入栈<br />              push 1          第一个参数入栈<br />              call function   调用参数，注意此时自动把cs:eip入栈</font></pre></div><div align="left">而对于函数自身，则可以翻译为： </div><div align="left"><pre style="padding: 8pt; background: rgb(239, 239, 239) none repeat scroll 0% 50%; font-size: small; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 2em; margin-right: 10%; font-family: -Lucida Sans Typewriter-;"><font size="2">      push  ebp               保存ebp寄存器，该寄存器将用来保存堆栈的栈顶指针，可以在函数退出时恢复<br />              mov   ebp,esp           保存堆栈指针<br />              mov   eax,[ebp + 8H]    堆栈中ebp指向位置之前依次保存有ebp,cs:eip,a,b,ebp +8指向a<br />              add   eax,[ebp + 0CH]   堆栈中ebp + 12处保存了b<br />              mov   esp,ebp           恢复esp<br />              pop   ebp<br />              ret   8</font></pre></div><p align="left">而在编译时，这个函数的名字被翻译成_function@8 </p><p align="left">注意不同编译器会插入自己的汇编代码以提供编译的通用性，但是大体代码如此。其中在函数开始处保留esp到ebp中，在函数结束恢复是编译器常用的方法。 </p><p align="left">从函数调用看，2和1依次被push进堆栈，而在函数中又通过相对于ebp(即刚进函数时的堆栈指针）的偏移量存取参数。函数结束后，ret 8表示清理8个字节的堆栈，函数自己恢复了堆栈。 </p><h2 align="left"> <font size="4">cdecl调用规范</font></h2><p align="left">cdecl调用约定又称为C调用约定，是C语言缺省的调用约定，它的定义语法是： </p><div align="left"><pre style="padding: 8pt; background: rgb(239, 239, 239) none repeat scroll 0% 50%; font-size: small; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 2em; margin-right: 10%; font-family: -Lucida Sans Typewriter-;"><font size="2"><font color="#0000ff">              int</font> function (<font color="#0000ff">int</font> a ,<font color="#0000ff">int</font> b)           <font color="#ff0000">// 不加修饰就是C调用约定</font><br />              <font color="#0000ff">int</font> __cdecl function(<font color="#0000ff">int</font> a,<font color="#0000ff">int</font> b)     <font color="#ff0000">// 明确指出C调用约定</font></font></pre></div><p align="left"> 
cdecl调用约定的参数压栈顺序是和stdcall是一样的，参数首先由有向左压入堆栈。所不同的是，函数本身不清理堆栈，调用者负责清理堆栈。由于这
种变化，C调用约定允许函数的参数的个数是不固定的，这也是C语言的一大特色。对于前面的function函数，使用cdecl后的汇编码变成： </p><div align="left"><pre style="padding: 8pt; background: rgb(239, 239, 239) none repeat scroll 0% 50%; font-size: small; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 2em; margin-right: 10%; font-family: -Lucida Sans Typewriter-;"><font size="2">调用处<br />              push   1<br />              push   2<br />              call   function<br />              add    esp,8              注意：这里调用者在恢复堆栈<br />              被调用函数_function处<br />              push   ebp                保存ebp寄存器，该寄存器将用来保存堆栈的栈顶指针，可以在函数退出时恢复<br />              mov    ebp,esp            保存堆栈指针<br />              mov    eax,[ebp + 8H]     堆栈中ebp指向位置之前依次保存有ebp,cs:eip,a,b,ebp +8指向a<br />              add    eax,[ebp + 0CH]    堆栈中ebp + 12处保存了b<br />              mov    esp,ebp            恢复esp<br />              pop    ebp<br />              ret                       注意，这里没有修改堆栈</font></pre></div><p align="left">MSDN中说，该修饰自动在函数名前加前导的下划线，因此函数名在符号表中被记录为_function。 <br /></p><p align="left">由于参数按照从右向左顺序压栈，因此最开始的参数在最接近栈顶的位置，因此当采用不定个数参数时，第一个参数在栈中的位置肯定能知道，只要不定的参数个数能够根据第一个后者后续的明确的参数确定下来，就可以使用不定参数，例如对于sprintf函数，定义为：</p><div align="left"><pre style="padding: 8pt; background: rgb(239, 239, 239) none repeat scroll 0% 50%; font-size: small; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 2em; margin-right: 10%; font-family: -Lucida Sans Typewriter-;"><font size="2"><font color="#0000ff">int</font> sprintf(<font color="#0000ff">char</font>* buffer,<font color="#0000ff">const</font><font color="#0000ff">char</font>* format,...)</font></pre></div><div align="left">由于所有的不定参数都可以通过format确定，因此使用不定个数的参数是没有问题的。 </div><h2 align="left"> <font size="4">fastcall调用规范</font></h2><div align="left">fastcall调用约定和stdcall类似，它意味着： </div><div align="left"><pre style="padding: 8pt; background: rgb(239, 239, 239) none repeat scroll 0% 50%; font-size: medium; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 2em; margin-right: 10%; font-family: -Lucida Sans Typewriter-;"><font size="2">            1) 函数的第一个和第二个DWORD参数（或者尺寸更小的）通过ecx和edx传递，其他参数通过从右向左的顺序压栈；<br />            2) 被调用函数清理堆栈；<br />            3) 函数名修改规则同stdcall。</font></pre></div><div align="left">其声明语法为：int __fastcall function(int a,int b) </div><h2 align="left"> <font size="4">thiscall调用规范</font></h2><p align="left">thiscall是唯一一个不能明确指明的函数修饰，因为thiscall不是关键字。它是C++类成员函数缺省的调用约定。由于成员函数调用还有一个this指针，因此必须特殊处理，thiscall意味着： </p><div align="left"><pre style="padding: 8pt; background: rgb(239, 239, 239) none repeat scroll 0% 50%; font-size: medium; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 2em; margin-right: 10%; font-family: -Lucida Sans Typewriter-;"><font size="2">            1) 参数从右向左入栈；<br />            2) 如果参数个数确定，this指针通过ecx传递给被调用者；如果参数个数不确定，this指针在所有参数压栈后被压入堆栈；<br />            3) 对参数个数不定的，调用者清理堆栈，否则函数自己清理堆栈。</font></pre></div><div align="left">为了说明这个调用约定，定义如下类和使用代码： </div><div align="left"><pre style="padding: 8pt; background: rgb(239, 239, 239) none repeat scroll 0% 50%; font-size: small; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 2em; margin-right: 10%; font-family: -Lucida Sans Typewriter-;"><font size="2"><br /><font color="#0000ff">class</font> A<br />            {<br /><font color="#804040">public</font>:<br /><font color="#0000ff">int</font> function1(<font color="#0000ff">int</font> a,<font color="#0000ff">int</font> b);<br /><font color="#0000ff">int</font> function2(<font color="#0000ff">int</font> a,...);<br />            };<br /><font color="#0000ff">int</font> A::function1 (<font color="#0000ff">int</font> a,<font color="#0000ff">int</font> b)<br />            {<br /><font color="#804040">return</font> a+b;<br />            }<br /><font color="#0000ff">int</font> A::function2(<font color="#0000ff">int</font> a,...)<br />            {<br /><font color="#0000ff">va_list</font> ap;<br />            va_start(ap,a);<br /><font color="#0000ff">int</font> i;<br /><font color="#0000ff">int</font> result = <font color="#ff00ff">0</font>;<br /><font color="#804040">for</font>(i = <font color="#ff00ff">0</font> ; i &lt; a ; i ++)<br />            {<br />            result += va_arg(ap,<font color="#0000ff">int</font>);<br />            }<br /><font color="#804040">return</font> result;<br />            }<br /><font color="#0000ff">void</font> callee()<br />            {<br />            A a;<br />            a.function1(<font color="#ff00ff">1</font>,<font color="#ff00ff">2</font>);<br />            a.function2(<font color="#ff00ff">3</font>,<font color="#ff00ff">1</font>,<font color="#ff00ff">2</font>,<font color="#ff00ff">3</font>);<br />            }</font></pre></div><div align="left">callee函数被翻译成汇编后就变成： </div><div align="left"><pre style="padding: 8pt; background: rgb(239, 239, 239) none repeat scroll 0% 50%; font-size: small; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 2em; margin-right: 10%; font-family: -Lucida Sans Typewriter-;"><font size="2">// 函数function1调用<br />              0401C1D    push        2<br />              00401C1F   push        1<br />              00401C21   lea         ecx,[ebp-8]<br />              00401C24   call   function1             注意，这里this没有被入栈<br />              // 函数function2调用<br />              00401C29   push        3<br />              00401C2B   push        2<br />              00401C2D   push        1<br />              00401C2F   push        3<br />              00401C31   lea         eax,[ebp-8]      这里引入this指针<br />              00401C34   push        eax<br />              00401C35   call   function2<br />              00401C3A   add         esp,14h</font></pre></div><div align="left"><font size="2">可见，对于参数个数固定情况下，它类似于stdcall，不定时则类似cdecl</font></div><h2 align="left"> <font size="4">naked call调用规范</font></h2><div align="left">这是一个很少见的调用约定，一般程序设计者建议不要使用。编译器不会给这种函数增加初始化和清理代码，更特殊的是，不能用return返回返回值，只能用插入汇编返回结果。这一般用于实模式驱动程序设计，假设定义一个求和的加法程序，可以定义为： </div><div align="left"><pre style="padding: 8pt; background: rgb(239, 239, 239) none repeat scroll 0% 50%; font-size: small; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 2em; margin-right: 10%; font-family: -Lucida Sans Typewriter-;"><font size="2"> __declspec(naked) <font color="#0000ff">int</font>  add(<font color="#0000ff">int</font> a,<font color="#0000ff">int</font> b)<br />               {<br />                   __asm mov eax,a<br />                   __asm add eax,b<br />                   __asm ret<br />               }</font></pre></div><div align="left">注意，这个函数没有显式的return返回值，返回通过修改eax寄存器实现，而且连退出函数的ret指令都必须显式插入。上面代码被翻译成汇编以后变成： </div><div align="left"><pre style="padding: 8pt; background: rgb(239, 239, 239) none repeat scroll 0% 50%; font-size: small; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 2em; margin-right: 10%; font-family: -Lucida Sans Typewriter-;">  <font size="2"> mov    eax,[ebp+8]<br />   add    eax,[ebp+12]<br />   ret    8</font></pre></div><div align="left">注意这个修饰是和__stdcall及cdecl结合使用的，前面是它和cdecl结合使用的代码，对于和stdcall结合的代码，则变成： </div><div align="left"><pre style="padding: 8pt; background: rgb(239, 239, 239) none repeat scroll 0% 50%; font-size: small; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 2em; margin-right: 10%; font-family: -Lucida Sans Typewriter-;"><font size="2"> __declspec(naked) <font color="#0000ff">int</font> __stdcall function(<font color="#0000ff">int</font> a,<font color="#0000ff">int</font> b)<br />               {<br />                   __asm mov eax,a<br />                   __asm add eax,b<br />                   __asm ret <font color="#ff00ff">8</font><font color="#ff0000">//注意后面的8</font><br />               }</font></pre></div><div align="left">至于这种函数被调用，则和普通的cdecl及stdcall调用函数一致。 </div><h2 align="left"> <font size="4">函数调用约定导致的常见问题</font></h2><div align="left">如果定义的约定和使用的约定不一致，则将导致堆栈被破坏，导致严重问题，下面是两种常见的问题： </div><div align="left"><pre style="padding: 8pt; background: rgb(239, 239, 239) none repeat scroll 0% 50%; font-size: medium; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 2em; margin-right: 10%; font-family: -Lucida Sans Typewriter-;"><font size="2">1) 函数原型声明和函数体定义不一致<br />            2) DLL导入函数时声明了不同的函数约定</font></pre></div></div></div>
		</div>
		<br />
		<br />
<img src ="http://www.cppblog.com/erran/aggbug/34182.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/erran/" target="_blank">erran</a> 2007-10-14 00:33 <a href="http://www.cppblog.com/erran/archive/2007/10/14/34182.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：C++资源之不完全导引（完整版）</title><link>http://www.cppblog.com/erran/archive/2007/10/14/34178.html</link><dc:creator>erran</dc:creator><author>erran</author><pubDate>Sat, 13 Oct 2007 16:14:00 GMT</pubDate><guid>http://www.cppblog.com/erran/archive/2007/10/14/34178.html</guid><wfw:comment>http://www.cppblog.com/erran/comments/34178.html</wfw:comment><comments>http://www.cppblog.com/erran/archive/2007/10/14/34178.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/erran/comments/commentRss/34178.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/erran/services/trackbacks/34178.html</trackback:ping><description><![CDATA[
		<br />
		<table class="fixedTable blogpost" border="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td class="ellipse">
										<span class="bvTitle" id="subjcns!1p5qP-LmQlonNx_ujZCY3OgA!128">
												<strong>
														<font size="3">C++资源之不完全导引（完整版）</font>
												</strong>
										</span>
								</td>
						</tr>
						<tr>
								<td class="bvh8">
										<strong>
												<font size="3">
												</font>
										</strong>
										<br />
								</td>
						</tr>
						<tr>
								<td id="msgcns!1p5qP-LmQlonNx_ujZCY3OgA!128">
										<p>C++资源之不完全导引（完整版）</p>
										<p>来源：<a href="http://www.csdn.net/"><u><font color="#0000ff">www.csdn.net</font></u></a></p>
										<p>撰文：曾毅、陶文</p>
										<p>声明：本文2004年5月首发于《CSDN开发高手》，版权归该杂志与《程序员》杂志社<br />所有。</p>
										<p>------------------------------------------------------------------------<br />--------</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>　　1，前言</p>
		<p>　　无数次听到“我要开始学习C++!”的呐喊，无数次听到“C++太复杂了，我真的<br />学不会”的无奈。Stan Lippman先生曾在《C++ Primer》一书中指出“C++是最为难<br />学的高级程序设计语言之一”，人们常将“之一”去掉以表达自己对C++的敬畏。诚<br />然，C++程序设计语言对于学习者的确有很多难以逾越的鸿沟，体系结构的庞大，应<br />接不暇并不断扩充的特性……除此之外，参考资料之多与冗杂使它的学习者望而却<br />步，欲求深入者苦不堪言。希望这一份不完全导引能够成为您C++学习之路上的引路<br />灯。</p>
		<p>　　撰写本文的初衷并不打算带领大家体验古老的C++历史，如果你想了解C++的历<br />史与其前期发展中诸多技术的演变，你应当去参考Bjarne的《The Design and Evo<br />lution of C++》。当然也不打算给大家一个无所不包的宝典（并非不想：其一是因<br />水平有限，其二无奈C++之博大精深），所给出的仅仅是一些我们认为对于想学习C<br />++的广大读者来说最重要并且触手可及的开发与学习资源。</p>
		<p>　　本文介绍并分析了一些编译器，开发环境，库，少量的书籍以及参考网站，并<br />且尽可能尝试着给出一个利用这些资源的导引，望对如同我们一样的初学者能够有<br />所裨益。</p>
		<p>------------------------------------------------------------------------<br />--------</p>
		<p>　　2，编译器</p>
		<p>　　在C++之外的任何语言中，编译器都从来没有受到过如此之重视。因为C++是一<br />门相当复杂的语言，所以编译器也难于构建。直到最近我们才开始能够使用上完全<br />符合C++标准的编译器（哦，你可能会责怪那些编译器厂商不能尽早的提供符合标准<br />的编译器，这只能怪他们各自维系着自身的一套别人不愿接受的标准）。什么？你<br />说这无关紧要？哦，不，你所需要的是和标准化C++高度兼容的编译环境。长远来看<br />，只有这样的编译器对C++开发人员来说才是最有意义的工具，尤其是对于程序设计<br />语言的学习者。一至性让代码具备可移植性，并让一门语言及其库的应用更为广泛<br />。嗯，是的，我们这里只打算介绍一些公认的优秀编译器。</p>
		<p>　　2.1 Borland C++</p>
		<p>　　这个是Borland C++ Builder和Borland C++ Builder X这两种开发环境的后台<br />编译器。（哦，我之所以将之分为两种开发环境你应当能明白为什么，正如Delphi<br />7到Delphi8的转变，是革命性的两代。）Borland C++由老牌开发工具厂商Borland<br />倾力打造。该公司的编译器素以速度快，空间效率高著称，Borland C++ 系列编译<br />器秉承了这个传统，属于非常优质的编译器。标准化方面早在5.5版本的编译器中对<br />标准化C++的兼容就达到了92.73%。目前最新版本是Borland C++ Builder X中的6.<br />0版本，官方称100%符合ANSI/ISO的C++标准以及C99标准。嗯…这正是我前面所指的<br />“完全符合C++标准的编译器”。</p>
		<p>　　2.2 Visual C++</p>
		<p>　　这个正是我们熟知的Visual Studio 和 Visual Studio.net 2002, 2003以及2<br />005 Whidbey中带的C++编译器。由Microsoft公司研制。在Visual Studio 6.0中，<br />因为编译器有太多地方不能与后来出现的C++标准相吻合而饱受批评（想想你在使用<br />STL的时候编译时报出的那些令人厌恶的error和warning吧）。VC++6.0对标准化C+<br />+的兼容只有83.43%。但是随着C++编译器设计大师Stanley Lippman以及诸多C++社<br />群达人的加盟，在Visual Studio.NET 2003中，Visual C++编译器已经成为一个非<br />常成熟可靠的C++编译器了。Dr.Dobb's Journal的评测显示Visual C++7.1对标准C<br />++的兼容性高达98.22%，一度成为CBX之前兼容性最好的编译器。结合强大的Visua<br />l Studio.NET开发环境，是一个非常不错的选择。至于Whidbey时代的Visual C++,<br />似乎微软所最关注的是C++/CLI……我们不想评论微软下一代的C++编译器对标准化<br />兼容如何，但他确实越来越适合.NET (其实你和我的感觉可能是一样的，微软不应<br />当把标准C++这块肥肉丢给Borland,然而微软可能并不这样认为)。</p>
		<p>　　2.3 GNU C++</p>
		<p>　　著名的开源C++编译器。是类Unix操作系统下编写C++程序的首选。特点是有非<br />常好的移植性，你可以在非常广泛的平台上使用它，同时也是编写跨平台，嵌入式<br />程序很好的选择。另外在符合标准这个方面一直都非常好，GCC3.3大概能够达到96<br />.15%。但是由于其跨平台的特性，在代码尺寸速度等优化上略微差一点。</p>
		<p>　　基于GNU C++的编译器有很多，比如：</p>
		<p>　　(1) Mingw</p>
		<p>　　<a href="http://www.mingw.org/"><u><font color="#0000ff">http://www.mingw.org/</font></u></a></p>
		<p>　　GCC的一个Windows的移植版本（Dev-C++的后台）</p>
		<p>　　(2) Cygwin</p>
		<p>　　<a href="http://sources.redhat.com/cygwin/"><u><font color="#0000ff">http://sources.redhat.com/cygwin/</font></u></a></p>
		<p>　　GCC的另外一个Windows移植版本是Cygwin的一部分，Cygwin是Windows下的一个<br />Unix仿真环境。严格的说是模拟GNU的环境，这也就是"Gnu's Not Unix"要表达的意<br />思，噢，扯远了，这并不是我们在这里关心的实质内容。</p>
		<p>　　(3) Djgpp</p>
		<p>　　<a href="http://www.delorie.com/djgpp/"><u><font color="#0000ff">http://www.delorie.com/djgpp/</font></u></a></p>
		<p>　　这是GCC的DOS移植版本。</p>
		<p>　　(4) RSXNT</p>
		<p>　　<a href="http://www.mathematik.uni-bielefeld.de/%7Erainer/"><u><font color="#0000ff">http://www.mathematik.uni-bielefeld.de/~rainer/</font></u></a></p>
		<p>　　这是GCC的DOS和Windows移植版本。</p>
		<p>　　(5) Intel C++</p>
		<p>　　著名CPU制造厂商Intel出品的编译器，Special Design for Intel x86！对于<br />Intel x86结构的CPU经过特别的优化。在有些应用情况下，特别是数值计算等高性<br />能应用，仅仅采用Intel的编译器编译就能大幅度的提高性能。</p>
		<p>　　(6) Digital Mars C++</p>
		<p>　　网络上提供免费下载，Zortech/Symantec C++的继承者，其前身在当年惨烈的<br />C++四国战中也是主角之一。</p>
		<p>------------------------------------------------------------------------<br />--------</p>
		<p>　　3，开发环境</p>
		<p>　　开发环境对于程序员的作用不言而喻。选择自己朝夕相处的环境也不是容易的<br />事情，特别是在IDE如此丰富的情况下。下面就是我们推荐的一些常见的C++开发环<br />境，并没有包括一些小型的，罕见的IDE。其中任何一款都是功能丰富，可以用作日<br />常开发使用的。对于不同层面的开发者，请参见内文关于适用对象的描述。</p>
		<p>　　3.1 Visual Studio 6.0</p>
		<p>　　这个虽然是Microsoft公司的老版本的开发环境，但是鉴于其后继版本Visual<br />Studio.NET的庞大身躯，以及初学者并不那么高的功能要求，所以推荐这个开发环<br />境给C++的初学者，供其学习C++的最基本的部分，比如C的那部分子集，当然你别指<br />望他能够支持最新的C99标准。在日常的开发中，仍然有很多公司使用这个经典稳定<br />的环境，比如笔者就看曾亲见有些公司将其编译器替换为GCC做手机开发之用。</p>
		<p>　　3.2 Visual Studio.NET 2003</p>
		<p>　　作为Microsoft公司官方正式发布的最新版本开发环境，其中有太多激动人心的<br />功能。结合其最新的C++编译器。对于机器配置比较好的开发人员来说，使用这个开<br />发环境将能满足其大部分的要求。这里不打算单独说Visual Studio Whidbey,虽然<br />Visual Studio .NET 2005 - Whidbey社区预览版已经推出，但暂不是很稳定，读者<br />可以亲身去体验。</p>
		<p>　　3.3 Borland C++ Builder 6</p>
		<p>　　这个并不是Borland的C++开发环境的最新版本。选择它的原因是它不是用Java<br />写的IDE，速度比较快。它有一个很完善的GUI窗体设计器，和Delphi共用一个VCL。<br />由于这些特点，比较适合初学者上手。但是由于其GUI的中心位置，可能不利于对于<br />C++语言的学习。而且其为了支持VCL这个Object Pascal写的库也对C++进行了一些<br />私有的扩充。使得人们有一个不得不接受的事实：“Borland C++ Builder 6的高手<br />几乎都是Delphi高手”。</p>
		<p>　　3.4 Borland C++ Builder X</p>
		<p>　　正如前文所述，虽然版本号上和前面那个IDE非常相象，但是其实它们是完全不<br />同的两个集成开发环境。C++Builder更多的是一个和Delphi同步的C++版本的开发环<br />境，C++BuilderX则是完全从C++的角度思考得出的一个功能丰富的IDE。其最大的特<br />点是跨平台，跨编译器，多种Framework的集成，并且有一个WxWindows为基础的GU<br />I设计器。尤其是采用了纯C++来重写了整个Framework,摒弃了以前令人无奈的版本<br />。对于C++的开发来说，从编译器，到库，到功能集成都是非常理想的。可以预见，<br />Borland C++ Builder X 2.0很值得C++爱好者期待。唯一令人难堪之处是作为一个<br />C++的开发工具，其IDE是用Java写的，在配置不够理想的机器上请慎重考虑再安装<br />。</p>
		<p>　　3.5 Emacs + GCC</p>
		<p>　　前面讲的大部分是Windows环境下的集成开发环境。Linux上的开发者更倾向于<br />使用Emacs来编辑C++的文件，用Makefile来命令GCC做编译。虽然看上去比较松散，<br />但是这些东西综合起来还是一个开0发环境。如果你能够娴熟的使用这样的环境写程<br />序，你的水平应该足够指导我们来写这篇陋文了。</p>
		<p>　　3.6 Dev C++</p>
		<p>　　GCC是一个很好的编译器。在Windows上的C++编译器一直和标准有着一段距离的<br />时候，GCC就是一个让Windows下开发者流口水的编译器。Dev-C++就是能够让GCC跑<br />在Windows下的工具，作为集成开发环境，还提供了同专业IDE相媲美的语法高亮，<br />代码提示，调试等功能。由于使用Delphi开发，占用内存少，速度很快，比较适合<br />轻量级的学习和使用。</p>
		<p>　　3.7 Eclipse + CDT</p>
		<p>　　Eclipse可是近来大名鼎鼎的开发工具。最新一期的Jolt大奖就颁给了这个杰出<br />的神物。说其神奇是因为，它本身是用Java写的，但是拥有比一般Java写的程序快<br />得多的速度。而且因为其基于插件组装一切的原则，使得能够有CDT这样的插件把E<br />clipse变成一个C/C++的开发环境。如果你一直用Eclipse写Java的程序，不妨用它<br />体验一下C++开发的乐趣。</p>
		<p>------------------------------------------------------------------------<br />--------</p>
		<p>　　4，工具</p>
		<p>　　C++的辅助工具繁多，我们分门别类的为大家作介绍：</p>
		<p>　　4.1 文档类</p>
		<p>　　(1) Doxygen</p>
		<p>　　参考站点：<a href="http://www.doxygen.org/"><u><font color="#0000ff">http://www.doxygen.org</font></u></a></p>
		<p>　　Doxygen是一种适合C风格语言（如C++、C、IDL、Java甚至包括C#和PHP）的、<br />开放源码的、基于命令行的文档产生器。</p>
		<p>　　(2) C++2HTML</p>
		<p>　　参考站点：<a href="http://www.bedaux.net/cpp2html/"><u><font color="#0000ff">http://www.bedaux.net/cpp2html/</font></u></a></p>
		<p>　　把C++代码变成语法高亮的HTML</p>
		<p>　　(3) CodeColorizer</p>
		<p>　　参考站点：<a href="http://www.chami.com/colorizer/"><u><font color="#0000ff">http://www.chami.com/colorizer/</font></u></a></p>
		<p>　　它能把好几种语言的源代码着色为HTML</p>
		<p>　　(4) Doc-O-Matic</p>
		<p>　　参考站点：<a href="http://www.doc-o-matic.com/"><u><font color="#0000ff">http://www.doc-o-matic.com/</font></u></a></p>
		<p>　　Doc-O_Matic为你的C/C++，C++.net，Delphi/Pascal, VB.NET，C#和Java程序<br />或者组件产生准确的文档。Doc-O-Matic使用源代码中的符号和注释以及外部的文档<br />文件创建与流行的文档样式一致的文档。</p>
		<p>　　(5) DocVizor</p>
		<p>　　参考站点：<a href="http://www.ucancode.net/Products/DocBuilder/Features.htm"><u><font color="#0000ff">http://www.ucancode.net/Products/DocBuilder/Features.htm</font></u></a></p>
		<p>　　DocVizor满足了面向对象软件开发者的基本要求——它让我们能够看到C++工程<br />中的类层次结构。DocVizor快速地产生完整可供打印的类层次结构图，包括从第三<br />方库中来的那些类，除此之外DocVizor还能从类信息中产生HTML文件。</p>
		<p>　　(6) SourcePublisher C++</p>
		<p>　　参考站点：<a href="http://www.scitools.com/sourcepublisher_c.html"><u><font color="#0000ff">http://www.scitools.com/sourcepublisher_c.html</font></u></a></p>
		<p>　　给源代码产生提供快速直观的HTML报表，包括代码，类层次结构，调用和被调<br />用树，包含和被包含树。支持多种操作系统。</p>
		<p>　　(7) Understand</p>
		<p>　　参考站点：<a href="http://www.scitools.com/ucpp.html"><u><font color="#0000ff">http://www.scitools.com/ucpp.html</font></u></a></p>
		<p>　　分析任何规模的C或者C++工程，帮助我们更好的理解以及编写文档。</p>
		<p>　　4.2 代码类</p>
		<p>　　(1) CC-Rider</p>
		<p>　　参考站点：<a href="http://www.cc-rider.com/"><u><font color="#0000ff">http://www.cc-rider.com</font></u></a></p>
		<p>　　CC-Rider是用于C/C++程序强大的代码可视化工具，通过交互式浏览、编辑及自<br />动文件来促进程序的维持和发展。</p>
		<p>　　(2) CodeInspect</p>
		<p>　　参考站点：<a href="http://www.yokasoft.com/"><u><font color="#0000ff">http://www.yokasoft.com/</font></u></a></p>
		<p>　　一种新的C/C++代码分析工具。它检查我们的源代码找出非标准的，可能的，以<br />及普通的错误代码。</p>
		<p>　　(3) CodeWizard</p>
		<p>　　参考站点：<a href="http://www.parasoft.com/"><u><font color="#0000ff">http://www.parasoft.com</font></u></a></p>
		<p>　　先进的C/C++源代码分析工具，使用超过500个编码规范自动化地标明危险的，<br />但是编译器不能检查到的代码结构。</p>
		<p>　　(4) C++ Validation Test Suites</p>
		<p>　　参考站点：<a href="http://www.plumhall.com/suites.html"><u><font color="#0000ff">http://www.plumhall.com/suites.html</font></u></a></p>
		<p>　　一组用于测试编译器和库对于标准吻合程度的代码库。</p>
		<p>　　(5) CppRefactory</p>
		<p>　　参考站点：<a href="http://cpptool.sourceforge.net/"><u><font color="#0000ff">http://cpptool.sourceforge.net/</font></u></a></p>
		<p>　　CPPRefactory是一个使得开发者能够重构他们的C++代码的程序。目的是使得C<br />++代码的重构能够尽可能的有效率和简单。</p>
		<p>　　(6) Lzz</p>
		<p>　　参考站点：<a href="http://www.lazycplusplus.com/"><u><font color="#0000ff">http://www.lazycplusplus.com/</font></u></a></p>
		<p>　　Lzz是一个自动化许多C++编程中的体力活的工具。它能够节省我们许多事件并<br />且使得编码更加有乐趣。给出一系列的声明，Lzz会给我们创建头文件和源文件。</p>
		<p>　　(7) QA C++ Generation 2000</p>
		<p>　　参考站点：<a href="http://www.programmingresearch.com/solutions/qacpp.htm"><u><font color="#0000ff">http://www.programmingresearch.com/solutions/qacpp.htm</font></u></a></p>
		<p>　　它关注面向对象的C++源代码，对有关于设计，效率，可靠性，可维护性的部分<br />提出警告信息。</p>
		<p>　　(8) s-mail project - Java to C++DOL</p>
		<p>　　参考站点：<a href="http://sadlocha.strefa.pl/s-mail/ja2dol.html"><u><font color="#0000ff">http://sadlocha.strefa.pl/s-mail/ja2dol.html</font></u></a></p>
		<p>　　把Java源代码翻译为相应的C++源代码的命令行工具。</p>
		<p>　　(9) SNIP from Cleanscape Software International</p>
		<p>　　参考站点：<a href="http://www.cleanscape.net/stdprod/snip/index.html"><u><font color="#0000ff">http://www.cleanscape.net/stdprod/snip/index.html</font></u></a></p>
		<p>　　一个填平编码和设计之间沟壑的易于使用的C++开发工具，节省大量编辑和调试<br />的事件，它还使得开发者能够指定设计模式作为对象模型，自动从对象模型中产生<br />C++的类。</p>
		<p>　　(10) SourceStyler C++</p>
		<p>　　参考站点：<a href="http://www.ochresoftware.com/"><u><font color="#0000ff">http://www.ochresoftware.com/</font></u></a></p>
		<p>　　对C/C++源代码提供完整的格式化和排版控制的工具。提供多于75个的格式化选<br />项以及完全支持ANSI C++。</p>
		<p>　　4.3 编译类</p>
		<p>　　(1) Compilercache</p>
		<p>　　参考站点：<a href="http://www.erikyyy.de/compilercache/"><u><font color="#0000ff">http://www.erikyyy.de/compilercache/</font></u></a></p>
		<p>　　Compilercache是一个对你的C和C++编译器的封装脚本。每次我们进行编译，封<br />装脚本，把编译的结果放入缓存，一旦编译相同的东西，结果将从缓存中取出而不<br />是再次编译。</p>
		<p>　　(2) Ccache</p>
		<p>　　参考站点：<a href="http://ccache.samba.org/"><u><font color="#0000ff">http://ccache.samba.org/</font></u></a></p>
		<p>　　Ccache是一个编译器缓存。它使用起来就像C/C++编译器的缓存预处理器，编译<br />速度通常能提高普通编译过程的5~10倍。</p>
		<p>　　(3) Cmm (C++ with MultiMethods)</p>
		<p>　　参考站点：<a href="http://www.op59.net/cmm/cmm-0.28/users.html"><u><font color="#0000ff">http://www.op59.net/cmm/cmm-0.28/users.html</font></u></a></p>
		<p>　　这是一种C++语言的扩展。读入Cmm源代码输出C++的源代码，功能是对C++语言<br />添加了对multimethod的支持。</p>
		<p>　　(4) The Frost Project</p>
		<p>　　参考站点：<a href="http://frost.flewid.de/"><u><font color="#0000ff">http://frost.flewid.de/</font></u></a></p>
		<p>　　Forst使得你能够在C++程序中像原生的C++特性一样使用multimethod以及虚函<br />数参数。它是一个编译器的外壳。</p>
		<p>　　4.4 测试和调试类</p>
		<p>　　(1) CPPUnit</p>
		<p>　　CppUnit 是个基于 LGPL 的开源项目，最初版本移植自 JUnit，是一个非常优<br />秀的开源测试框架。CppUnit 和 JUnit 一样主要思想来源于极限编程。主要功能就<br />是对单元测试进行管理，并可进行自动化测试。</p>
		<p>　　(2) C++Test</p>
		<p>　　参考站点：<a href="http://www.parasoft.com/"><u><font color="#0000ff">http://www.parasoft.com/</font></u></a></p>
		<p>　　C++ Test是一个单元测试工具，它自动化了C和C++类，函数或者组件的测试。</p>
		<p>
				<br />　　(3) Cantata++</p>
		<p>　　参考站点：<a href="http://www.iplbath.com/products/tools/pt400.shtml"><u><font color="#0000ff">http://www.iplbath.com/products/tools/pt400.shtml</font></u></a></p>
		<p>　　设计的目的是为了满足在合理的经济开销下使用这个工具可以让开发工程师开<br />展单元测试和集成测试的需求.</p>
		<p>　　(4) Purify</p>
		<p>　　参考站点：<a href="http://www-900.ibm.com/cn/software/rational/products/purif"><u><font color="#0000ff">http://www-900.ibm.com/cn/software/rational/products/purif</font></u></a><br />yplus/index.shtml</p>
		<p>　　IBM Rational PurifyPlus是一套完整的运行时分析工具，旨在提高应用程序的<br />可靠性和性能。PurifyPlus将内存错误和泄漏检测、应用程序性能描述、代码覆盖<br />分析等功能组合在一个单一、完整的工具包中。</p>
		<p>　　(5) BoundsChecker</p>
		<p>　　BoundsChecker是一个C++运行时错误检测和调试工具。它通过在Visual Studi<br />o内自动化调试过程加速开发并且缩短上市的周期。BoundsChecker提供清楚，详细<br />的程序错误分析，许多是对C++独有的并且在static，stack和heap内存中检测和诊<br />断错误，以及发现内存和资源的泄漏。　　(6) Insure++</p>
		<p>　　参考站点：<a href="http://www.parasoft.com/"><u><font color="#0000ff">http://www.parasoft.com/</font></u></a></p>
		<p>　　一个自动化的运行时程序测试工具，检查难以察觉的错误,如内存覆盖，内存泄<br />漏，内存分配错误，变量初始化错误，变量定义冲突，指针错误，库错误，逻辑错<br />误和算法错误等。</p>
		<p>　　(7) GlowCode</p>
		<p>　　参考站点：<a href="http://www.glowcode.com/"><u><font color="#0000ff">http://www.glowcode.com/</font></u></a></p>
		<p>　　GlowCode包括内存泄漏检查，code profiler，函数调用跟踪等功能。给C++开<br />发者提供完整的错误诊断，和运行时性能分析工具包。</p>
		<p>　　(8) Stack Spy</p>
		<p>　　参考站点：<a href="http://www.imperioustech.com/"><u><font color="#0000ff">http://www.imperioustech.com/</font></u></a></p>
		<p>　　它能捕捉stack corruption, stack over run, stack overflow等有关栈的错<br />误。</p>
		<p>------------------------------------------------------------------------<br />--------</p>
		<p>　　5，库</p>
		<p>　　在C++中，库的地位是非常高的。C++之父 Bjarne Stroustrup先生多次表示了<br />设计库来扩充功能要好过设计更多的语法的言论。现实中，C++的库门类繁多，解决<br />的问题也是极其广泛，库从轻量级到重量级的都有。不少都是让人眼界大开，亦或<br />是望而生叹的思维杰作。由于库的数量非常庞大，而且限于笔者水平，其中很多并<br />不了解。所以文中所提的一些库都是比较著名的大型库。</p>
		<p>　　5.1 标准库</p>
		<p>　　标准库中提供了C++程序的基本设施。虽然C++标准库随着C++标准折腾了许多年<br />，直到标准的出台才正式定型，但是在标准库的实现上却很令人欣慰得看到多种实<br />现，并且已被实践证明为有工业级别强度的佳作。</p>
		<p>　　(1) Dinkumware C++ Library</p>
		<p>　　参考站点：<a href="http://www.dinkumware.com/"><u><font color="#0000ff">http://www.dinkumware.com/</font></u></a></p>
		<p>　　P.J. Plauger编写的高品质的标准库。P.J. Plauger博士是Dr. Dobb's程序设<br />计杰出奖的获得者。其编写的库长期被Microsoft采用，并且最近Borland也取得了<br />其OEM的license，在其C/C++的产品中采用Dinkumware的库。</p>
		<p>　　(2) RogueWave Standard C++ Library</p>
		<p>　　参考站点：<a href="http://www.roguewave.com/"><u><font color="#0000ff">http://www.roguewave.com/</font></u></a></p>
		<p>　　这个库在Borland C++ Builder的早期版本中曾经被采用，后来被其他的库给替<br />换了。笔者不推荐使用。</p>
		<p>　　(3) SGI STL</p>
		<p>　　参考站点：<a href="http://www.roguewave.com/"><u><font color="#0000ff">http://www.roguewave.com/</font></u></a></p>
		<p>　　SGI公司的C++标准模版库。</p>
		<p>　　(4) STLport</p>
		<p>　　参考站点：<a href="http://www.stlport.org/"><u><font color="#0000ff">http://www.stlport.org/</font></u></a></p>
		<p>　　SGI STL库的跨平台可移植版本。</p>
		<p>　　5.2 “准”标准库 - Boost</p>
		<p>　　参考站点：<a href="http://www.boost.org/"><u><font color="#0000ff">http://www.boost.org</font></u></a></p>
		<p>　　国内镜像：<a href="http://www.c-view.org/tech/lib/boost/index.htm"><u><font color="#0000ff">http://www.c-view.org/tech/lib/boost/index.htm</font></u></a></p>
		<p>　　Boost库是一个经过千锤百炼、可移植、提供源代码的C++库，作为标准库的后<br />备，是C++标准化进程的发动机之一。 Boost库由C++标准委员会库工作组成员发起<br />，在C++社区中影响甚大，其成员已近2000人。 Boost库为我们带来了最新、最酷、<br />最实用的技术，是不折不扣的“准”标准库。</p>
		<p>　　Boost中比较有名气的有这么几个库：</p>
		<p>　　Regex</p>
		<p>　　正则表达式库</p>
		<p>　　Spirit</p>
		<p>　　LL parser framework，用C++代码直接表达EBNF</p>
		<p>　　Graph</p>
		<p>　　图组件和算法</p>
		<p>　　Lambda</p>
		<p>　　在调用的地方定义短小匿名的函数对象，很实用的functional功能</p>
		<p>　　concept check</p>
		<p>　　检查泛型编程中的concept</p>
		<p> </p>
		<p>　　Mpl</p>
		<p>　　用模板实现的元编程框架</p>
		<p> </p>
		<p>　　Thread</p>
		<p>　　可移植的C++多线程库</p>
		<p> </p>
		<p>　　Python</p>
		<p>　　把C++类和函数映射到Python之中</p>
		<p>　　Pool</p>
		<p>　　内存池管理</p>
		<p> </p>
		<p>　　smart_ptr</p>
		<p>　　5个智能指针，学习智能指针必读，一份不错的参考是来自CUJ的文章：</p>
		<p>　　Smart Pointers in Boost，哦，这篇文章可以查到，CUJ是提供在线浏览的。<br />中文版见笔者在《Dr. Dobb's Journal软件研发杂志》第7辑上的译文。</p>
		<p>　　Boost总体来说是实用价值很高，质量很高的库。并且由于其对跨平台的强调，<br />对标准C++的强调，是编写平台无关，现代C++的开发者必备的工具。但是Boost中也<br />有很多是实验性质的东西，在实际的开发中实用需要谨慎。并且很多Boost中的库功<br />能堪称对语言功能的扩展，其构造用尽精巧的手法，不要贸然的花费时间研读。Bo<br />ost另外一面，比如Graph这样的库则是具有工业强度，结构良好，非常值得研读的<br />精品代码，并且也可以放心的在产品代码中多多利用。</p>
		<p>　　5.3 GUI</p>
		<p>　　在众多C++的库中，GUI部分的库算是比较繁荣，也比较引人注目的。在实际开<br />发中，GUI库的选择也是非常重要的一件事情，下面我们综述一下可选择的GUI库，<br />各自的特点以及相关工具的支持。</p>
		<p>　　(1) MFC</p>
		<p>　　大名鼎鼎的微软基础类库（Microsoft Foundation Class）。大凡学过VC++的<br />人都应该知道这个库。虽然从技术角度讲，MFC是不大漂亮的，但是它构建于Windo<br />ws API 之上，能够使程序员的工作更容易,编程效率高，减少了大量在建立 Windo<br />ws 程序时必须编写的代码，同时它还提供了所有一般 C++ 编程的优点，例如继承<br />和封装。MFC 编写的程序在各个版本的Windows操作系统上是可移植的，例如，在<br />Windows 3.1下编写的代码可以很容易地移植到 Windows NT 或 Windows 95 上。但<br />是在最近发展以及官方支持上日渐势微。</p>
		<p>　　(2) QT</p>
		<p>　　参考网站：<a href="http://www.trolltech.com/"><u><font color="#0000ff">http://www.trolltech.com/</font></u></a></p>
		<p>　　Qt是Trolltech公司的一个多平台的C++图形用户界面应用程序框架。它提供给<br />应用程序开发者建立艺术级的图形用户界面所需的所用功能。Qt是完全面向对象的<br />很容易扩展，并且允许真正地组件编程。自从1996年早些时候，Qt进入商业领域，<br />它已经成为全世界范围内数千种成功的应用程序的基础。Qt也是流行的Linux桌面环<br />境KDE 的基础，同时它还支持Windows、Macintosh、Unix/X11等多种平台。</p>
		<p>　　(3) WxWindows</p>
		<p>　　参考网站：<a href="http://www.wxwindows.org/"><u><font color="#0000ff">http://www.wxwindows.org/</font></u></a></p>
		<p>　　跨平台的GUI库。因为其类层次极像MFC，所以有文章介绍从MFC到WxWindows的<br />代码移植以实现跨平台的功能。通过多年的开发也是一个日趋完善的GUI库，支持同<br />样不弱于前面两个库。并且是完全开放源代码的。新近的C++ Builder X的GUI设计<br />器就是基于这个库的。</p>
		<p>　　(4) Fox</p>
		<p>　　参考网站：<a href="http://www.fox-toolkit.org/"><u><font color="#0000ff">http://www.fox-toolkit.org/</font></u></a></p>
		<p>　　开放源代码的GUI库。作者从自己亲身的开发经验中得出了一个理想的GUI库应<br />该是什么样子的感受出发，从而开始了对这个库的开发。有兴趣的可以尝试一下。</p>
		<p>
				<br />　　(5) WTL</p>
		<p>　　基于ATL的一个库。因为使用了大量ATL的轻量级手法，模板等技术，在代码尺<br />寸，以及速度优化方面做得非常到位。主要面向的使用群体是开发COM轻量级供网络<br />下载的可视化控件的开发者。</p>
		<p>　　(6) GTK</p>
		<p>　　参考网站：<a href="http://gtkmm.sourceforge.net/"><u><font color="#0000ff">http://gtkmm.sourceforge.net/</font></u></a></p>
		<p>　　GTK是一个大名鼎鼎的C的开源GUI库。在Linux世界中有Gnome这样的杀手应用。<br />而GTK就是这个库的C++封装版本。</p>
		<p>　　5.4 网络通信</p>
		<p>　　(1) ACE</p>
		<p>　　参考网站：<a href="http://www.cs.wustl.edu/%7Eschmidt/ACE.html"><u><font color="#0000ff">http://www.cs.wustl.edu/~schmidt/ACE.html</font></u></a></p>
		<p>　　C++库的代表，超重量级的网络通信开发框架。ACE自适配通信环境（Adaptive<br /> Communication Environment）是可以自由使用、开放源代码的面向对象框架，在<br />其中实现了许多用于并发通信软件的核心模式。ACE提供了一组丰富的可复用C++包<br />装外观（Wrapper Facade）和框架组件，可跨越多种平台完成通用的通信软件任务<br />，其中包括：事件多路分离和事件处理器分派、信号处理、服务初始化、进程间通<br />信、共享内存管理、消息路由、分布式服务动态（重）配置、并发执行和同步，等<br />等。</p>
		<p>　　(2) StreamModule</p>
		<p>　　参考网站：<a href="http://www.omnifarious.org/StrMod/"><u><font color="#0000ff">http://www.omnifarious.org/StrMod/</font></u></a></p>
		<p>　　设计用于简化编写分布式程序的库。尝试着使得编写处理异步行为的程序更容<br />易，而不是用同步的外壳包起异步的本质。</p>
		<p>　　(3) SimpleSocket</p>
		<p>　　参考网站：<a href="http://home.hetnet.nl/%7Elcbokkers/simsock.htm"><u><font color="#0000ff">http://home.hetnet.nl/~lcbokkers/simsock.htm</font></u></a></p>
		<p>　　这个类库让编写基于socket的客户/服务器程序更加容易。</p>
		<p>　　(4) A Stream Socket API for C++</p>
		<p>　　参考网站：<a href="http://www.pcs.cnu.edu/%7Edgame/sockets/socketsC++/sockets.h"><u><font color="#0000ff">http://www.pcs.cnu.edu/~dgame/sockets/socketsC++/sockets.h</font></u></a><br />tml</p>
		<p>　　又一个对Socket的封装库。</p>
		<p>　　5.5 XML</p>
		<p>　　(1) Xerces</p>
		<p>　　参考网站：<a href="http://xml.apache.org/xerces-c/"><u><font color="#0000ff">http://xml.apache.org/xerces-c/</font></u></a></p>
		<p>　　Xerces-C++ 是一个非常健壮的XML解析器，它提供了验证，以及SAX和DOM API<br />。XML验证在文档类型定义(Document Type Definition，DTD)方面有很好的支持，<br />并且在2001年12月增加了支持W3C XML Schema 的基本完整的开放标准。</p>
		<p>　　(2) XMLBooster</p>
		<p>　　参考网站：<a href="http://www.xmlbooster.com/"><u><font color="#0000ff">http://www.xmlbooster.com/</font></u></a></p>
		<p>　　这个库通过产生特制的parser的办法极大的提高了XML解析的速度，并且能够产<br />生相应的GUI程序来修改这个parser。在DOM和SAX两大主流XML解析办法之外提供了<br />另外一个可行的解决方案。</p>
		<p>　　(3) Pull Parser</p>
		<p>　　参考网站：<a href="http://www.extreme.indiana.edu/xgws/xsoap/xpp/"><u><font color="#0000ff">http://www.extreme.indiana.edu/xgws/xsoap/xpp/</font></u></a></p>
		<p>　　这个库采用pull方法的parser。在每个SAX的parser底层都有一个pull的parse<br />r，这个xpp把这层暴露出来直接给大家使用。在要充分考虑速度的时候值得尝试。</p>
		<p>
				<br />　　(4) Xalan</p>
		<p>　　参考网站：<a href="http://xml.apache.org/xalan-c/"><u><font color="#0000ff">http://xml.apache.org/xalan-c/</font></u></a></p>
		<p>　　Xalan是一个用于把XML文档转换为HTML，纯文本或者其他XML类型文档的XSLT处<br />理器。</p>
		<p>　　(5) CMarkup</p>
		<p>　　参考网站：<a href="http://www.firstobject.com/xml.htm"><u><font color="#0000ff">http://www.firstobject.com/xml.htm</font></u></a></p>
		<p>　　这是一种使用EDOM的XML解析器。在很多思路上面非常灵活实用。值得大家在D<br />OM和SAX之外寻求一点灵感。</p>
		<p>　　(6) libxml++</p>
		<p>　　<a href="http://libxmlplusplus.sourceforge.net/"><u><font color="#0000ff">http://libxmlplusplus.sourceforge.net/</font></u></a></p>
		<p>　　libxml++是对著名的libxml XML解析器的C++封装版本</p>
		<p>　　5.6 科学计算</p>
		<p>　　(1) Blitz++</p>
		<p>　　参考网站：<a href="http://www.oonumerics.org/blitz/"><u><font color="#0000ff">http://www.oonumerics.org/blitz/</font></u></a></p>
		<p>　　Blitz++ 是一个高效率的数值计算函数库，它的设计目的是希望建立一套既具<br />像C++ 一样方便，同时又比Fortran速度更快的数值计算环境。通常，用C++所写出<br />的数值程序，比 Fortran慢20%左右，因此Blitz++正是要改掉这个缺点。方法是利<br />用C++的template技术，程序执行甚至可以比Fortran更快。Blitz++目前仍在发展中<br />，对于常见的SVD，FFTs，QMRES等常见的线性代数方法并不提供，不过使用者可以<br />很容易地利用Blitz++所提供的函数来构建。</p>
		<p>　　(2) POOMA</p>
		<p>　　参考网站：<a href="http://www.codesourcery.com/pooma/pooma"><u><font color="#0000ff">http://www.codesourcery.com/pooma/pooma</font></u></a></p>
		<p>　　POOMA是一个免费的高性能的C++库，用于处理并行式科学计算。POOMA的面向对<br />象设计方便了快速的程序开发，对并行机器进行了优化以达到最高的效率，方便在<br />工业和研究环境中使用。</p>
		<p>　　(3) MTL</p>
		<p>　　参考网站：<a href="http://www.osl.iu.edu/research/mtl/"><u><font color="#0000ff">http://www.osl.iu.edu/research/mtl/</font></u></a></p>
		<p>　　Matrix Template Library(MTL)是一个高性能的泛型组件库，提供了各种格式<br />矩阵的大量线性代数方面的功能。在某些应用使用高性能编译器的情况下，比如In<br />tel的编译器，从产生的汇编代码可以看出其与手写几乎没有两样的效能。</p>
		<p>　　(4) CGAL</p>
		<p>　　参考网站：<a href="http://www.cgal.org/"><u><font color="#0000ff">www.cgal.org</font></u></a></p>
		<p>　　Computational Geometry Algorithms Library的目的是把在计算几何方面的大<br />部分重要的解决方案和方法以C++库的形式提供给工业和学术界的用户。</p>
		<p>　　5.7 游戏开发</p>
		<p>　　(1) Audio/Video 3D C++ Programming Library</p>
		<p>　　参考网站：<a href="http://www.galacticasoftware.com/products/av/"><u><font color="#0000ff">http://www.galacticasoftware.com/products/av/</font></u></a></p>
		<p>　　***3D是一个跨平台，高性能的C++库。主要的特性是提供3D图形，声效支持（S<br />B,以及S3M），控制接口（键盘，鼠标和遥感），XMS。</p>
		<p>　　(2) KlayGE</p>
		<p>　　参考网站：<a href="http://home.g365.net/enginedev/"><u><font color="#0000ff">http://home.g365.net/enginedev/</font></u></a></p>
		<p>　　国内游戏开发高手自己用C++开发的游戏引擎。KlayGE是一个开放源代码、跨平<br />台的游戏引擎，并使用Python作脚本语言。KlayGE在LGPL协议下发行。感谢龚敏敏<br />先生为中国游戏开发事业所做出的贡献。</p>
		<p>　　(3) OGRE</p>
		<p>　　参考网站：<a href="http://www.ogre3d.org/"><u><font color="#0000ff">http://www.ogre3d.org</font></u></a></p>
		<p>　　OGRE（面向对象的图形渲染引擎）是用C++开发的，使用灵活的面向对象3D引擎<br />。它的目的是让开发者能更方便和直接地开发基于3D硬件设备的应用程序或游戏。<br />引擎中的类库对更底层的系统库（如：Direct3D和OpenGL）的全部使用细节进行了<br />抽象，并提供了基于现实世界对象的接口和其它类。</p>
		<p>　　5.8 线程</p>
		<p>　　(1) C++ Threads</p>
		<p>　　参考网站：<a href="http://threads.sourceforge.net/"><u><font color="#0000ff">http://threads.sourceforge.net/</font></u></a></p>
		<p>　　这个库的目标是给程序员提供易于使用的类，这些类被继承以提供在Linux环境<br />中很难看到的大量的线程方面的功能。</p>
		<p>　　(2) ZThreads</p>
		<p>　　参考网站：<a href="http://zthread.sourceforge.net/"><u><font color="#0000ff">http://zthread.sourceforge.net/</font></u></a></p>
		<p>　　一个先进的面向对象，跨平台的C++线程和同步库。</p>
		<p>　　5.9 序列化</p>
		<p>　　(1) s11n</p>
		<p>　　参考网站：<a href="http://s11n.net/"><u><font color="#0000ff">http://s11n.net/</font></u></a></p>
		<p>　　一个基于STL的C++库，用于序列化POD，STL容器以及用户定义的类型。</p>
		<p>　　(2) Simple XML Persistence Library</p>
		<p>　　参考网站：<a href="http://sxp.sourceforge.net/"><u><font color="#0000ff">http://sxp.sourceforge.net/</font></u></a></p>
		<p>　　这是一个把对象序列化为XML的轻量级的C++库。</p>
		<p>　　5.10 字符串</p>
		<p>　　(1) C++ Str Library</p>
		<p>　　参考网站：<a href="http://www.utilitycode.com/str/"><u><font color="#0000ff">http://www.utilitycode.com/str/</font></u></a></p>
		<p>　　操作字符串和字符的库，支持Windows和支持gcc的多种平台。提供高度优化的<br />代码，并且支持多线程环境和Unicode，同时还有正则表达式的支持。</p>
		<p>　　(2) Common Text Transformation Library</p>
		<p>　　参考网站：<a href="http://cttl.sourceforge.net/"><u><font color="#0000ff">http://cttl.sourceforge.net/</font></u></a></p>
		<p>　　这是一个解析和修改STL字符串的库。CTTL substring类可以用来比较，插入，<br />替换以及用EBNF的语法进行解析。</p>
		<p>　　(3) GRETA</p>
		<p>　　参考网站：<a href="http://research.microsoft.com/projects/greta/"><u><font color="#0000ff">http://research.microsoft.com/projects/greta/</font></u></a></p>
		<p>　　这是由微软研究院的研究人员开发的处理正则表达式的库。在小型匹配的情况<br />下有非常优秀的表现。</p>
		<p>　　5.11 综合</p>
		<p>　　(1) P::Classes</p>
		<p>　　参考网站：<a href="http://pclasses.com/"><u><font color="#0000ff">http://pclasses.com/</font></u></a></p>
		<p>　　一个高度可移植的C++应用程序框架。当前关注类型和线程安全的signal/slot<br />机制，i/o系统包括基于插件的网络协议透明的i/o架构，基于插件的应用程序消息<br />日志框架，访问sql数据库的类等等。</p>
		<p>　　(2) ACDK - Artefaktur Component Development Kit</p>
		<p>　　参考网站：<a href="http://acdk.sourceforge.net/"><u><font color="#0000ff">http://acdk.sourceforge.net/</font></u></a></p>
		<p>　　这是一个平台无关的C++组件框架，类似于Java或者.NET中的框架（反射机制，<br />线程，Unicode，废料收集，I/O，网络，实用工具，XML，等等），以及对Java, P<br />erl, Python, TCL, Lisp, COM 和 CORBA的集成。</p>
		<p>　　(3) dlib C++ library</p>
		<p>　　参考网站：<a href="http://www.cis.ohio-state.edu/%7Ekingd/dlib/"><u><font color="#0000ff">http://www.cis.ohio-state.edu/~kingd/dlib/</font></u></a></p>
		<p>　　各种各样的类的一个综合。大整数，Socket，线程，GUI，容器类,以及浏览目<br />录的API等等。</p>
		<p>　　(4) Chilkat C++ Libraries</p>
		<p>　　参考网站：<a href="http://www.chilkatsoft.com/cpp_libraries.asp"><u><font color="#0000ff">http://www.chilkatsoft.com/cpp_libraries.asp</font></u></a></p>
		<p>　　这是提供zip，e-mail，编码，S/MIME，XML等方面的库。</p>
		<p>　　(5) C++ Portable Types Library (PTypes)</p>
		<p>　　参考网站：<a href="http://www.melikyan.com/ptypes/"><u><font color="#0000ff">http://www.melikyan.com/ptypes/</font></u></a></p>
		<p>　　这是STL的比较简单的替代品，以及可移植的多线程和网络库。</p>
		<p>　　(6) LFC</p>
		<p>　　参考网站：<a href="http://lfc.sourceforge.net/"><u><font color="#0000ff">http://lfc.sourceforge.net/</font></u></a></p>
		<p>　　哦，这又是一个尝试提供一切的C++库</p>
		<p>　　5.12 其他库</p>
		<p>　　(1) Loki</p>
		<p>　　参考网站：<a href="http://www.moderncppdesign.com/"><u><font color="#0000ff">http://www.moderncppdesign.com/</font></u></a></p>
		<p>　　哦，你可能抱怨我早该和Boost一起介绍它，一个实验性质的库。作者在loki中<br />把C++模板的功能发挥到了极致。并且尝试把类似设计模式这样思想层面的东西通过<br />库来提供。同时还提供了智能指针这样比较实用的功能。</p>
		<p>　　(2) ATL</p>
		<p>　　ATL(Active Template Library)</p>
		<p>　　是一组小巧、高效、灵活的类，这些类为创建可互操作的COM组件提供了基本的<br />设施。</p>
		<p>　　(3) FC++: The Functional C++ Library</p>
		<p>　　这个库提供了一些函数式语言中才有的要素。属于用库来扩充语言的一个代表<br />作。如果想要在OOP之外寻找另一分的乐趣，可以去看看函数式程序设计的世界。大<br />师Peter Norvig在 “Teach Yourself Programming in Ten Years”一文中就将函<br />数式语言列为至少应当学习的6类编程语言之一。</p>
		<p>　　(4) FACT!</p>
		<p>　　参考网站：<a href="http://www.kfa-juelich.de/zam/FACT/start/index.html"><u><font color="#0000ff">http://www.kfa-juelich.de/zam/FACT/start/index.html</font></u></a></p>
		<p>　　另外一个实现函数式语言特性的库</p>
		<p>　　(5) Crypto++</p>
		<p>　　提供处理密码，消息验证，单向hash，公匙加密系统等功能的免费库。</p>
		<p>　　还有很多非常激动人心或者是极其实用的C++库，限于我们的水平以及文章的篇<br />幅不能包括进来。在对于这些已经包含近来的库的介绍中，由于并不是每一个我们<br />都使用过，所以难免有偏颇之处，请读者见谅。</p>
		<p>------------------------------------------------------------------------<br />--------</p>
		<p>　　6，书籍</p>
		<p>　　以前熊节先生曾撰文评论相对于Java程序设计语言，C++的好书多如牛毛。荣耀<br />先生在《程序员》杂志上撰文《C++程序设计之四书五经》也将本领域内几乎所有的<br />经典书籍作了全面的介绍,任何关于书的评论此时看来便是很多余的了。个人浅见，<br />除非你打算以C++作为唯一兴趣或者生存之本，一般读者确实没有足够的时间和必要<br />将20余本书籍全部阅读。更有参考价值的是荣耀先生的另一篇文章：《至少应该阅<br />读的九本C++著作》，可以从下面的地址浏览到此文：</p>
		<p>　　<a href="http://www.royaloo.com/articles/articles_2003/9CppBooks.htm"><u><font color="#0000ff">http://www.royaloo.com/articles/articles_2003/9CppBooks.htm</font></u></a></p>
		<p>　　下面几本书对于走在C++初学之路上的读者是我们最愿意推荐给大家的：</p>
		<p>　　(1) 《C++ Primer》</p>
		<p>　　哦，也许你会抱怨我们为什么不先介绍TCPL,但对于走在学习之路上的入门者，<br />本书内容更为全面，更为详细易懂，我们称它为“C++的超级宝典”并不过分。配有<br />一本不错的习题解答《C++ Primer Answer Book》可以辅助你的学习之路。</p>
		<p>　　(2) 《Essential C++》</p>
		<p>　　如果说《C++ Primer》是C++领域的超级宝典，那么此书作为掌握C++的大局观<br />当之无愧。正如《.NET大局观》一书能够让读者全揽.NET，本书讲述了C++中最核心<br />的全部主题。书虽不厚，内容精炼，不失为《C++ Primer》读者茶余饭后的主题回<br />顾之作。</p>
		<p>　　(3) 《The C++ Programming Language》</p>
		<p>　　Bjarne为你带来的C++教程，真正能够告诉你怎么用才叫真正的C++的唯一一本<br />书。虽然如同“某某程序设计语言”这样的书籍会给大家一个内容全揽，入门到精<br />通的感觉，但本书确实不太适合初学者阅读。如果你自认为是一名很有经验的C++程<br />序员，那至少也要反复咀嚼Bjarne先生所强调的若干内容。</p>
		<p>　　(4) 《Effective C++》，《More Effective C++》</p>
		<p>　　是的，正如一些C++爱好者经常以读过与没有读过上述两本作品来区分你是否是<br />C++高手。我们也极力推崇这两本著作。在各种介绍C++专家经验的书籍里面，这两<br />本是最贴近语言本质，看后最能够有脱胎换骨感觉的书，读此书你需每日三省汝身<br />。</p>
		<p>　　技术书籍仁者见仁，过多的评论反无太多意义，由读者喜好选择最适合自己的<br />书方为上策。</p>
		<p>------------------------------------------------------------------------<br />--------</p>
		<p>　　7，资源网站</p>
		<p>　　正如我们可以通过计算机历史上的重要人物了解计算机史的发展，C++相关人物<br />的网站也可以使我们得到最有价值的参考与借鉴，下面的人物我们认为没有介绍的<br />必要，只因下面的人物在C++领域的地位众所周知，我们只将相关的资源进行罗列以<br />供读者学习，他们有的工作于贝尔实验室，有的工作于知名编译器厂商，有的在不<br />断推进语言的标准化，有的为读者撰写了多部千古奇作……<br />　　(1) Bjarne Stroustrup<br />　　<a href="http://www.research.att.com/%7Ebs/"><u><font color="#0000ff">http://www.research.att.com/~bs/</font></u></a></p>
		<p>　　(2) Stanley B. Lippman<br />　　<a href="http://blogs.msdn.com/slippman/"><u><font color="#0000ff">http://blogs.msdn.com/slippman/</font></u></a><br />　　中文版 <a href="http://www.zengyihome.net/slippman/index.htm"><u><font color="#0000ff">http://www.zengyihome.net/slippman/index.htm</font></u></a></p>
		<p>　　(3) Scott Meyers<br />　　<a href="http://www.aristeia.com/"><u><font color="#0000ff">http://www.aristeia.com/</font></u></a></p>
		<p>　　(4) David Musser<br />　　<a href="http://www.cs.rpi.edu/%7Emusser/"><u><font color="#0000ff">http://www.cs.rpi.edu/~musser/</font></u></a></p>
		<p>　　(5) Bruce Eckel<br />　　<a href="http://www.bruceeckel.com/"><u><font color="#0000ff">http://www.bruceeckel.com</font></u></a></p>
		<p>　　(6) Nicolai M. Josuttis<br />　　<a href="http://www.josuttis.com/"><u><font color="#0000ff">http://www.josuttis.com/</font></u></a></p>
		<p>　　(7) Herb Sutter<br />　　<a href="http://www.gotw.ca/"><u><font color="#0000ff">http://www.gotw.ca/</font></u></a></p>
		<p>　　(8) Andrei Alexandrescu<br />　　<a href="http://www.coderncppdesign.com/"><u><font color="#0000ff">http://www.coderncppdesign.com/</font></u></a></p>
		<p>　　(9) 侯捷先生<br />　　<a href="http://www.jjhou.com/"><u><font color="#0000ff">http://www.jjhou.com</font></u></a></p>
		<p>　　(10) 孟岩先生<br />　　先生繁忙于工作，痴迷于技术，暂无个人主页，关于先生的作品可以通过CSDN<br />的专栏和侯先生的主页访问到。</p>
		<p>　　(11) 荣耀先生<br />　　<a href="http://www.royaloo.com/"><u><font color="#0000ff">http://www.royaloo.com/</font></u></a></p>
		<p>　　(12) 潘爱民先生<br />　　<a href="http://www.icst.pku.edu.cn/panaimin/pam_homepage.htm"><u><font color="#0000ff">http://www.icst.pku.edu.cn/panaimin/pam_homepage.htm</font></u></a></p>
		<p>　　除了上述大师的主页外，以下的综合类C++学习参考站点是我们非常愿意向大家<br />推荐的：</p>
		<p>　　(1) CodeProject<br />　　<a href="http://www.codeproject.com/"><u><font color="#0000ff">http://www.codeproject.com</font></u></a></p>
		<p>　　(2) CodeGuru<br />　　<a href="http://www.codeguru.com/"><u><font color="#0000ff">http://www.codeguru.com</font></u></a></p>
		<p>　　(3) Dr. Dobb's Journal<br />　　<a href="http://www.ddj.com/"><u><font color="#0000ff">http://www.ddj.com</font></u></a></p>
		<p>　　(4) C/C++ Users Journal<br />　　<a href="http://www.cuj.com/"><u><font color="#0000ff">http://www.cuj.com</font></u></a></p>
		<p>　　(5) C维视点<br />　　<a href="http://www.c-view.org/"><u><font color="#0000ff">http://www.c-view.org</font></u></a></p>
		<p>　　(6) allaboutprogram<br />　　<a href="http://www.allaboutprogram.com/"><u><font color="#0000ff">http://www.allaboutprogram.com</font></u></a><br />　　其他资料</p>
		<p>　　(1) ISO IEC JTC1/SC22/WG21 - C++：标准C++的权威参考<br />　　<a href="http://anubis.dkuug.dk/jtc1/sc22/wg21/"><u><font color="#0000ff">http://anubis.dkuug.dk/jtc1/sc22/wg21/</font></u></a></p>
		<p>　　(2) C++ FAQ LITE — Frequently Asked Questions: 最为全面的C++FAQ<br />　　<a href="http://www.sunistudio.com/cppfaq/index.html"><u><font color="#0000ff">http://www.sunistudio.com/cppfaq/index.html</font></u></a><br />　　C/C++ 新闻组：<br />　　你不妨尝试从这里提问和回答问题，很多不错的Q&amp;A资源......</p>
		<p>　　(1) .alt.comp.lang.learn.c-c++<br />　　这个简单些，如果你和我一样是个菜鸟</p>
		<p>　　(2) .comp.lang.c++.moderated<br />    嗯，这个显然水平高一些</p>
		<p>　　(3) .comp.std.c++<br />　　如果你需要讨论标准C++相关话题的话</p>
		<p>------------------------------------------------------------------------<br />--------</p>
		<p>　　8，不得不写的结束语</p>
		<p>　　结束的时候也是总结现状，展望未来的时候。虽然C++从脱胎于C开始，一路艰<br />难坎坷的走过来，但是无论如何C++已经取得了工业基础的地位。文章列举的大量相关<br />资源就是最好的证明，而业界的大量用C++写成的产品代码以及大量的C++职业工程<br />师则是最直接的证明。同时，我们可以看到各个高校的计算机专业都开设有C++这门<br />课程，网络上对于C++的学习讨论也从来都没有停过。但是，在Java和.NET两大企业<br />开发平台的围攻下，给人的感觉是C++越来越“不行”了。</p>
		<p>　　C++在面向企业的软件开发中，在开发便捷性等方面的确要比Java和C#差很多，<br />其中一个问题是C++语言本身比较复杂，学习曲线比较陡峭，另外一个问题是C++标<br />准化的时间太长，丧失了很多的壮大机会，耗费了很多精力在厂商的之间的斗争上<br />，而C++的标准库离一个完善的程序开发框架还缺少太多太多的内容，各个第三方的<br />类库和框架又在一致性和完整性上没法和随平台提供的框架相提并论。难道C++真的<br />要退出历史舞台了？</p>
		<p>　　从C++目前的活跃程度，以及应用现状来说是完全能够肯定C++仍然是软件工业<br />的基础，也不会退出历史舞台的。另外从Boost，Loki这些库中我们也能够看到C++<br />的发展非常活跃，对于新技术新思维非常激进，C++仍然广泛受到关注。从ACE在高<br />性能通信领域的应用，以及MTL这样的库在数值计算领域的出色表现，我们可以看到<br />C++在高性能应用场合下的不可替代的作用，而嵌入式系统这样的内存受限开发平台<br />，比如Symbian OS上，C++已经发挥着并且将发挥更大的作用。可以预见的是以后的<br />软件无论上层的应用怎么变，它的底层核心都会是由C/C++这样的系统级软件编写的<br />，比如Java虚拟机，.NET Framwork。因为只有这样的系统级软件才能完全彻底的发<br />挥机器的功能。</p>
		<p>　　需要看到的是两个趋势，一个趋势是C++变得更加复杂，更加学院派，通过模板<br />等有潜力的语法因素构造越来越精巧的库成为了现代C++的热点，虽然在利用库实现<br />新的编程范式，乃至设计模式等方面很有开创意义，也确实产生了一些能够便捷开<br />发的工具，但是更多的是把C++变得更加强大，更加复杂，也更加难懂，似乎也更加<br />学院派，不得不说它正在向边缘化道路发展。另一个趋势是C++在主流的企业应用开<br />发中已经逐渐退出了，ERP这样的企业软件开发中基本上不会考虑C++，除非需要考<br />虑性能或者和遗留代码的集成这些因素。C++退守到系统级别语言，成为软件工业的<br />基础是大势所趋。然而反思一下，真的是退守么？自从STL出现，无数的人风起云涌<br />的开始支持C++,他们狂呼“我看到深夜消失了，目标软件工程的出现。我看到了可<br />维护的代码。”是的，STL在可维护性下做得如此出色。但是又怎样呢？STL为C++铺<br />平了现代软件工程的道路，而在上层应用程序软件开发领域这块场地早不单独属于<br />C++,很多程序设计语言都做得很出色，疯狂的支持者会毫不犹豫地说我们应当支持<br />C++,因为它是世界上最棒的语言。而坦率地说，你的腰杆真的那么硬么？也许只是<br />在逃避一些事实。C++是优秀的，这不可否认，STL的出现让C++一度走上了最辉煌的<br />时刻，然而现在看来……我的一位恩师曾言：真正能够将STL应用得淋漓尽致的人很<br />保守地说国内也不超过200人，或许不加入STL能够使C++向着它应当发展的方向发展<br />的更好，而现在看来，C++也应当回首到真正属于他的那一片圣地上……</p>
		<br />
<img src ="http://www.cppblog.com/erran/aggbug/34178.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/erran/" target="_blank">erran</a> 2007-10-14 00:14 <a href="http://www.cppblog.com/erran/archive/2007/10/14/34178.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：C++的4种类型转换 </title><link>http://www.cppblog.com/erran/archive/2007/10/13/34150.html</link><dc:creator>erran</dc:creator><author>erran</author><pubDate>Sat, 13 Oct 2007 13:27:00 GMT</pubDate><guid>http://www.cppblog.com/erran/archive/2007/10/13/34150.html</guid><wfw:comment>http://www.cppblog.com/erran/comments/34150.html</wfw:comment><comments>http://www.cppblog.com/erran/archive/2007/10/13/34150.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/erran/comments/commentRss/34150.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/erran/services/trackbacks/34150.html</trackback:ping><description><![CDATA[
		<font face="Arial">
				<font size="2">原文：http://blog.csdn.net/stanleyrprose/archive/2006/01/25/588083.aspx<br />作者：<br /></font>
				<br />
				<br />
				<b>C++的4种类型转换 </b>
				<br />
				<br />
				<br />
				<strong>一、C 风格（C-style）强制转型如下：</strong>
		</font>
		<p>
				<font face="Arial">    (T) expression // cast expression to be of type T <br />    函数风格（Function-style）强制转型使用这样的语法：<br />    T(expression) // cast expression to be of type T <br />    这两种形式之间没有本质上的不同，它纯粹就是一个把括号放在哪的问题。我把这两种形式称为旧风格（old-style）的强制转型。 </font>
		</p>
		<p>
				<font face="Arial">
						<strong>   二、 C++的四种强制转型形式：</strong>
				</font>
		</p>
		<p>
				<font face="Arial">　　C++ 同时提供了四种新的强制转型形式（通常称为新风格的或 C++ 风格的强制转型）： <br />　　const_cast(expression) <br />　　dynamic_cast(expression) <br />　　reinterpret_cast(expression) <br />　　static_cast(expression) </font>
		</p>
		<p>
				<font face="Arial">　　每一种适用于特定的目的： </font>
		</p>
		<p>
				<font face="Arial">　　·dynamic_cast 主要用于执行“安全的向下转型（safe downcasting）”，也就是说，要确定一个对象是否是一个继承体系中的一个特定类型。它是唯一不能用旧风格语法执行的强制转型，也是唯一可能有重大运行时代价的强制转型。<br />    <br />   
·static_cast 可以被用于强制隐型转换（例如，non-const 对象转型为 const 对象，int 转型为
double，等等），它还可以用于很多这样的转换的反向转换（例如，void*
指针转型为有类型指针，基类指针转型为派生类指针），但是它不能将一个 const 对象转型为 non-const 对象（只有
const_cast 能做到），它最接近于C-style的转换。<br />    <br />　　·const_cast 一般用于强制消除对象的常量性。它是唯一能做到这一点的 C++ 风格的强制转型。 </font>
		</p>
		<p>
				<font face="Arial">　　·reinterpret_cast 是特意用于底层的强制转型，导致实现依赖（implementation-dependent）（就是说，不可移植）的结果，例如，将一个指针转型为一个整数。这样的强制转型在底层代码以外应该极为罕见。<br />　　<br />　
　旧风格的强制转型依然合法，但是新的形式更可取。首先，在代码中它们更容易识别（无论是人还是像 grep
这样的工具都是如此），这样就简化了在代码中寻找类型系统被破坏的地方的过程。第二，更精确地指定每一个强制转型的目的，使得编译器诊断使用错误成为可
能。例如，如果你试图使用一个 const_cast 以外的新风格强制转型来消除常量性，你的代码将无法编译。 </font>
		</p>
		<p>
				<font face="Arial">==  <br /><strong>==  dynamic_cast .vs. static_cast</strong><br />==</font>
		</p>
		<div class="Code">
				<p>
						<font face="Arial">class B { ... };<br />class D : public B { ... };</font>
				</p>
				<p>
						<font face="Arial">void f(B* pb)<br />{<br />   D* pd1 = dynamic_cast&lt;D*&gt;(pb);<br />   D* pd2 = static_cast&lt;D*&gt;(pb);<br />}</font>
				</p>
				<p>
						<font face="Arial">If
pb really points to an object of type D, then pd1 and pd2 will get the
same value. They will also get the same value if pb == 0. </font>
				</p>
				<p>
						<font face="Arial">If pb
points to an object of type B and not to the complete D class, then
dynamic_cast will know enough to return zero. However, static_cast
relies on the programmer’s assertion that pb points to an object of
type D and simply returns a pointer to that supposed D object.</font>
				</p>
		</div>
		<p>
				<font face="Arial">   
即dynamic_cast可用于继承体系中的向下转型，即将基类指针转换为派生类指针，比static_cast更严格更安全。
dynamic_cast在执行效率上比static_cast要差一些,但static_cast在更宽上范围内可以完成映射,这种不加限制的映射伴随
着不安全性.static_cast覆盖的变换类型除类层次的静态导航以外,还包括无映射变换,窄化变换(这种变换会导致对象切片,丢失信息),用
VOID*的强制变换,隐式类型变换等...</font>
		</p>
		<p>
				<font face="Arial">
						<br />==<br /><strong>==  static_cast .vs. reinterpret_cast</strong><br />==</font>
		</p>
		<p>
				<font face="Arial">    reinterpret_cast是为了映射到一个完全不同类型的意思,这个关键词在我们需要把类型映射回原有类型时用到它.我们映射到的类型仅仅是为了故弄玄虚和其他目的,这是所有映射中最危险的.(这句话是C++编程思想中的原话)</font>
		</p>
		<p>
				<font face="Arial">   
static_cast 和 reinterpret_cast 操作符修改了操作数类型. 它们不是互逆的; static_cast
在编译时使用类型信息执行转换, 在转换执行必要的检测(诸如指针越界计算, 类型检查). 其操作数相对是安全的. 另一方面,
reinterpret_cast 仅仅是重新解释了给出的对象的比特模型而没有进行二进制转换, 例子如下:</font>
		</p>
		<p>
				<font face="Arial">    int n=9; double d=static_cast &lt; double &gt; (n); </font>
		</p>
		<p>
				<font face="Arial">   
上面的例子中, 我们将一个变量从 int 转换到 double. 这些类型的二进制表达式是不同的. 要将整数 9 转换到 双精度整数 9,
static_cast 需要正确地为双精度整数 d 补足比特位. 其结果为 9.0. 而reinterpret_cast 的行为却不同: </font>
		</p>
		<p>
				<font face="Arial">    int n=9;<br />    double d=reinterpret_cast&lt;double &amp; &gt; (n); </font>
		</p>
		<p>
				<font face="Arial">    这次, 结果有所不同. 在进行计算以后, d 包含无用值. 这是因为 reinterpret_cast 仅仅是复制 n 的比特位到 d, 没有进行必要的分析. <br /></font>
		</p>
		<font face="Arial">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=588083</font>
<img src ="http://www.cppblog.com/erran/aggbug/34150.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/erran/" target="_blank">erran</a> 2007-10-13 21:27 <a href="http://www.cppblog.com/erran/archive/2007/10/13/34150.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：堆和栈的区别 </title><link>http://www.cppblog.com/erran/archive/2007/10/13/34148.html</link><dc:creator>erran</dc:creator><author>erran</author><pubDate>Sat, 13 Oct 2007 13:12:00 GMT</pubDate><guid>http://www.cppblog.com/erran/archive/2007/10/13/34148.html</guid><wfw:comment>http://www.cppblog.com/erran/comments/34148.html</wfw:comment><comments>http://www.cppblog.com/erran/archive/2007/10/13/34148.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/erran/comments/commentRss/34148.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/erran/services/trackbacks/34148.html</trackback:ping><description><![CDATA[
		<br />
		<a href="http://kb.csdn.net/.net/Articles/200605/80f93200-6a0c-4e21-82d8-4212844da589.html" target="_blank">参见http://kb.csdn.net/.net/Articles/200605/80f93200-6a0c-4e21-82d8-4212844da589.html</a>
		<br />
		<br />
		<br />堆和栈的区别 
<br /><br /><br />一般认为在c中分为这几个存储区 
<br />1栈 - 有编译器自动分配释放 
<br />2堆 - 一般由程序员分配释放，若程序员不释放，程序结束时可能由OS回收 
<br />3全局区（静态区），全局变量和静态变量的存储是放在一块的，初始化的全局变量和静 
<br />态变量在一块区域，未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 
<br />- 程序结束释放 
<br />4另外还有一个专门放常量的地方。 - 程序结束释放 
<br />在函数体中定义的变量通常是在栈上，用malloc, calloc, realloc等分配内存的函数分 
<br />配得到的就是在堆上。在所有函数体外定义的是全局量，加了static修饰符后不管在哪 
<br />里都存放在全局区（静态区）,在所有函数体外定义的static变量表示在该文件中有效， 
<br />不能extern到别的文件用，在函数体内定义的static表示只在该函数体内有效。另外， 
<br />函数中的"adgfdf"这样的字符串存放在常量区。 
<br />比如： 
<br />int a = 0; 全局初始化区 
<br />char *p1; 全局未初始化区 
<br />main() 
<br />{ 
<br />int b; 栈 
<br />char s[] = "abc";栈 
<br />char *p2; 栈 
<br />char *p3 = "123456"; 123456\0在常量区，p3在栈上。 
<br />static int c =0； 全局（静态）初始化区 
<br />p1 = (char *)malloc(10); 
<br />p2 = (char *)malloc(20); 
<br />分配得来得10和20字节的区域就在堆区。 
<br />strcpy(p1, "123456"); 123456\0放在常量区，编译器可能会将它与p3所指向的"12345 
<br />6"优化成一块。 
<br />} 
<br />还有就是函数调用时会在栈上有一系列的保留现场及传递参数的操作。 
<br />栈的空间大小有限定，vc的缺省是2M。栈不够用的情况一般是程序中分配了大量数组和 
<br />递归函数层次太深。有一点必须知道，当一个函数调用完返回后它会释放该函数中所有 
<br />的栈空间。栈是由编译器自动管理的，不用你操心。 
<br />堆是动态分配内存的，并且你可以分配使用很大的内存。但是用不好会产生内存泄漏。 
<br />并且频繁地malloc和free会产生内存碎片（有点类似磁盘碎片），因为c分配动态内存时 
<br />是寻找匹配的内存的。而用栈则不会产生碎片。 
<br />在栈上存取数据比通过指针在堆上存取数据快些。 
<br />一般大家说的堆栈和栈是一样的，就是栈(stack)，而说堆时才是堆heap. 
<br />栈是先入后出的，一般是由高地址向低地址生长。 
<br /><br /><br />堆(heap)和栈(stack)是C/C++编程不可避免会碰到的两个基本概念。<br />首先，这两个概念都可以在讲数据结构的书中找到，他们都是基本的数据结构，虽然栈更为简单一些。在具体的C/C++编程框架中，这两个概念并不是并行的。对底层机器代码的研究可以揭示，栈是机器系统提供的数据结构，而堆则是C/C++函数库提供的。 具体地说，现代计算机(串行执行机制)，都直接在代码底层支持栈的数据结构。这体现在，有专门的寄存器指向栈所在的地址，有专门的机器指令完成数据入栈出栈的操作。 

这种机制的特点是效率高，支持的数据有限，一般是整数，指针，浮点数等系统直接支 持的数据类型，并不直接支持其他的数据结构。因为栈的这种特点，对栈的使用在程序中是非常频繁的。对子程序的调用就是直接利用栈完成的。机器的call指令里隐含了把返回地址推入栈，然后跳转至子程序地址的操作，而子程序中的ret指令则隐含从堆栈中弹出返回地址并跳转之的操作。C/C++中的自动变量是直接利用栈的例子，这也就是为什么当函数返回时，该函数的自动变量自动失效的原因(因为 颜换指戳说饔们暗 状态)。 

和栈不同，堆的数据结构并不是由系统(无论是机器系统还是操作系统)支持的，而是由函数库提供的。基本的malloc/realloc/free函数维护了一套内部的堆数据结构。当程序使用这些函数去获得新的内存空间时，这套函数首先试图从内部堆中寻找可用的内存空间，如果没有可以使用的内存空间，则试图利用系统调用来动态增加程序数据段的内存大小，新分配得到的空间首先被组织进内部堆中去，然后再以适当的形式返回给调用者。当程序释放分配的内存空间时，这片内存空间被返回内部堆结构中，可能会被适当的处理(比如和其他空闲空间合并成更大的空闲空间)，以更适合下一次内存分配申请。<br />这套复杂的分配机制实际上相当于一个内存分配的缓冲池(Cache)，使用这套机制有如下若干原因： 
<br />1. 系统调用可能不支持任意大小的内存分配。有些系统的系统调用只支持固定大小及其倍数的内存请求(按页分配)；这样的话对于大量的小内存分类来说会造成浪费。<br />2. 系统调用申请内存可能是代价昂贵的。系统调用可能涉及用户态和核心态的转换。
<br />3. 没有管理的内存分配在大量复杂内存的分配释放操作下很容易造成内存碎片。 

<br /><br />堆和栈的对比 

从以上知识可知，栈是系统提供的功能，特点是快速高效，缺点是有限制，数据不灵活；而栈是函数库提供的功能，特点是灵活方便，数据适应面广泛，但是效率有一定降低。栈是系统数据结构，对于进程/线程是唯一的；堆是函数库内部数据结构，不一定唯一。不同堆分配的内存无法互相操作。栈空间分静态分配和动态分配两种。静态分配是编译器完成的，比如自动变量(auto)的分配。动态分配由alloca函数完成。栈的动态分配无需释放(是自动的)，也就没有释放函数。为可移植的程序起见，栈的动态分配操作是不被鼓励的！堆空间的分配总是动态的，虽然程序结束时所有的数据空间都会被释放回系统，但是精确的申请内存/释放内存匹配是良好程序的基本要素。 

<br />所以计算机中的堆和栈经常时放一块讲的
<br />nod 一般不是必要就不要动态创建，最讨厌把new出来的东西当局部变量用，<br />用万了马上delete 的做法.<br /><br /> 理由<br /> 1.栈分配比堆快，只需要一条指令就呢给配所有的局部变量 
<br />2.栈不会出现内存碎片 
<br />3。栈对象好管理 

<br /><br />当然，某些情况下也要那么写,比如 
<br />1.对象很大 
<br />2.对象需要在某个特定的时刻构造或析够 
<br />3.类只允许对象动态创建,比如VCL的大多数类 

当然，必须用堆对象时也不能躲避<br /> <br /><a href="http://kb.csdn.net/.net/Articles/200605/80f93200-6a0c-4e21-82d8-4212844da589.html" target="_blank">http://kb.csdn.net/.net/Articles/200605/80f93200-6a0c-4e21-82d8-4212844da589.html</a><img src ="http://www.cppblog.com/erran/aggbug/34148.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/erran/" target="_blank">erran</a> 2007-10-13 21:12 <a href="http://www.cppblog.com/erran/archive/2007/10/13/34148.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++中成员函数的重载、覆盖与隐藏</title><link>http://www.cppblog.com/erran/archive/2007/10/13/34128.html</link><dc:creator>erran</dc:creator><author>erran</author><pubDate>Sat, 13 Oct 2007 09:52:00 GMT</pubDate><guid>http://www.cppblog.com/erran/archive/2007/10/13/34128.html</guid><wfw:comment>http://www.cppblog.com/erran/comments/34128.html</wfw:comment><comments>http://www.cppblog.com/erran/archive/2007/10/13/34128.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/erran/comments/commentRss/34128.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/erran/services/trackbacks/34128.html</trackback:ping><description><![CDATA[稍微懂得点oop的人都知道重载，那是多态性的重要体现！可是在c++中你能分清成员函数的重载、覆盖吗？这个好像也不难，重载存在与同一个类中，而覆盖存在于派生类于基类中！可是如果再加上隐藏呢？说实话，以前我从来没有听说过这个概念！也不知道自己曾经捏造的程序，出了多少问题！看看林锐在《高质量c++编程指南》中的解释。
<h2><font size=2><span><span><br>&nbsp;&nbsp;&nbsp; </span></span><span>成员函数的重载、覆盖（<span>override</span>）与隐藏很容易混淆，<span>C++</span>程序员必须要搞清楚概念，否则错误将防不胜防。<span> </h2>
<p></span></span></font></p>
<p><span>
<p><font size=2>&nbsp;</font></p>
</span>
<p>&#160;</p>
<p><font size=2><chsdate w:st="on" isrocdate="False" islunardate="False" day="30" month="12" year="1899"><strong><span>8.2.1</span></strong></chsdate><strong><span> </span></strong><strong><span>重载与覆盖<span>
<p></span></span></strong></font></p>
<p><font size=2><span><span>&nbsp;&nbsp;&nbsp; </span></span><span>成员函数被重载的特征：<span>
<p></span></span></font></p>
<p><span><font size=2>（<span>1</span>）相同的范围（在同一个类中）；<span>
<p></span></font></span></p>
<p><span><font size=2>（<span>2</span>）函数名字相同；<span>
<p></span></font></span></p>
<p><span><font size=2>（<span>3</span>）参数不同；<span>
<p></span></font></span></p>
<p><font size=2><span>（<span>4</span>）<span>virtual</span>关键字可有可无。</span><span>
<p></span></font></p>
<p><font size=2><span><span>&nbsp;&nbsp;&nbsp; </span></span><strong><span>覆盖是指派生类函数覆盖基类函数，特征是：<span>
<p></span></span></strong></font></p>
<p><strong><span><font size=2>（<span>1</span>）不同的范围（分别位于派生类与基类）；<span>
<p></span></font></span></strong></p>
<p><strong><span><font size=2>（<span>2</span>）函数名字相同；<span>
<p></span></font></span></strong></p>
<p><strong><span><font size=2>（<span>3</span>）参数相同；<span>
<p></span></font></span></strong></p>
<p><strong><span><font size=2>（<span>4</span>）基类函数必须有<span>virtual</span>关键字。<span>
<p></span></font></span></strong></p>
<p><font size=2><span><span>&nbsp;&nbsp;&nbsp; </span></span><span>示例<chsdate w:st="on" isrocdate="False" islunardate="False" day="1" month="2" year="2008"><span>8-2-1</span></chsdate>中，函数<span>Base::f(int)</span>与<span>Base::f(float)</span>相互重载，而<span>Base::g(void)</span>被<span>Derived::g(void)</span>覆盖。<span>
<p></span></span></font></p>
<p><span>
<p><font size=2>&nbsp;</font></p>
</span>
<p>&#160;</p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=574>
            <p><span><font size=2>#include &lt;iostream.h&gt;
            <p></font></span></p>
            <p><span><font size=2><span>&nbsp;&nbsp;&nbsp; </span>class Base
            <p></font></span></p>
            <p><span><font size=2>{
            <p></font></span></p>
            <p><span><font size=2>public:
            <p></font></span></p>
            <p><span><font size=2><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&nbsp;void f(int x){ cout &lt;&lt; "Base::f(int) " &lt;&lt; x &lt;&lt; endl; }
            <p></font></span></p>
            <p><span><font size=2>void f(float x){ cout &lt;&lt; "Base::f(float) " &lt;&lt; x &lt;&lt; endl; }
            <p></font></span></p>
            <p><span><font size=2><span>&nbsp;&nbsp;&nbsp; </span>&nbsp;virtual void g(void){ cout &lt;&lt; "Base::g(void)" &lt;&lt; endl;}
            <p></font></span></p>
            <p><span><font size=2>};
            <p></font></span></p>
            <p><span>
            <p><font size=2>&nbsp;</font></p>
            </span>
            <p>&#160;</p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=574>
            <p><span><font size=2><span>&nbsp;&nbsp;&nbsp; </span>class Derived : public Base
            <p></font></span></p>
            <p><span><font size=2>{
            <p></font></span></p>
            <p><span><font size=2>public:
            <p></font></span></p>
            <p><span><font size=2><span>&nbsp;&nbsp;&nbsp; </span>&nbsp;<strong><span>virtual</span></strong> void g(void){ cout &lt;&lt; "Derived::g(void)" &lt;&lt; endl;}
            <p></font></span></p>
            <p><span><font size=2>};
            <p></font></span></p>
            <p><span>
            <p><font size=2>&nbsp;</font></p>
            </span>
            <p>&#160;</p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=574>
            <p><span><font size=2><span>&nbsp;&nbsp;&nbsp; </span>void main(void)
            <p></font></span></p>
            <p><span><font size=2><span>&nbsp;&nbsp;&nbsp; </span>{
            <p></font></span></p>
            <p><span><font size=2><span>&nbsp;&nbsp;&nbsp; </span>&nbsp;Derived&nbsp;d;
            <p></font></span></p>
            <p><span><font size=2><span>&nbsp;&nbsp;&nbsp; </span>&nbsp;Base *pb = &amp;d;
            <p></font></span></p>
            <p><span><font size=2><span>&nbsp;&nbsp;&nbsp; </span>&nbsp;pb-&gt;f(42); <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>// Base::f(int) 42
            <p></font></span></p>
            <p><span><font size=2><span>&nbsp;&nbsp;&nbsp; </span>&nbsp;pb-&gt;f(<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="3.14" unitname="F">3.14f</chmetcnv>); <span>&nbsp;&nbsp;&nbsp; </span>// Base::f(float) 3.14
            <p></font></span></p>
            <p><span><font size=2><span>&nbsp;&nbsp;&nbsp; </span>&nbsp;pb-&gt;g(); <span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;</span>// Derived::g(void)
            <p></font></span></p>
            <p><span><font size=2>}
            <p></font></span></p>
            </td>
        </tr>
    </tbody>
</table>
<p align=center><span><font size=2>示例<chsdate w:st="on" isrocdate="False" islunardate="False" day="1" month="2" year="2008"><span>8-2-1</span></chsdate>成员函数的重载和覆盖<span>
<p></span></font></span></p>
<p><span><font size=2><span>&nbsp;&nbsp;&nbsp; </span>
<p></font></span></p>
<p><font size=2><chsdate w:st="on" isrocdate="False" islunardate="False" day="30" month="12" year="1899"><strong><span>8.2.2</span></strong></chsdate><strong><span> </span></strong><strong><span>令人迷惑的隐藏规则</span></strong></font></p>
<p><font size=2><strong></strong></font><font size=2><span><span>&nbsp;&nbsp;&nbsp; </span></span><span>本来仅仅区别重载与覆盖并不算困难，但是<span>C++</span>的隐藏规则使问题复杂性陡然增加。这里&#8220;隐藏&#8221;是指派生类的函数屏蔽了与其同名的基类函数，规则如下：<span>
<p></span></span></font></p>
<p><strong><span><font size=2>（<span>1</span>）如果派生类的函数与基类的函数同名，但是参数不同。此时，不论有无<span>virtual</span>关键字，基类的函数将被隐藏（注意别与重载混淆）。<span>
<p></span></font></span></strong></p>
<p><font size=2><strong><span>（<span>2</span>）如果派生类的函数与基类的函数同名，并且参数也相同，但是基类函数没有<span>virtual</span>关键字。此时，基类的函数被隐藏（注意别与覆盖混淆）。</span></strong><span>
<p></span></font></p>
<p><font size=2><span><span>&nbsp;&nbsp;&nbsp; </span></span><span>示例程序<chsdate w:st="on" isrocdate="False" islunardate="False" day="2" month="2" year="2008"><span>8-2-2</span></chsdate>（<span>a</span>）中：<span>
<p></span></span></font></p>
<p><span><font size=2>（<span>1</span>）函数<span>Derived::f(float)</span>覆盖了<span>Base::f(float)</span>。<span>
<p></span></font></span></p>
<p><span><font size=2>（<span>2</span>）函数<span>Derived::g(int)</span>隐藏了<span>Base::g(float)</span>，而不是重载。<span>
<p></span></font></span></p>
<p><span><font size=2>（<span>3</span>）函数<span>Derived::h(float)</span>隐藏了<span>Base::h(float)</span>，而不是覆盖。<span>
<p></span></font></span></p>
<p><span>
<p><font size=2>&nbsp;</font></p>
</span>
<p>&#160;</p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=581>
            <p><span><font size=2>#include &lt;iostream.h&gt;
            <p></font></span></p>
            <p><span><font size=2><span>&nbsp;&nbsp;&nbsp; </span>class Base
            <p></font></span></p>
            <p><span><font size=2>{
            <p></font></span></p>
            <p><span><font size=2>public:
            <p></font></span></p>
            <p><span><font size=2><span>&nbsp;&nbsp;&nbsp; </span>virtual<span> </span>void f(float x){ cout &lt;&lt; "Base::f(float) " &lt;&lt; x &lt;&lt; endl; }
            <p></font></span></p>
            <p><span><font size=2>void g(float x){ cout &lt;&lt; "Base::g(float) " &lt;&lt; x &lt;&lt; endl; }
            <p></font></span></p>
            <p><span><font size=2><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>void h(float x){ cout &lt;&lt; "Base::h(float) " &lt;&lt; x &lt;&lt; endl; }
            <p></font></span></p>
            <p><span><font size=2>};
            <p></font></span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=581>
            <p><span><font size=2><span>&nbsp;&nbsp;&nbsp; </span>class Derived : public Base
            <p></font></span></p>
            <p><span><font size=2>{
            <p></font></span></p>
            <p><span><font size=2>public:
            <p></font></span></p>
            <p><span><font size=2><span>&nbsp;&nbsp;&nbsp; </span>virtual<span> </span>void f(float x){ cout &lt;&lt; "Derived::f(float) " &lt;&lt; x &lt;&lt; endl; }
            <p></font></span></p>
            <p><span><font size=2>void g(int x){ cout &lt;&lt; "Derived::g(int) " &lt;&lt; x &lt;&lt; endl; }
            <p></font></span></p>
            <p><span><font size=2><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>void h(float x){ cout &lt;&lt; "Derived::h(float) " &lt;&lt; x &lt;&lt; endl; }
            <p></font></span></p>
            <p><span><font size=2>};
            <p></font></span></p>
            </td>
        </tr>
    </tbody>
</table>
<p align=center><span><font size=2>示例<chsdate w:st="on" isrocdate="False" islunardate="False" day="2" month="2" year="2008"><span>8-2-2</span></chsdate>（<span>a</span>）成员函数的重载、覆盖和隐藏<span>
<p></span></font></span></p>
<p><span>
<p><font size=2>&nbsp;</font></p>
</span>
<p>&#160;</p>
<p><font size=2><span><span>&nbsp;&nbsp;&nbsp; </span></span><span>据作者考察，很多<span>C++</span>程序员没有意识到有&#8220;隐藏&#8221;这回事。由于认识不够深刻，&#8220;隐藏&#8221;的发生可谓神出鬼没，常常产生令人迷惑的结果。<span>
<p></span></span></font></p>
<p><span><font size=2>示例<chsdate w:st="on" isrocdate="False" islunardate="False" day="2" month="2" year="2008"><span>8-2-2</span></chsdate>（<span>b</span>）中，<span>pb</span>和<span>pd</span>指向同一地址，按理说运行结果应该是相同的，可事实并非这样。<span>
<p></span></font></span></p>
<p><span>
<p><font size=2>&nbsp;</font></p>
</span>
<p>&#160;</p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=560>
            <p><span><font size=2>void main(void)
            <p></font></span></p>
            <p><span><font size=2>{
            <p></font></span></p>
            <p><span><font size=2>Derived&nbsp;d;
            <p></font></span></p>
            <p><span><font size=2>Base *pb = &amp;d;
            <p></font></span></p>
            <p><span><font size=2>Derived *pd = &amp;d;
            <p></font></span></p>
            <p><span><font size=2>// Good : behavior depends solely on type of the object
            <p></font></span></p>
            <p><span><font size=2>pb-&gt;f(<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="3.14" unitname="F">3.14f</chmetcnv>);<span> </span>// Derived::f(float) 3.14
            <p></font></span></p>
            <p><span><font size=2>pd-&gt;f(<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="3.14" unitname="F">3.14f</chmetcnv>);<span> </span>// Derived::f(float) 3.14
            <p></font></span></p>
            <p><span>
            <p><font size=2>&nbsp;</font></p>
            </span>
            <p>&#160;</p>
            <p><span><font size=2>// Bad : behavior depends on type of the pointer
            <p></font></span></p>
            <p><span><font size=2>pb-&gt;g(<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="3.14" unitname="F">3.14f</chmetcnv>);<span> </span>// Base::g(float) 3.14
            <p></font></span></p>
            <p><span><font size=2>pd-&gt;g(<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="3.14" unitname="F">3.14f</chmetcnv>);<span> </span>// Derived::g(int) 3<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>(surprise!)
            <p></font></span></p>
            <p><span>
            <p><font size=2>&nbsp;</font></p>
            </span>
            <p>&#160;</p>
            <p><span><font size=2>// Bad : behavior depends on type of the pointer
            <p></font></span></p>
            <p><span><font size=2>pb-&gt;h(<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="3.14" unitname="F">3.14f</chmetcnv>);<span> </span>// Base::h(float) 3.14<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>(surprise!)
            <p></font></span></p>
            <p><span><font size=2>pd-&gt;h(<chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="3.14" unitname="F">3.14f</chmetcnv>);<span> </span>// Derived::h(float) 3.14
            <p></font></span></p>
            <p><span><font size=2>}
            <p></font></span></p>
            </td>
        </tr>
    </tbody>
</table>
<p align=center><font size=2><span>示例<chsdate w:st="on" isrocdate="False" islunardate="False" day="2" month="2" year="2008"><span>8-2-2</span></chsdate>（<span>b</span>） 重载、覆盖和隐藏的比较</span><span>
<p></span></font></p>
<p><font size=2><chsdate w:st="on" isrocdate="False" islunardate="False" day="30" month="12" year="1899"><strong><span>8.2.3</span></strong></chsdate><strong><span> </span></strong><strong><span>摆脱隐藏<span>
<p></span></span></strong></font></p>
<p><font size=2><span><span>&nbsp;&nbsp;&nbsp; </span></span><span>隐藏规则引起了不少麻烦。示例<chsdate w:st="on" isrocdate="False" islunardate="False" day="3" month="2" year="2008"><span>8-2-3</span></chsdate>程序中，语句<span>pd-&gt;f(10)</span>的本意是想调用函数<span>Base::f(int)</span>，但是<span>Base::f(int)</span>不幸被<span>Derived::f(char *)</span>隐藏了。由于数字<span>10</span>不能被隐式地转化为字符串，所以在编译时出错。<span>
<p></span></span></font></p>
<p><span>
<p><font size=2>&nbsp;</font></p>
</span>
<p>&#160;</p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=567>
            <p><span><font size=2>class Base
            <p></font></span></p>
            <p><span><font size=2>{
            <p></font></span></p>
            <p><span><font size=2>public:
            <p></font></span></p>
            <p><span><font size=2>void f(int x);
            <p></font></span></p>
            <p><span><font size=2>};
            <p></font></span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=567>
            <p><span><font size=2>class Derived : public Base
            <p></font></span></p>
            <p><span><font size=2>{
            <p></font></span></p>
            <p><span><font size=2>public:
            <p></font></span></p>
            <p><span><font size=2>void f(char *str);
            <p></font></span></p>
            <p><span><font size=2>};
            <p></font></span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=567>
            <p><span><font size=2>void Test(void)
            <p></font></span></p>
            <p><span><font size=2>{
            <p></font></span></p>
            <p><span><font size=2>Derived *pd = new Derived;
            <p></font></span></p>
            <p><span><font size=2>pd-&gt;f(10);<span>&nbsp;&nbsp;&nbsp; </span>// error
            <p></font></span></p>
            <p><span><font size=2>}
            <p></font></span></p>
            </td>
        </tr>
    </tbody>
</table>
<p align=center><font size=2><span>示例<chsdate w:st="on" isrocdate="False" islunardate="False" day="3" month="2" year="2008"><span>8-2-3</span></chsdate><span> </span>由于隐藏而导致错误</span><span>
<p></span></font></p>
<p><span>
<p><font size=2>&nbsp;</font></p>
</span>
<p>&#160;</p>
<p><font size=2><span><span>&nbsp;&nbsp;&nbsp; </span></span><span>从示例<chsdate w:st="on" isrocdate="False" islunardate="False" day="3" month="2" year="2008"><span>8-2-3</span></chsdate>看来，隐藏规则似乎很愚蠢。但是隐藏规则至少有两个存在的理由：<span>
<p></span></span></font></p>
<p><font size=2><span><span>u<span Times New Roman??>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>写语句<span>pd-&gt;f(10)</span>的人可能真的想调用<span>Derived::f(char *)</span>函数，只是他误将参数写错了。有了隐藏规则，编译器就可以明确指出错误，这未必不是好事。否则，编译器会静悄悄地将错就错，程序员将很难发现这个错误，流下祸根。<span>
<p></span></span></font></p>
<p><font size=2><span><span>u<span Times New Roman??>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>假如类<span>Derived</span>有多个基类（多重继承），有时搞不清楚哪些基类定义了函数<span>f</span>。如果没有隐藏规则，那么<span>pd-&gt;f(10)</span>可能会调用一个出乎意料的基类函数<span>f</span>。尽管隐藏规则看起来不怎么有道理，但它的确能消灭这些意外。<span>
<p></span></span></font></p>
<p><span>
<p><font size=2>&nbsp;</font></p>
</span>
<p>&#160;</p>
<p><span><font size=2>示例<chsdate w:st="on" isrocdate="False" islunardate="False" day="3" month="2" year="2008"><span>8-2-3</span></chsdate>中，如果语句<span>pd-&gt;f(10)</span>一定要调用函数<span>Base::f(int)</span>，那么将类<span>Derived</span>修改为如下即可。<span>
<p></span></font></span></p>
<p><span><font size=2>class Derived : public Base
<p></font></span></p>
<p><span><font size=2>{
<p></font></span></p>
<p><span><font size=2>public:
<p></font></span></p>
<p><span><font size=2>void f(char *str);
<p></font></span></p>
<p><span><font size=2>void f(int x) { Base::f(x); }
<p></font></span></p>
<p><span><font size=2>};
<p></font></span></p>
<img src ="http://www.cppblog.com/erran/aggbug/34128.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/erran/" target="_blank">erran</a> 2007-10-13 17:52 <a href="http://www.cppblog.com/erran/archive/2007/10/13/34128.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：C++类库介绍</title><link>http://www.cppblog.com/erran/archive/2007/10/13/34119.html</link><dc:creator>erran</dc:creator><author>erran</author><pubDate>Sat, 13 Oct 2007 08:42:00 GMT</pubDate><guid>http://www.cppblog.com/erran/archive/2007/10/13/34119.html</guid><wfw:comment>http://www.cppblog.com/erran/comments/34119.html</wfw:comment><comments>http://www.cppblog.com/erran/archive/2007/10/13/34119.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/erran/comments/commentRss/34119.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/erran/services/trackbacks/34119.html</trackback:ping><description><![CDATA[
		<p style="font-size: 10pt; font-family: Arial;">原文：<a href="http://hi.baidu.com/chplj/blog/item/08d8f6368def16310a55a931.html">http://hi.baidu.com/chplj/blog/item/08d8f6368def16310a55a931.html</a><br />作者：<br /><br /><strong>C++类库介绍</strong><br /><br /><br />再次体现了C++保持核心语言的效率同时大力发展应用库的发展趋势!!在C++中，库的地位是非常高的。C++之父 Bjarne Stroustrup先生多次表示了设计库来扩充功能要好过设计更多的语法的言论。现实中，C++的库门类繁多，解决的问题也是极其广泛，库从轻量级到重量级的都有。不少都是让人眼界大开，亦或是望而生叹的思维杰作。由于库的数量非常庞大，而且限于笔者水平，其中很多并不了解。所以文中所提的一些库都是比较著名的大型库。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">
				<strong>标准库 </strong>
		</p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">标准库中提供了C++程序的基本设施。虽然C++标准库随着C++标准折腾了许多年，直到标准的出台才正式定型，但是在标准库的实现上却很令人欣慰得看到多种实现，并且已被实践证明为有工业级别强度的佳作。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">1、 Dinkumware C++ Library </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考站点：http://www.dinkumware.com</p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">P.J. Plauger编写的高品质的标准库。P.J. Plauger博士是Dr. Dobb's程序设计杰出奖的获得者。其编写的库长期被Microsoft采用，并且最近Borland也取得了其OEM的license，在其C/C+ +的产品中采用Dinkumware的库。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">2、 RogueWave Standard C++ Library </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考站点：http://www.roguewave.com/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">这个库在Borland C++ Builder的早期版本中曾经被采用，后来被其他的库给替换了。笔者不推荐使用。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">3、SGI STL </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考站点：http://www.roguewave.com/<br />　SGI公司的C++标准模版库。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">4、STLport </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考站点：http://www.stlport.org/<br />　SGI STL库的跨平台可移植版本。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">准标准库——Boost </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Boost 库是一个经过千锤百炼、可移植、提供源代码的C++库，作为标准库的后备，是C++标准化进程的发动机之一。 Boost库由C++标准委员会库工作组成员发起，在C++社区中影响甚大，其成员已近2000人。 Boost库为我们带来了最新、最酷、最实用的技术，是不折不扣的"准"标准库。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Boost中比较有名气的有这么几个库： <br /><br />　Regex <br />　正则表达式库 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Spirit <br />　LL parser framework，用C++代码直接表达EBNF </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Graph <br />　图组件和算法 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Lambda <br />　在调用的地方定义短小匿名的函数对象，很实用的functional功能 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">concept check <br />　检查泛型编程中的concept </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Mpl <br />　用模板实现的元编程框架 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Thread <br />　可移植的C++多线程库 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Python <br />　把C++类和函数映射到Python之中 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Pool <br />　内存池管理 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">smart_ptr <br />　5个智能指针，学习智能指针必读，一份不错的参考是来自CUJ的文章： </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Smart Pointers in Boost,哦，这篇文章可以查到，CUJ是提供在线浏览的。中文版见笔者在《Dr. Dobb's Journal软件研发杂志》第7辑上的译文。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Boost 总体来说是实用价值很高，质量很高的库。并且由于其对跨平台的强调，对标准C++的强调，是编写平台无关，现代C++的开发者必备的工具。但是Boost 中也有很多是实验性质的东西，在实际的开发中实用需要谨慎。并且很多Boost中的库功能堪称对语言功能的扩展，其构造用尽精巧的手法，不要贸然的花费时间研读。Boost另外一面，比如Graph这样的库则是具有工业强度，结构良好，非常值得研读的精品代码，并且也可以放心的在产品代码中多多利用。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考站点：http://www.boost.org（国内镜像：http://www.c-view.org/tech/lib/boost/index.htm） </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">GUI </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">在众多C++的库中，GUI部分的库算是比较繁荣，也比较引人注目的。在实际开发中，GUI库的选择也是非常重要的一件事情，下面我们综述一下可选择的GUI库，各自的特点以及相关工具的支持。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">1、 MFC </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">大名鼎鼎的微软基础类库（Microsoft Foundation Class）。大凡学过VC++的人都应该知道这个库。虽然从技术角度讲，MFC是不大漂亮的，但是它构建于Windows API 之上，能够使程序员的工作更容易,编程效率高，减少了大量在建立 Windows 程序时必须编写的代码，同时它还提供了所有一般 C++ 编程的优点，例如继承和封装。MFC 编写的程序在各个版本的Windows操作系统上是可移植的，例如，在 Windows 3.1下编写的代码可以很容易地移植到 Windows NT 或 Windows 95 上。但是在最近发展以及官方支持上日渐势微。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">2、 QT </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://www.trolltech.com<br />Qt 是Trolltech公司的一个多平台的C++图形用户界面应用程序框架。它提供给应用程序开发者建立艺术级的图形用户界面所需的所用功能。Qt是完全面向对象的很容易扩展，并且允许真正地组件编程。自从1996年早些时候，Qt进入商业领域，它已经成为全世界范围内数千种成功的应用程序的基础。Qt也是流行的Linux桌面环境KDE 的基础，同时它还支持Windows、Macintosh、Unix/X11等多种平台。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">3、WxWindows </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://www.wxwindows.org/</p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">跨平台的GUI库。因为其类层次极像MFC，所以有文章介绍从MFC到WxWindows的代码移植以实现跨平台的功能。通过多年的开发也是一个日趋完善的 GUI库，支持同样不弱于前面两个库。并且是完全开放源代码的。新近的C++ Builder X的GUI设计器就是基于这个库的。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">4、Fox </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">开放源代码的GUI库。作者从自己亲身的开发经验中得出了一个理想的GUI库应该是什么样子的感受出发，从而开始了对这个库的开发。有兴趣的可以尝试一下。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://www.fox-toolkit.org/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">5、 WTL </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">基于ATL的一个库。因为使用了大量ATL的轻量级手法，模板等技术，在代码尺寸，以及速度优化方面做得非常到位。主要面向的使用群体是开发COM轻量级供网络下载的可视化控件的开发者。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">6、 GTK </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://gtkmm.sourceforge.net/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">GTK是一个大名鼎鼎的C的开源GUI库。在Linux世界中有Gnome这样的杀手应用。而GTK就是这个库的C++封装版本。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">网络通信库</p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">ACE </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://www.cs.wustl.edu/~schmidt/ACE.html <br />　ACE网络编程开发论坛：http://www.acejoy.com</p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">C+ +库的代表，超重量级的网络通信开发框架。ACE自适配通信环境（Adaptive Communication Environment）是可以自由使用、开放源代码的面向对象框架，在其中实现了许多用于并发通信软件的核心模式。ACE提供了一组丰富的可复用C++ 包装外观（Wrapper Facade）和框架组件，可跨越多种平台完成通用的通信软件任务，其中包括：事件多路分离和事件处理器分派、信号处理、服务初始化、进程间通信、共享内存管理、消息路由、分布式服务动态（重）配置、并发执行和同步，等等。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">StreamModule </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://www.omnifarious.org/StrMod/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">设计用于简化编写分布式程序的库。尝试着使得编写处理异步行为的程序更容易，而不是用同步的外壳包起异步的本质。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">SimpleSocket </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://home.hetnet.nl/~lcbokkers/simsock.htm </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">这个类库让编写基于socket的客户/服务器程序更加容易。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">A Stream Socket API for C++ <br /><br />　参考网站：http://www.pcs.cnu.edu/~dgame/sockets/socketsC++/sockets.html </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">又一个对Socket的封装库。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">XML </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Xerces </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://xml.apache.org/xerces-c/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Xerces-C++ 是一个非常健壮的XML解析器，它提供了验证，以及SAX和DOM API。XML验证在文档类型定义(Document Type Definition，DTD)方面有很好的支持，并且在2001年12月增加了支持W3C XML Schema 的基本完整的开放标准。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">XMLBooster </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://www.xmlbooster.com/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">这个库通过产生特制的parser的办法极大的提高了XML解析的速度，并且能够产生相应的GUI程序来修改这个parser。在DOM和SAX两大主XML解析办法之外提供了另外一个可行的解决方案。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Pull Parser </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://www.extreme.indiana.edu/xgws/xsoap/xpp/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">这个库采用pull方法的parser。在每个SAX的parser底层都有一个pull的parser，这个xpp把这层暴露出来直接给大家使用。在要充分考虑速度的时候值得尝试。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Xalan </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://xml.apache.org/xalan-c/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Xalan是一个用于把XML文档转换为HTML，纯文本或者其他XML类型文档的XSLT处理器。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">CMarkup </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://www.firstobject.com/xml.htm <br /><br />　这是一种使用EDOM的XML解析器。在很多思路上面非常灵活实用。值得大家在DOM和SAX之外寻求一点灵感。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">libxml++ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">http://libxmlplusplus.sourceforge.net/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">libxml++是对著名的libxml XML解析器的C++封装版本 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">科学计算 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Blitz++ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://www.oonumerics.org/blitz/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Blitz++ 是一个高效率的数值计算函数库，它的设计目的是希望建立一套既具像C++ 一样方便，同时又比Fortran速度更快的数值计算环境。通常，用C++所写出的数值程序，比 Fortran慢20%左右，因此Blitz++正是要改掉这个缺点。方法是利用C++的template技术，程序执行甚至可以比Fortran更快。 Blitz++目前仍在发展中，对于常见的SVD，FFTs，QMRES等常见的线性代数方法并不提供，不过使用者可以很容易地利用Blitz++所提供的函数来构建。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">POOMA </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://www.codesourcery.com/pooma/pooma </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">POOMA是一个免费的高性能的C++库，用于处理并行式科学计算。POOMA的面向对象设计方便了快速的程序开发，对并行机器进行了优化以达到最高的效率，方便在工业和研究环境中使用。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">MTL </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://www.osl.iu.edu/research/mtl/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Matrix Template Library(MTL)是一个高性能的泛型组件库，提供了各种格式矩阵的大量线性代数方面的功能。在某些应用使用高性能编译器的情况下，比如Intel的编译器，从产生的汇编代码可以看出其与手写几乎没有两样的效能。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">CGAL <br /><br />　参考网站：www.cgal.org </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Computational Geometry Algorithms Library的目的是把在计算几何方面的大部分重要的解决方案和方法以C++库的形式提供给工业和学术界的用户。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">游戏开发 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Audio/Video 3D C++ Programming Library </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://www.galacticasoftware.com/products/av/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">AV3D是一个跨平台，高性能的C++库。主要的特性是提供3D图形，声效支持（SB,以及S3M），控制接口（键盘，鼠标和遥感），XMS。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">KlayGE </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://home.g365.net/enginedev/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">国内游戏开发高手自己用C++开发的游戏引擎。KlayGE是一个开放源代码、跨平台的游戏引擎，并使用Python作脚本语言。KlayGE在LGPL协议下发行。感谢龚敏敏先生为中国游戏开发事业所做出的贡献。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">OGRE </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://www.ogre3d.org </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">OGRE （面向对象的图形渲染引擎）是用C++开发的，使用灵活的面向对象3D引擎。它的目的是让开发者能更方便和直接地开发基于3D硬件设备的应用程序或游戏。引擎中的类库对更底层的系统库（如：Direct3D和OpenGL）的全部使用细节进行了抽象，并提供了基于现实世界对象的接口和其它类。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">线程 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">C++ Threads </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://threads.sourceforge.net/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">这个库的目标是给程序员提供易于使用的类，这些类被继承以提供在Linux环境中很难看到的大量的线程方面的功能。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">ZThreads </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://zthread.sourceforge.net/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">一个先进的面向对象，跨平台的C++线程和同步库。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">序列化 <br />　s11n <br />　参考网站：http://s11n.net/ <br />　一个基于STL的C++库，用于序列化POD，STL容器以及用户定义的类型。 <br />　Simple XML Persistence Library <br />　参考网站：http://sxp.sourceforge.net/ <br />　这是个把对象序列化为XML的轻量级的C++库。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">字符串 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">C++ Str Library </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://www.utilitycode.com/str/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">操作字符串和字符的库，支持Windows和支持gcc的多种平台。提供高度优化的代码，并且支持多线程环境和Unicode，同时还有正则表达式的支持。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Common Text Transformation Library </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://cttl.sourceforge.net/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">这是一个解析和修改STL字符串的库。CTTL substring类可以用来比较，插入，替换以及用EBNF的语法进行解析。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">GRETA </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://research.microsoft.com/projects/greta/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">这是由微软研究院的研究人员开发的处理正则表达式的库。在小型匹配的情况下有非常优秀的表现。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">综合 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">P::Classes </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://pclasses.com/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">一个高度可移植的C++应用程序框架。当前关注类型和线程安全的signal/slot机制，i/o系统包括基于插件的网络协议透明的i/o架构，基于插件的应用程序消息日志框架，访问sql数据库的类等等。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">ACDK - Artefaktur Component Development Kit </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://acdk.sourceforge.net/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">这是一个平台无关的C++组件框架，类似于Java或者.NET中的框架（反射机制，线程，Unicode，废料收集，I/O，网络，实用工具，XML，等等），以及对Java, Perl, Python, TCL, Lisp, COM 和 CORBA的集成。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">dlib C++ library </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://www.cis.ohio-state.edu/~kingd/dlib/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">各种各样的类的一个综合。大整数，Socket，线程，GUI，容器类,以及浏览目录的API等等。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Chilkat C++ Libraries </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://www.chilkatsoft.com/cpp_libraries.asp </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">这是提供zip，e-mail，编码，S/MIME，XML等方面的库。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">C++ Portable Types Library (PTypes) </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://www.melikyan.com/ptypes/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">这是STL的比较简单的替代品，以及可移植的多线程和网络库。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">LFC </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://lfc.sourceforge.net/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">哦，这又是一个尝试提供一切的C++库 </p>
		<p style="font-size: 10pt; font-family: Arial;"> </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">其他库 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Loki </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://www.moderncppdesign.com/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">哦，你可能抱怨我早该和Boost一起介绍它，一个实验性质的库。作者在loki中把C++模板的功能发挥到了极致。并且尝试把类似设计模式这样思想层面的东西通过库来提供。同时还提供了智能指针这样比较实用的功能。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">ATL </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">ATL(Active Template Library)是一组小巧、高效、灵活的类，这些类为创建可互操作的COM组件提供了基本的设施。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">FC++: The Functional C++ Library </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">这个库提供了一些函数式语言中才有的要素。属于用库来扩充语言的一个代表作。如果想要在OOP之外寻找另一分的乐趣，可以去看看函数式程序设计的世界。大师 Peter Norvig在 "Teach Yourself Programming in Ten Years"一文中就将函数式语言列为至少应当学习的6类编程语言之一。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">FACT! </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">参考网站：http://www.kfa-juelich.de/zam/FACT/start/index.html </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">另外一个实现函数式语言特性的库 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Crypto++ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">提供处理密码，消息验证，单向hash，公匙加密系统等功能的免费库。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">还有很多非常激动人心或者是极其实用的C++库，限于我们的水平以及文章的篇幅不能包括进来。在对于这些已经包含近来的库的介绍中，由于并不是每一个我们都使用过，所以难免有偏颇之处，请读者见谅。 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">资源网站 </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">正如我们可以通过计算机历史上的重要人物了解计算机史的发展，C++相关人物的网站也可以使我们得到最有价值的参考与借鉴，下面的人物我们认为没有介绍的必要，只因下面的人物在C++领域的地位众所周知，我们只将相关的资源进行罗列以供读者学习，他们有的工作于贝尔实验室，有的工作于知名编译器厂商，有的在不断推进语言的标准化，有的为读者撰写了多部千古奇作...... </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Bjarne Stroustrup http://www.research.att.com/~bs/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Stanley B. Lippman </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">http: //blogs.msdn.com/slippman/ 中文版 http: //www.zengyihome.net/slippman/index.htm<br />　Scott Meyers http://www.aristeia.com/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">David Musser http://www.cs.rpi.edu/~musser/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Bruce Eckel http://www.bruceeckel.com </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Nicolai M. Josuttis http://www.josuttis.com/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Herb Sutter http://www.gotw.ca/ </p>
		<p class="content" style="font-size: 10pt; font-family: Arial;">Andrei Alexandrescu http://www.moderncppdesign.com/</p>
		<p style="font-size: 10pt; font-family: Arial;">
				<br /> </p>
<img src ="http://www.cppblog.com/erran/aggbug/34119.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/erran/" target="_blank">erran</a> 2007-10-13 16:42 <a href="http://www.cppblog.com/erran/archive/2007/10/13/34119.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：Little Endian &amp; Big Endian</title><link>http://www.cppblog.com/erran/archive/2007/10/13/34115.html</link><dc:creator>erran</dc:creator><author>erran</author><pubDate>Sat, 13 Oct 2007 08:23:00 GMT</pubDate><guid>http://www.cppblog.com/erran/archive/2007/10/13/34115.html</guid><wfw:comment>http://www.cppblog.com/erran/comments/34115.html</wfw:comment><comments>http://www.cppblog.com/erran/archive/2007/10/13/34115.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/erran/comments/commentRss/34115.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/erran/services/trackbacks/34115.html</trackback:ping><description><![CDATA[
		<p style="font-size: 10pt; font-family: Arial;" align="left">原文：<a href="http://dev.csdn.net/article/39/39864.shtm">http://dev.csdn.net/article/39/39864.shtm</a><br /><br /><strong> <span id="ArticleTitle1_ArticleTitle1_lblTitle">Little Endian &amp; Big Endian</span></strong>    <br /><br /><span id="ArticleContent1_ArticleContent1_lblContent">这个标题中的Endian是什么意思呢？还是让我们先来看看下面的情况，这是内存中一个WORD值中的内容，那么这个WORD中的值是0x1234呢，还是0x3412 ?  <br /><br />low byte high byte  <br />0x12      0x34  <br /><br />熟悉x86汇编的人立刻就知道这个值应为0x3412，很对，但在一些情况下，比如说你在SGI的机器上看到这种情况，则正好相反，0x1234才是正确答案，这与CPU内部处理数据的方式有关。这两种处理方式都存在于不同厂商生产的CPU之中，在上例中若此WORD值为0x3412的，我们称之为little-endian, 若为0x1234的，我们称之为big-endian，这是两种不同的byte orders。MSDN中有比较精确的定义如下： <br /><br />Byte Ordering Byte ordering Meaning  <br />big-endian The most significant byte is on the left end of a word.  <br />little-endian The most significant byte is on the right end of a word.  <br /><br />一般来说我们不用关心byte ordering的问题，但若要涉及跨平台之间的通信和资源共享，则不得不考虑这个问题了。也许你会说，我永远不会去用其它非x86的CPU，也许是这样，你甚至可以不必知道我们最常用的Intel，AMD等生产的x86的byte ordering是little-endian的，而且按现在的装机数量来看，可以说世界上绝大多数CPU是little-endian的，但多了解一些没有什么坏处，也许有用上的一天，实际若您要涉及到网络编程，了解一些还是有所帮助的，看完本文后您就应该知道为何socket编程中为何要用到如 ntohl, htonl, ntohs, htons这几个看起来名字似乎怪怪的API了，也很容易理解这些函数名的意义了。 <br /><br />假设我们要在不同byte ordering的机器之间传输和交换数据，那该怎么办呢，有两个方法，一是全部转换成文本来传输(如XML使用的)，另一个方法两方都按照某一方的byte order，这时就涉及到了不同byte order之间相互转换的问题（网络传输标准如TCP/IP采用第二种方法并且由于历史的原因，byte ordering是big-endian的）。两种之间该如何转换呢？方法有很多，我们可以先看看MFC中在处理serialize的代码中所用的方法(List), 虽然代码应该是高效易读的, 但我个人并不喜欢它, 原因是我觉得这不是一种通用优美的方法.下面列出的是我自己写的转换的代码： <br /><br />template <br />F3D_INLINE T ConvertEndian(T  t) <br />{ <br />   T tResult = 0; <br />   for (int  I = 0; I &lt; sizeof(T); ++ I) <br />   { <br />      tResult &lt;&lt;= 8;    <br />      tResult |= (t &amp; 0xFF) ; <br /><br />      t &gt;&gt;= 8; <br />   } <br />   return  tResult; <br />} <br /><br />原理非常简单，交换字节顺序，我就不多说了，当然这个写法并不是快速的, 只是通用的(我没条件试, 若有不对之处请指出), 若要快速的代码，可以在不同platform上用与platform相关的代码, 如在PowerPC上有 "load word byte-reversed indexed" (lwbrx) 和 "load halfword byte-reversed indexed" (lhbrx) 指令, 在x86上还可用BSWAP单个汇编指令等，在类型上专为int16, int32写的通用的代码也可以比这快得多.  <br /><br />当然如果在byte ordering相同的情况下，应该不必用这个转换函数，所以我们可以定义一个宏来处理不同的byte ordering，也可以在运行时测试byte ordering, 下面的代码给出了一个简单的测试方法。  <br /><br /><br />// Test for endianness. <br />F3D_INLINE bool IsLittleEndian(void) <br />{ <br />   DWORD dwTestValue = 0x12345678L; <br />   return  (*((BYTE*)&amp;dwTestValue) == 0x78); <br />} <br /><br />但是float比较怪，有可能所涉及到不仅仅是byte order的问题，因为有些平台如Alpha不使用IEEE的浮点格式，还得自己转换。当然同上，其它的方法一是将所用的float用文本方式输入输出，另一个办法是在某些情况下可将其转换成定点数再处理，这里我不再深入。 <br /><br />如果是读写第三方已经指定byte order的文件或数据流，比如说读SGI的位图文件格式，则可以直接自行按指定的byte order拼起来，不必考虑host机是何种byte ordering。下面我给出相应的代码： <br /><br /><br />// Read a little-endian TYPE from address <br />template <br />F3D_INLINE T GetLittleEndian(const BYTE*  pBuf) <br />{ <br />   T tResult = 0; <br />   pBuf += sizeof(T) - 1; <br />   for (int  I = 0; I &lt; sizeof(T); ++ I) <br />   { <br />      tResult &lt;&lt;= 8; <br />      tResult |= *pBuf --; <br />   } <br /><br />   return  tResult; <br />} <br /><br />// Read a big-endian TYPE from address <br />template <br />F3D_INLINE T GetBigEndian(const BYTE*  pBuf) <br />{ <br />   T tResult = 0; <br />   for (int  I = 0; I &lt; sizeof(T); ++ I) <br />   { <br />      tResult &lt;&lt;= 8; <br />      tResult |= *pBuf ++; <br />   } <br /><br />   return  tResult; <br />} <br /><br />// Set a little-endian TYPE on a address <br />template <br />F3D_INLINE void SetLittleEndian(BYTE*  pBuf, T  t) <br />{ <br />   for (int  I = 0; I &lt; sizeof(T); ++ I) <br />   { <br />   *pBuf ++ = BYTE(t &amp; 0xFF); <br />   t &gt;&gt;= 8; <br />   } <br />} <br /><br />// Set a big-endian T on a address <br />template <br />F3D_INLINE void SetBigEndian(BYTE*  pBuf, T  t) <br />{ <br />   pBuf += sizeof(T) - 1; <br />   for (int  I = 0; I &lt; sizeof(T); ++ I) <br />   { <br />      *pBuf -- = BYTE(t &amp; 0xFF); <br />      t &gt;&gt;= 8; <br />   } <br />} <br /><br />从上文可以看出，byte order挺简单的，一般应用中可能也用不上，但若您对写跨平台的程序有兴趣，则一定要了解的比较清楚才行。以上代码都是从实际使用的源码中取下来的。  <br /><br />附：常见Processor, OS的byte ordering情况 <br /><br />Processor OS Order  <br />x86 (Intel, AMD, … ) All little-endian  <br />DEC Alpha All little-endian  <br />HP-PA NT little-endian  <br />HP-PA UNIX big-endian  <br />SUN SPARC All? big-endian  <br />MIPS NT little-endian  <br />MIPS UNIX big-endian  <br />PowerPC NT little-endian  <br />PowerPC non-NT big-endian  <br />RS/6000 UNIX big-endian  <br />Motorola m68k All big-endian </span></p>
<img src ="http://www.cppblog.com/erran/aggbug/34115.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/erran/" target="_blank">erran</a> 2007-10-13 16:23 <a href="http://www.cppblog.com/erran/archive/2007/10/13/34115.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>怎样实现数目不定的函数参数</title><link>http://www.cppblog.com/erran/archive/2006/12/28/16959.html</link><dc:creator>erran</dc:creator><author>erran</author><pubDate>Thu, 28 Dec 2006 12:21:00 GMT</pubDate><guid>http://www.cppblog.com/erran/archive/2006/12/28/16959.html</guid><wfw:comment>http://www.cppblog.com/erran/comments/16959.html</wfw:comment><comments>http://www.cppblog.com/erran/archive/2006/12/28/16959.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/erran/comments/commentRss/16959.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/erran/services/trackbacks/16959.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp; 怎样实现数目不定的函数参数 &nbsp; 2006-12-28 erran &nbsp; 实现方法一：自定义指针找到函数参数的下一个参数； &nbsp; // 例子 A ： template&lt;class T&gt; T umin(T _a, ...) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp...&nbsp;&nbsp;<a href='http://www.cppblog.com/erran/archive/2006/12/28/16959.html'>阅读全文</a><img src ="http://www.cppblog.com/erran/aggbug/16959.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/erran/" target="_blank">erran</a> 2006-12-28 20:21 <a href="http://www.cppblog.com/erran/archive/2006/12/28/16959.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>函数指针(全局函数/类成员函数)、函数对象(Function object)</title><link>http://www.cppblog.com/erran/archive/2006/12/26/16868.html</link><dc:creator>erran</dc:creator><author>erran</author><pubDate>Tue, 26 Dec 2006 05:27:00 GMT</pubDate><guid>http://www.cppblog.com/erran/archive/2006/12/26/16868.html</guid><wfw:comment>http://www.cppblog.com/erran/comments/16868.html</wfw:comment><comments>http://www.cppblog.com/erran/archive/2006/12/26/16868.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/erran/comments/commentRss/16868.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/erran/services/trackbacks/16868.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一.&nbsp;&nbsp; 函数指针类型为全局函数 . &nbsp; &nbsp; &#160;                                    #include "stdafx.h"             &nbsp;             #include &lt;iostream&gt;             usin...&nbsp;&nbsp;<a href='http://www.cppblog.com/erran/archive/2006/12/26/16868.html'>阅读全文</a><img src ="http://www.cppblog.com/erran/aggbug/16868.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/erran/" target="_blank">erran</a> 2006-12-26 13:27 <a href="http://www.cppblog.com/erran/archive/2006/12/26/16868.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C/C++头文件一览</title><link>http://www.cppblog.com/erran/archive/2006/05/30/7906.html</link><dc:creator>erran</dc:creator><author>erran</author><pubDate>Tue, 30 May 2006 15:35:00 GMT</pubDate><guid>http://www.cppblog.com/erran/archive/2006/05/30/7906.html</guid><wfw:comment>http://www.cppblog.com/erran/comments/7906.html</wfw:comment><comments>http://www.cppblog.com/erran/archive/2006/05/30/7906.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/erran/comments/commentRss/7906.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/erran/services/trackbacks/7906.html</trackback:ping><description><![CDATA[<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">C</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">、传统<span lang=EN-US> C++</span></span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;assert.h&gt;//</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">设定插入点</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;ctype.h&gt; //</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">字符处理</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;errno.h&gt; //</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">定义错误码</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;float.h&gt; //</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">浮点数处理</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;fstream.h&gt;</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">　<span lang=EN-US> //</span>文件输入／输出</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;iomanip.h&gt;</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">　<span lang=EN-US> //</span>参数化输入／输出</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;iostream.h&gt;</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">　<span lang=EN-US>//</span>数据流输入／输出</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;limits.h&gt;//</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">定义各种数据类型最值常量</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;locale.h&gt;//</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">定义本地化函数</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;math.h&gt;</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">　<span lang=EN-US>//</span>定义数学函数</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;stdio.h&gt; //</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">定义输入／输出函数</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;stdlib.h&gt;//</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">定义杂项函数及内存分配函数</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;string.h&gt;//</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">字符串处理</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;strstrea.h&gt;</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">　<span lang=EN-US>//</span>基于数组的输入／输出</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;time.h&gt;</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">　<span lang=EN-US>//</span>定义关于时间的函数</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;wchar.h&gt; //</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">宽字符处理及输入／输出</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;wctype.h&gt;//</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">宽字符分类</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">//////////////////////////////////////////////////////////////////////////</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">标准<span lang=EN-US> C++</span>　（同上的不再注释）</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;algorithm&gt;</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">　<span lang=EN-US> //STL </span>通用算法</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;bitset&gt;</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">　<span lang=EN-US>//STL </span>位集容器</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;cctype&gt;</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;cerrno&gt;</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;clocale&gt;</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;cmath&gt;</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;complex&gt; //</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">复数类</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;cstdio&gt;</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;cstdlib&gt;</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;cstring&gt;</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;ctime&gt;</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;deque&gt;</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">　<span lang=EN-US> //STL </span>双端队列容器</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;exception&gt;</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">　<span lang=EN-US> //</span>异常处理类</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;fstream&gt;</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;functional&gt;</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">　<span lang=EN-US>//STL </span>定义运算函数（代替运算符）</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;limits&gt;</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;list&gt;//STL </span><span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">线性列表容器</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;map&gt; //STL </span><span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">映射容器</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;iomanip&gt;</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;ios&gt; //</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">基本输入／输出支持</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;iosfwd&gt;</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">　<span lang=EN-US>//</span>输入／输出系统使用的前置声明</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;iostream&gt;</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;istream&gt; //</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">基本输入流</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;ostream&gt; //</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">基本输出流</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;queue&gt;</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">　<span lang=EN-US> //STL </span>队列容器</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;set&gt; //STL </span><span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">集合容器</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;sstream&gt; //</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">基于字符串的流</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;stack&gt;</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">　<span lang=EN-US> //STL </span>堆栈容器</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;stdexcept&gt;</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">　<span lang=EN-US> //</span>标准异常类</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;streambuf&gt;</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">　<span lang=EN-US> //</span>底层输入／输出支持</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;string&gt;</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">　<span lang=EN-US>//</span>字符串类</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;utility&gt; //STL </span><span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">通用模板类</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;vector&gt;</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">　<span lang=EN-US>//STL </span>动态数组容器</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;cwchar&gt;</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;cwctype&gt;</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">using namespace std;</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">//////////////////////////////////////////////////////////////////////////</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">C99 </span><span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">增加</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;complex.h&gt; //</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">复数处理</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;fenv.h&gt;//</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">浮点环境</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;inttypes.h&gt;//</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">整数格式转换</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;stdbool.h&gt; //</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">布尔环境</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;stdint.h&gt;</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">　<span lang=EN-US>//</span>整型环境</span> <span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt"><br><br></span><span lang=EN-US style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">#include &lt;tgmath.h&gt;</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">　<span lang=EN-US>//</span>通用类型数学宏</span> </p>
<img src ="http://www.cppblog.com/erran/aggbug/7906.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/erran/" target="_blank">erran</a> 2006-05-30 23:35 <a href="http://www.cppblog.com/erran/archive/2006/05/30/7906.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>我的数据实体里常有的几个函数</title><link>http://www.cppblog.com/erran/archive/2006/05/30/7905.html</link><dc:creator>erran</dc:creator><author>erran</author><pubDate>Tue, 30 May 2006 15:14:00 GMT</pubDate><guid>http://www.cppblog.com/erran/archive/2006/05/30/7905.html</guid><wfw:comment>http://www.cppblog.com/erran/comments/7905.html</wfw:comment><comments>http://www.cppblog.com/erran/archive/2006/05/30/7905.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/erran/comments/commentRss/7905.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/erran/services/trackbacks/7905.html</trackback:ping><description><![CDATA[<p style="MARGIN-BOTTOM: 12pt"><span style="FONT-SIZE: 10pt"><font face=宋体>在此聊聊我设计数据实体的一些小伎俩<span lang=EN-US>^_^ .........&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br></span></font><font face=宋体><span lang=EN-US><br></span>为了方便数据的组织<span lang=EN-US>.</span>运算以及数据实体类的使用<span lang=EN-US>, </span>一般我会把所有数据实体从同一个实体基类继承而来<span lang=EN-US>, </span>基类里有一些常用的函数<span lang=EN-US>, </span>以类<span lang=EN-US>CEntiy</span>为例说明如下</font> <font face=宋体><span lang=EN-US>:<br><br>1.&nbsp;&nbsp; &nbsp;CEntity(const CEntity&amp; ent);<br><br></span>首先当然是拷贝构造函数<span lang=EN-US>, </span>在实际使用实体过程中这个函数很有用<span lang=EN-US>, </span>当然在<span lang=EN-US>CEntity</span>的派生类中我也会去实现其派生类的拷贝构造函数</font> <font face=宋体><span lang=EN-US>.<br><br><br>2.&nbsp;&nbsp;&nbsp;&nbsp;virtual ~CEntity();<br><br>&nbsp;</span>析构函数<span lang=EN-US>, </span>这个就不必说了<span lang=EN-US>, </span>要</font> <font face=宋体><span lang=EN-US>virtual<br><br><br>3.&nbsp; virtual CString GetTypeID(void) const;<br><br></span>此函数返回一个<span lang=EN-US>CString</span>类型的实体标识<span lang=EN-US>, </span>以标明到底是那个类<span lang=EN-US>, </span>在基类中我一般这样实现<span lang=EN-US>: return&nbsp; _T("ENT_UNKNOW");&nbsp;&nbsp; </span>很显然我会在<span lang=EN-US>CEntity</span>的每一个派生类中重载这个函数<span lang=EN-US>, </span>有了这个函数<span lang=EN-US>, </span>就可以很方便的从一个基类的指针知道其实例化的到底是哪一个派生类的对象<span lang=EN-US>,&nbsp;</span>这样就可以很方便的管理系统中多个相似数据实体<span lang=EN-US>,&nbsp; </span>就可以把所有的数据实体实例化为基类的指针<span lang=EN-US>,&nbsp; </span>关于数据实体的接口都可以用基类的指针或者引用类型<span lang=EN-US>,&nbsp; </span>而不用去担心他到底是那个派生类的对象<span lang=EN-US>.&nbsp; </span>当然也可以<span lang=EN-US> virtual int GetTypeID(void) const;&nbsp; virtual DWORD GetTypeID(void) const; virtual DWORD GetClassID(void) const;</span>等等。<span lang=EN-US><o:p></o:p></span></font> </span></p>
<p style="MARGIN: 5pt 0cm 12pt 20.25pt; TEXT-INDENT: -20.25pt; mso-list: l0 level1 lfo1; tab-stops: list 20.25pt"><span lang=EN-US style="FONT-SIZE: 10pt"><span style="mso-list: Ignore"><font face=宋体>4.</font> <span style="FONT: 7pt 'Times New Roman'"><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span><span lang=EN-US style="FONT-SIZE: 10pt"><font face=宋体>virtual void Initiate(void);<o:p></o:p></font> </span></p>
<p style="MARGIN-BOTTOM: 12pt"><span style="FONT-SIZE: 10pt"><font face=宋体>数据初始化。 初始化数据实体的数据<span lang=EN-US>.<o:p></o:p></span></font> </span></p>
<p style="MARGIN-BOTTOM: 12pt"><span lang=EN-US style="FONT-SIZE: 10pt"><o:p><font face=宋体>&nbsp;</font> </o:p></span></p>
<p style="MARGIN-BOTTOM: 12pt"><font face=宋体><span lang=EN-US style="FONT-SIZE: 10pt">5</span> <span style="FONT-SIZE: 10pt">．<span lang=EN-US>&nbsp;virtual void Reset(void);<o:p></o:p></span></span> </font></p>
<p style="MARGIN-BOTTOM: 12pt"><span style="FONT-SIZE: 10pt"><font face=宋体>数据复位操作。把数据实体复位到某一状态<span lang=EN-US>.<o:p></o:p></span></font> </span></p>
<p style="MARGIN-BOTTOM: 12pt"><span lang=EN-US style="FONT-SIZE: 10pt"><o:p><font face=宋体>&nbsp;</font> </o:p></span></p>
<p style="MARGIN-LEFT: 20.25pt; TEXT-INDENT: -20.25pt; mso-list: l0 level1 lfo1; tab-stops: list 20.25pt"><span lang=EN-US style="FONT-SIZE: 10pt"><span style="mso-list: Ignore"><font face=宋体>5.</font> <span style="FONT: 7pt 'Times New Roman'"><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span><span lang=EN-US style="FONT-SIZE: 10pt"><font face=宋体>virtual CEntity * Clone(void) const;<o:p></o:p></font> </span></p>
<p><span style="FONT-SIZE: 10pt"><font face=宋体>克隆数据实体<span lang=EN-US>. </span>这个函数一般这样实现<span lang=EN-US>: return new CEntity(*this);<o:p></o:p></span></font> </span></p>
<p><span lang=EN-US style="FONT-SIZE: 10pt"><o:p><font face=宋体>&nbsp;</font> </o:p></span></p>
<p style="MARGIN-LEFT: 20.25pt; TEXT-INDENT: -20.25pt; mso-list: l0 level1 lfo1; tab-stops: list 20.25pt"><span lang=EN-US style="FONT-SIZE: 10pt"><span style="mso-list: Ignore"><font face=宋体>6.</font> <span style="FONT: 7pt 'Times New Roman'"><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span><span lang=EN-US style="FONT-SIZE: 10pt"><font face=宋体>virtual void Serialize(CArchive&amp; ar);<o:p></o:p></font> </span></p>
<p><span style="FONT-SIZE: 10pt"><font face=宋体>数据串行化<span lang=EN-US>. </span>以实现数据实体左右移方式的对数据实体赋值<span lang=EN-US>,</span>保存等操作<span lang=EN-US>. </span>常把其与<span lang=EN-US>CMemFile</span>一起使用<span lang=EN-US>,</span>感觉效果很好<span lang=EN-US>.</span>唯一不足的是解决数据实体版本升级时的数据一致性的问题很麻烦<span lang=EN-US>.<br><br><br><o:p></o:p></span></font></span></p>
<p style="MARGIN-LEFT: 20.25pt; TEXT-INDENT: -20.25pt; mso-list: l0 level1 lfo1; tab-stops: list 20.25pt"><span lang=EN-US style="FONT-SIZE: 10pt"><span style="mso-list: Ignore"><font face=宋体>7.</font> <span style="FONT: 7pt 'Times New Roman'"><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span><span lang=EN-US style="FONT-SIZE: 10pt"><font face=宋体>virtual BOOL DataSet(const CEntity&amp; ent); <o:p></o:p></font></span></p>
<p><font face=宋体><span style="FONT-SIZE: 10pt">刷新数据<span lang=EN-US>,</span>实现数据实体之间的赋值操作<span lang=EN-US>.</span>这个函数主要是为了解决上一篇所提的问题<span lang=EN-US>(</span></span> <span lang=EN-US><a href="http://www.cppblog.com/erran/archive/2006/05/22/7466.html"><font size=2>C++<span lang=EN-US><span lang=EN-US>随笔</span></span><span lang=EN-US><span lang=EN-US></span></span><span lang=EN-US><span lang=EN-US>关于virtual poperator =</span></span></font> </a><font size=2>( 05-22 01:09)</font> </span><span lang=EN-US style="FONT-SIZE: 10pt">).</span> <span style="FONT-SIZE: 10pt">可以把他设为<span lang=EN-US>protected</span>类型<span lang=EN-US>, </span>同<span lang=EN-US>operator=</span>结合起来使用<span lang=EN-US>, </span>供<span lang=EN-US>poperator =</span>调用<span lang=EN-US>.<br><br><br><o:p></o:p></span></span></font></p>
<p style="MARGIN-LEFT: 20.25pt; TEXT-INDENT: -20.25pt; mso-list: l0 level1 lfo1; tab-stops: list 20.25pt"><font size=2><span lang=EN-US><span style="mso-list: Ignore"><font face=宋体>8.</font> <span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang=EN-US style="FONT-SIZE: 10pt"><font face=宋体><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp; </span>const CEntity&amp; operator=(const CEntity&amp; ent);</font> </span></font></p>
<p><span style="FONT-SIZE: 10pt"><font face=宋体>赋值操作<span lang=EN-US>.</span>在派生类中也会重载<span lang=EN-US>operator=, </span>不是重载基类的<span lang=EN-US>operator=.<br><br><br><o:p></o:p></span></font></span></p>
<p style="MARGIN-LEFT: 20.25pt; TEXT-INDENT: -20.25pt; mso-list: l0 level1 lfo1; tab-stops: list 20.25pt"><span lang=EN-US style="FONT-SIZE: 10pt"><span style="mso-list: Ignore"><font face=宋体>9.</font> <span style="FONT: 7pt 'Times New Roman'"><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></span><span style="FONT-SIZE: 10pt"><font face=宋体>另外如果存在数据比较的话<span lang=EN-US>, </span>会重载<span lang=EN-US>operator==</span>操作符<span lang=EN-US>.<o:p></o:p></span></font> </span></p>
<p><span lang=EN-US style="FONT-SIZE: 10pt"><font face=宋体>&nbsp;friend bool operator==(const CEntity&amp; ent1, const CEntity&amp; ent2);<o:p></o:p></font> </span></p>
<p><span lang=EN-US style="FONT-SIZE: 10pt"><font face=宋体>&nbsp;friend bool operator!=(const CEntity&amp; ent1, const CEntity&amp; ent2);<o:p></o:p></font> </span></p>
<p><span lang=EN-US style="FONT-SIZE: 10pt"><o:p><font face=宋体>&nbsp;<br></font></o:p></span></p>
<p><font face=宋体><font size=2><font face=宋体><span lang=EN-US>谢谢关注~~~<br></span></font><br>以下附三相电流电压数据实体部分实现代码<span lang=EN-US>:</span></font> </font></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>class CThreePhaseEntity: public CEntity</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>{</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>public:</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>CThreePhaseEntity ();</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>CThreePhaseEntity (const CSixPhaseEntity&amp; ent);</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>~CSixPhaseEntity();</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>public:</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>CString GetTypeID(void) const;</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>void Initiate(void);</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>void Reset(void);</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>public:</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>CEntity * Clone(void) const;</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>void Serialize(CArchive&amp; ar);</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>BOOL DataSet(const CEntity&amp; ent);</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>public:</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>const CSixPhaseEntity&amp; operator=(const CSixPhaseEntity&amp; ent);</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>friend bool operator==(const CSixPhaseEntity&amp; ent1, const CSixPhaseEntity&amp; ent2);</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>friend bool operator!=(const CSixPhaseEntity&amp; ent1, const CSixPhaseEntity&amp; ent2);</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>public:</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><font size=2><span lang=EN-US>//</span> <span style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">获取三相数据</span> <span lang=EN-US>, </span><span style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">内联函数</span> </font></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>const float&amp; GetSixPhaseData(int nDateType, int nPhaseMark) const; </font></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=2><span lang=EN-US><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//</span> <span style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">修改三相数据</span> <span lang=EN-US>, </span><span style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">内联函数</span> </font></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>void SetSixPhaseData(int nDataType, int nPhaseMark, const float&amp; fData);</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>private:<span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp; </span></font></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=2><span lang=EN-US><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>float m_gfRange[3];<span style="mso-spacerun: yes">&nbsp; </span>//</span> <span style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">幅值</span> <span lang=EN-US>,</span> </font></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=2><span lang=EN-US><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>float m_gfPhase[3];<span style="mso-spacerun: yes">&nbsp; </span>//</span> <span style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">相位</span> <span lang=EN-US>,</span> </font></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=2><span lang=EN-US><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>float m_gfFrequency[3];<span style="mso-spacerun: yes">&nbsp; </span>//</span> <span style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">频率</span> </font></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>};</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><font size=2><span lang=EN-US>///******cpp</span> <span style="FONT-FAMILY: 宋体; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'">文件</span> </font></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>CThreePhaseEntity:: CThreePhaseEntity ()</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>{</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Initiate();</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>}</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>CThreePhaseEntity:: CThreePhaseEntity (const CThreePhaseEntity &amp; ent)</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>{</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>for(int i=0; i&lt;3; i++)</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>m_gfRange[i] = ent.m_gfRange[i];</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>m_gfPhase[i] = ent.m_gfPhase[i];</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>m_gfFrequency[i] = ent.m_gfFrequency[i];</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>}</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>CThreePhaseEntity::~ CThreePhaseEntity ()</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>{</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>}</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>CString CThreePhaseEntity::GetTypeID(void) const</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>{</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return _T("ENT_THREEPHASE ");</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>}</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>void CThreePhaseEntity::Initiate()</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>{</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>for(int i=0; i&lt;3; i++)</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>m_gfRange[i] = <st1:chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="0" unitname="F">0.0f</st1:chmetcnv>;</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>m_gfPhase[i] = <st1:chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="0" unitname="F">0.0f</st1:chmetcnv>;</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>m_gfFrequency[i] = <st1:chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="0" unitname="F">0.0f</st1:chmetcnv>;</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>}</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>void CThreePhaseEntity::Reset(void)</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>{</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>for(int i=0; i&lt;3; i++)</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>m_gfRange[i] = <st1:chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="57.74" unitname="F">57.740f</st1:chmetcnv>;</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt"><span lang=EN-US><font size=2>m_gfFrequency[i] = <st1:chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="50" unitname="F">50.0f</st1:chmetcnv>;</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><span lang=EN-US><font size=2>}</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><span lang=EN-US><font size=2>m_ gfPhase [0] = <st1:chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="0" unitname="F">0.0f</st1:chmetcnv></font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><span lang=EN-US><font size=2>m_ gfPhase [1] = <st1:chmetcnv w:st="on" tcsc="0" numbertype="1" negative="True" hasspace="False" sourcevalue="120" unitname="F">-120.0f</st1:chmetcnv></font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0"><span lang=EN-US><font size=2>m_ gfPhase [2] = <st1:chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="120" unitname="F">120.0f</st1:chmetcnv></font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>}</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>void CThreePhaseEntity::Serialize(CArchive&amp; ar)</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>{</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if(ar.IsStoring())</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>for(int i=0; i&lt;3; i++)</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt"><span lang=EN-US><font size=2>{</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: 21pt"><span lang=EN-US><font size=2>ar&lt;&lt;m_gfRange[i]&lt;&lt;m_gfPhase[i]&lt;&lt;m_gfFrequency[i];</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 42pt; mso-char-indent-count: 4.0"><span lang=EN-US><font size=2>}</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>else</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>for(int i=0; i&lt;3; i++)</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt"><span lang=EN-US><font size=2>{</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: 21pt"><span lang=EN-US><font size=2>ar&gt;&gt;m_gfRange[i]&gt;&gt;m_gfPhase[i]&gt;&gt;m_gfFrequency[i];</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 42pt; mso-char-indent-count: 4.0"><span lang=EN-US><font size=2>}</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>}</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>BOOL CThreePhaseEntity::DataSet(const CEntity&amp; ent)</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>{</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if(GetTypeID() != ent.GetTypeID()) return FALSE;</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><span style="mso-tab-count: 1"><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>const CThreePhaseEntity * pEnt = reinterpret_cast&lt;const CThreePhaseEntity *&gt;(&amp;ent);</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>(*this) = (*pEnt);</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return TRUE;</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>}</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>CEntity * CThreePhaseEntity::Clone(void) const</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>{</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return new CThreePhaseEntity (*this);</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>}</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>const CThreePhaseEntity &amp; CThreePhaseEntity::operator=(const CThreePhaseEntity &amp; ent)</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>{</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if(this == &amp;ent) return *this;</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>for(int i=0; i&lt;3; i++)</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>m_gfRange[i] = ent.m_gfRange[i];</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>m_gfPhase[i] = ent.m_gfPhase[i];</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>m_gfFrequency[i] = ent.m_gfFrequency[i];</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return *this;</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>}</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>bool operator==(const CThreePhaseEntity &amp; ent1, const CThreePhaseEntity &amp; ent2)</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>{</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>for(int i=0; i&lt;3; i++)</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if(ent1.m_gfRange[i] != ent2.m_gfRange[i]) return false;</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if(ent1.m_gfPhase[i] != ent2.m_gfPhase[i]) return false;</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if(ent1.m_gfFrequency[i] != ent2.m_gfFrequency[i]) return false;</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return true;</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>}</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p><font size=2>&nbsp;</font> </o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>bool operator!=(const CThreePhaseEntity &amp; ent1, const CThreePhaseEntity &amp; ent2)</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>{</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2><span style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return (ent1 == ent2) ? false : true;</font> </span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><font size=2>}</font> </span></p>
<img src ="http://www.cppblog.com/erran/aggbug/7905.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/erran/" target="_blank">erran</a> 2006-05-30 23:14 <a href="http://www.cppblog.com/erran/archive/2006/05/30/7905.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++随笔 关于virtual operator =</title><link>http://www.cppblog.com/erran/archive/2006/05/22/7466.html</link><dc:creator>erran</dc:creator><author>erran</author><pubDate>Sun, 21 May 2006 17:09:00 GMT</pubDate><guid>http://www.cppblog.com/erran/archive/2006/05/22/7466.html</guid><wfw:comment>http://www.cppblog.com/erran/comments/7466.html</wfw:comment><comments>http://www.cppblog.com/erran/archive/2006/05/22/7466.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/erran/comments/commentRss/7466.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/erran/services/trackbacks/7466.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; <br><font size=2>如果在派生类中要重载派生类的operator = ，那么在基类中一般不要重载operator = ，因为这样会带来很多麻烦. <br><br>定义了两个类：<br>&nbsp;class CBase<br>{&nbsp;&nbsp; <br>public: <br>&nbsp;&nbsp; CBase() <br>&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; cout&lt;&lt;"CBase constructing ..."&lt;&lt;endl; <br>&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp; virtual ~CBase() <br>&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout&lt;&lt;"CBase destructing ..."&lt;&lt;endl; <br>&nbsp;&nbsp;&nbsp; } <br>public: <br>&nbsp;&nbsp; CBase &amp; operator=(const CBase &amp; ent) <br>&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;cout&lt;&lt;"CBase operator = ... "&lt;&lt;endl; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return *this; <br>&nbsp;&nbsp;&nbsp; } <br>}; <br><br>class CDerive: public CBase <br>{ <br>public: <br>&nbsp;&nbsp;&nbsp;&nbsp; CDerive() <br>&nbsp;&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout&lt;&lt;"CDerive constructing&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp;&nbsp; ~CDerive() <br>&nbsp;&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;cout&lt;&lt;"CDerive destructing ..."&lt;&lt;endl; <br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;}&nbsp;<br>public: <br>&nbsp;&nbsp;&nbsp;&nbsp; CDerive &amp; operator=(const CDerive &amp; ent) <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout&lt;&lt;"CDerive operator = ... "&lt;&lt;endl; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return *this;<br>&nbsp;&nbsp;&nbsp;&nbsp; } <br>}<br><br>定义如下操作：<br><br>CBase * b1 = new CDerive();<br>CBase * b2 = new CDerive();<br><br>(*b1) = (*b2);<br><br>可以看到其输出为：<br>CBase constructing ...<br>CDerive constructing ...<br>CBase constructing ...<br>CDerive constructing ...<br>CBase operator = ...<br>CDerive destructing ...<br>CBase destructing ...<br>CDerive destructing ...<br>CBase destructing <br><br>而实际上，操作(*b1) = (*b2)是想把b1,b2实际所指类型的两个对象之间进行赋值，但是它只是调用了基类的赋值操作，没有执行其本身派生类的赋值操作。<br><br>发现有两种方法可以解决这个问题，如果能够知道基类指针实际所指的是哪个派生类的的对象，直接类型转换就可以了：<br><br>(*((CDerive*)b1)) = (*((CDerive*)b2));<br><br>这样可以发现输出了：CDerive operator = ... 。但是当要定义基类的指针的时候，往往隐藏了具体的派生类，即往往不知道指针到底实现的是哪个派生类，所以这种方法有很多局限性。<br><br>这时候可以采用第二种方法，即在派生类中重载基类的赋值操作符，即首先把基类的operator=定义为virtual operator＝，再在派生类中重载这个，如：<br><br>CBase &amp; operator=(const CBase &amp; ent)<br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const CDerive * p = reinterpret_cast&lt;const CDerive *&gt;(&amp;ent);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return operator=((*p));<br>&nbsp;}<br><br>好的，当再执行 (*b1) = (*b2) 的时候就可以看到输出：CDerive operator = ... 。<br><br><br>&nbsp;在此发现在派生类中重载派生类的operator =的时候，如果在基类中也重载operator = ，这样会带来很多麻烦，可能会丢失很多也许不想丢失的数据。<br>&nbsp;<br>同样，依次还存在问题： <br>CBase * b1 = new CDerive(); <br>CDervie * d1 = new CDerive(); <br><br>(*b1) = (*d1); <br><br>CBase * b2 = new CBase (); <br>CDervie * d2 = new CDerive(); <br>(*b2) = (*d2); <br><br>所以我个人觉得，如果一个基类有很多个派生类的，而派生类中又重载了派生类本身的赋值操作符的时候，则基类中最好不要去重载赋值操作符，不如直接用函数去赋值。正如<c++编程思想>所说那样，运算符重载只是为了一种语法上的方便，是另外一种函数调用方式，如果不能带来方便，就没必要了，还不如直接用函数去代替。 <br><br><br>.............敬请指点.................. </c++编程思想></font>
<img src ="http://www.cppblog.com/erran/aggbug/7466.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/erran/" target="_blank">erran</a> 2006-05-22 01:09 <a href="http://www.cppblog.com/erran/archive/2006/05/22/7466.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++随笔 关于赋值操作 内存丢失</title><link>http://www.cppblog.com/erran/archive/2006/05/21/7451.html</link><dc:creator>erran</dc:creator><author>erran</author><pubDate>Sat, 20 May 2006 16:47:00 GMT</pubDate><guid>http://www.cppblog.com/erran/archive/2006/05/21/7451.html</guid><wfw:comment>http://www.cppblog.com/erran/comments/7451.html</wfw:comment><comments>http://www.cppblog.com/erran/archive/2006/05/21/7451.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/erran/comments/commentRss/7451.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/erran/services/trackbacks/7451.html</trackback:ping><description><![CDATA[<p><font size=2>开发中发现在进行&nbsp;赋值操作的时候，很容易内存丢失，看实例：<br><br>class CEntity<br>{<br></font><font size=2>public:<br>&nbsp;&nbsp;&nbsp;&nbsp;CEntity(char flag);<br>&nbsp;&nbsp;&nbsp;&nbsp;~CEntity();<br></font><font size=2>private:&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;char m_flag;<br>};</font> <font size=2><br>CEntity::CEntity(char flag)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;m_flag = flag;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;"constructing entity "&lt;&lt;m_flag&lt;&lt;endl;&nbsp;<br>}</font> <font size=2><br>CEntity::~CEntity()<br>{<br>&nbsp;cout&lt;&lt;"destructing entity "&lt;&lt;m_flag&lt;&lt;endl;<br>}<br><br>执行代码：<br>int main(int argc, char* argv[])<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;CEntity m('m'),n('n');<br></font><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;m = n;<br></font><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br>}<br><br>输出为：<br>constructing entity m<br>constructing entity n<br>destructing entity n<br>destructing entity n<br><br>这个没有出现任何问题，很成功，因为在CEntity里面没有new任何东西，如果把CEntity该为：<br>class CEntity<br>{<br>enum {SIZE = 10};<br><font size=2>public:<br>&nbsp;&nbsp;&nbsp;&nbsp;CEntity(char flag);<br>&nbsp;&nbsp;&nbsp;&nbsp;~CEntity();<br></font><font size=2>private:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;char * m_flag;<br>};</font><font size=2><br>CEntity::CEntity(char flag)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;m_flag = new char[SIZE ];<br>&nbsp;&nbsp;&nbsp; m_flag[0] = flag;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;"constructing entity "&lt;&lt;m_flag[0]&lt;&lt;endl;&nbsp;<br>}</font><font size=2><br>CEntity::~CEntity()<br>{<br>&nbsp;cout&lt;&lt;"destructing entity "&lt;&lt;m_flag[0]&lt;&lt;endl;<br>delete[] m_flag;<br>}<br></font><br>执行同样的main函数，程序将无法运行，debug assertion error! <br><br>这个问题该怎么解决？</font> <font size=2>先睡觉<br><br><br>如oosky所说，重载了赋值操作符，问题就解决了，<br><br><br>CEntity &amp; CEntity::operator=(const CEntity &amp; ent)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;if (ent.m_flag == NULL)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (m_flag != NULL)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete [] m_flag;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_flag = NULL;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (m_flag == NULL)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_flag = new char[SIZE];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int i=0; i&lt;SIZE; i++)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_flag[i] = ent.m_flag[i];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp; &nbsp;return *this;<br>}</font> </p>
<div class=feedbackListTitle>由此可见自定义对象之间的赋值操作要小心行事.....</div>
<p><font size=2></font>&nbsp;</p>
<img src ="http://www.cppblog.com/erran/aggbug/7451.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/erran/" target="_blank">erran</a> 2006-05-21 00:47 <a href="http://www.cppblog.com/erran/archive/2006/05/21/7451.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++随笔 delete void *</title><link>http://www.cppblog.com/erran/archive/2006/05/20/7450.html</link><dc:creator>erran</dc:creator><author>erran</author><pubDate>Sat, 20 May 2006 15:48:00 GMT</pubDate><guid>http://www.cppblog.com/erran/archive/2006/05/20/7450.html</guid><wfw:comment>http://www.cppblog.com/erran/comments/7450.html</wfw:comment><comments>http://www.cppblog.com/erran/archive/2006/05/20/7450.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/erran/comments/commentRss/7450.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/erran/services/trackbacks/7450.html</trackback:ping><description><![CDATA[<p><font size=2>用了这么久的C++，才发现C++是目前所有的编成语言中最为复杂的一种，C++之路,&nbsp;&nbsp; 艰难.....<br><br>&nbsp;&nbsp;&nbsp;<br><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete void *<br></strong><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这一操作对于一些简单的系统内建类型不会有问题，但如果void*所指向的对象在析构函数里要释放，进行此造作会丢失内存，<strong>因为它不执行析构函数</strong>，例如：&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>class CEntity<br>{<br></font><font size=2>public:<br>&nbsp;&nbsp;&nbsp;&nbsp;CEntity(char flag);<br>&nbsp;&nbsp;&nbsp;&nbsp;~CEntity();<br></font><font size=2>private:<br>&nbsp;&nbsp;&nbsp;&nbsp;void * m_data;<br>&nbsp;&nbsp;&nbsp;char&nbsp;&nbsp; m_flag;<br>};</font> </p>
<p><font size=2>CEntity::CEntity(char flag)<br>{<br>&nbsp;&nbsp;&nbsp;m_flag = flag;<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;"constructing entity "&lt;&lt;m_flag&lt;&lt;endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;m_data = new char[100];&nbsp;<br>}</font> </p>
<p><font size=2>CEntity::~CEntity()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;"destructing entity "&lt;&lt;m_flag&lt;&lt;endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;delete[] m_data;<br>}</font> </p>
<font size=2>
<p>以上这个类是没什么问题的，但是看以下的调用：<br>int main(int argc, char* argv[])<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CEntity * a = new CEntity('a');<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete a;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void * b = new CEntity('b');<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete b;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br>}<br><br>其输出为：&nbsp;constructing entity a<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;destructing entity a<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; constructing entity b&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>可见，delete b&nbsp;的时候没有释放m_data所指向的内存，没有执行析构函数。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
</font>
<img src ="http://www.cppblog.com/erran/aggbug/7450.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/erran/" target="_blank">erran</a> 2006-05-20 23:48 <a href="http://www.cppblog.com/erran/archive/2006/05/20/7450.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>