??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲综合久久久,久久久综合香蕉尹人综合网,精品一区二区久久http://www.shnenglu.com/erran/category/5344.htmlzh-cnMon, 19 May 2008 13:29:01 GMTMon, 19 May 2008 13:29:01 GMT60转:字节寚w详解http://www.shnenglu.com/erran/archive/2007/10/16/34383.htmlerranerranTue, 16 Oct 2007 14:56:00 GMThttp://www.shnenglu.com/erran/archive/2007/10/16/34383.htmlhttp://www.shnenglu.com/erran/comments/34383.htmlhttp://www.shnenglu.com/erran/archive/2007/10/16/34383.html#Feedback2http://www.shnenglu.com/erran/comments/commentRss/34383.htmlhttp://www.shnenglu.com/erran/services/trackbacks/34383.html看了q篇Qhttp://www.shnenglu.com/Randy/archive/2007/10/15/34288.aspxQ关于字节对其的随笔Q觉得迷qLp的Q脑袋里只有字节对其q个概念Q具体都忘的差不多了Q又另外找了细M下,ȝ理解了?br />
来源Qhttp://www.yuanma.org/data/2006/0723/article_1213.htm

一.什么是字节寚w,Z么要寚w?

    C计算Z内存I间都是按照byte划分的,从理Z讲似乎对Mcd的变量的讉K可以从Q何地址开始,但实际情冉|在访问特定类型变量的时候经常在? 定的内存地址讉KQ这需要各U类型数据按照一定的规则在空间上排列Q而不是顺序的一个接一个的排放Q这是寚w?br />    寚w的作用和原因Q各个硬件^台对存储I间的处理上有很大的不同。一些^台对某些特定cd的数据只能从某些特定地址开始存取。比如有些架构的CPU在访? 一个没有进行对齐的变量的时候会发生错误,那么在这U架构下~程必须保证字节寚w.其他q_可能没有q种情况Q但是最常见的是如果不按照适合其^台要求对 数据存放q行寚wQ会在存取效率上带来损失。比如有些^台每ơ读都是从偶地址开始,如果一个int型(假设?2位系l)如果存放在偶地址开始的地方Q那 么一个读周期可以读32bitQ而如果存攑֜奇地址开始的地方Q就需?个读周期Qƈ对两ơ读出的l果的高低字节进行拼凑才能得到该32bit? 据。显然在d效率上下降很多?/p>

?字节寚w对程序的影响:

    先让我们看几个例子吧(32bit,x86环境,gcc~译?:
讄构体如下定义Q?br />struct A
{
    int a;
    char b;
    short c;
};
struct B
{
    char b;
    int a;
    short c;
};
现在已知32位机器上各种数据cd的长度如?
char:1(有符hW号?    
short:2(有符hW号?    
int:4(有符hW号?    
long:4(有符hW号?    
float:4    double:8
那么上面两个l构大小如何?
l果?
sizeof(strcut A)gؓ8
sizeof(struct B)的值却?2

l构体A中包含了4字节长度的int一个,1字节长度的char一个和2字节长度的short型数据一?B也一?按理说A,B大小应该都是7字节?br />之所以出C面的l果是因为编译器要对数据成员在空间上q行寚w。上面是按照~译器的默认讄q行寚w的结?那么我们是不是可以改变编译器的这U默认对齐设|呢,当然可以.例如:
#pragma pack (2) /*指定?字节寚w*/
struct C
{
    char b;
    int a;
    short c;
};
#pragma pack () /*取消指定寚wQ恢复缺省对?/
sizeof(struct C)值是8?br />修改寚wgؓ1Q?br />#pragma pack (1) /*指定?字节寚w*/
struct D
{
    char b;
    int a;
    short c;
};
#pragma pack () /*取消指定寚wQ恢复缺省对?/
sizeof(struct D)gؓ7?br />后面我们再讲?pragma pack()的作?

?~译器是按照什么样的原则进行对齐的?

    先让我们看四个重要的基本概念Q?br />1.数据cd自n的对齐|
  对于char型数据,其自w对齐gؓ1Q对于short型ؓ2Q对于int,float,doublecdQ其自n寚wgؓ4Q单位字节?br />2.l构体或者类的自w对齐|其成员中自n寚w值最大的那个倹{?br />3.指定寚w?/font>Q?pragma pack (value)时的指定寚w值value?br />4.数据成员、结构体和类的有效对齐|自n寚w值和指定寚wg的那个倹{?br />? 了这些|我们可以很方便的来讨论具体数据l构的成员和其自w的寚w方式。有效对齐值N是最l用来决定数据存攑֜址方式的|最重要。有效对齐NQ就? 表示“对齐在N上”,也就是说该数据的"存放起始地址%N=0".而数据结构中的数据变量都是按定义的先后顺序来排放的。第一个数据变量的起始地址是? 据结构的起始地址。结构体的成员变量要寚w排放Q结构体本n也要Ҏ自n的有效对齐值圆?是l构体成员变量占用总长度需要是对结构体有效寚w值的整数 倍,l合下面例子理解)。这样就不能理解上面的几个例子的g?br />例子分析Q?br />分析例子BQ?br />struct B
{
    char b;
    int a;
    short c;
};
? 设B从地址I间0x0000开始排放。该例子中没有定义指定对齐|在笔者环境下Q该值默认ؓ4。第一个成员变量b的自w对齐值是1Q比指定或者默认指? 寚w?,所以其有效寚wgؓ1Q所以其存放地址0x0000W合0x0000%1=0.W二个成员变量aQ其自n寚wgؓ4Q所以有效对齐g?Q? 所以只能存攑֜起始地址?x0004?x0007q四个连l的字节I间中,复核0x0004%4=0,且紧靠第一个变量。第三个变量c,自n寚wgؓ 2Q所以有效对齐g?Q可以存攑֜0x0008?x0009q两个字节空间中Q符?x0008%2=0。所以从0x0000?x0009存放? 都是B内容。再看数据结构B的自w对齐gؓ其变量中最大对齐?q里是bQ所以就?Q所以结构体的有效对齐g?。根据结构体圆整的要求, 0x0009?x0000=10字节Q(10Q?Q%4Q?。所?x0000A?x000B也ؓl构体B所占用。故B?x0000?x000B 共有12个字?sizeof(struct B)=12;其实如果p一个就来说它已满_节对齐了, 因ؓ它的起始地址?,因此肯定是对齐的,之所以在后面补充2个字?是因为编译器Z实现l构数组的存取效?试想如果我们定义了一个结构B的数l?? 么第一个结构v始地址?没有问题,但是W二个结构呢?按照数组的定?数组中所有元素都是紧挨着?如果我们不把l构的大补充ؓ4的整数?那么下一 个结构的起始地址是0x0000A,q显然不能满结构的地址寚w?因此我们要把l构补充成有效对齐大的整数?其实诸如:对于char型数据,? 自n寚wgؓ1Q对于short型ؓ2Q对于int,float,doublecdQ其自n寚wgؓ4Q这些已有类型的自n寚wg是基于数l考虑?? 是因些类型的长度已知?所以他们的自n寚wg已知了.
同理,分析上面例子CQ?br />#pragma pack (2) /*指定?字节寚w*/
struct C
{
    char b;
    int a;
    short c;
};
#pragma pack () /*取消指定寚wQ恢复缺省对?/
W? 一个变量b的自w对齐gؓ1Q指定对齐gؓ2Q所以,其有效对齐gؓ1Q假设C?x0000开始,那么b存放?x0000Q符?x0000%1= 0;W二个变量,自n寚wgؓ4Q指定对齐gؓ2Q所以有效对齐gؓ2Q所以顺序存攑֜0x0002?x0003?x0004?x0005四个q箋 字节中,W合0x0002%2=0。第三个变量c的自w对齐gؓ2Q所以有效对齐gؓ2Q顺序存?br />?x0006?x0007中,W合 0x0006%2=0。所以从0x0000?x00007共八字节存放的是C的变量。又C的自w对齐gؓ4Q所以C的有效对齐gؓ2。又8%2=0,C 只占?x0000?x0007的八个字节。所以sizeof(struct C)=8.

?如何修改~译器的默认寚w?

1.在VC IDE中,可以q样修改Q[Project]|[Settings],c/c++选项卡Category的Code Generation选项的Struct Member Alignment中修改,默认?字节?br />2.在编码时Q可以这样动态修改:#pragma pack .注意:是pragma而不是progma.

?针对字节寚w,我们在编E中如何考虑?


    如果在编E的时候要考虑节约I间的话,那么我们只需要假定结构的首地址?,然后各个变量按照上面的原则进行排列即?基本的原则就是把l构中的变量按照 cd大小从小到大声明,量减少中间的填补空?q有一U就是ؓ了以I间换取旉的效?我们昄的进行填补空间进行对?比如:有一U用空间换旉? 法是昑ּ的插入reserved成员Q?br />         struct A{
           char a;
           char reserved[3];//使用I间换时?br />           int b;
}

reserved成员Ҏ们的E序没有什么意?它只是v到填补空间以辑ֈ字节寚w的目?当然即不加q个成员通常~译器也会给我们自动填补寚w,我们自己加上它只是v到显式的提醒作用.

?字节寚w可能带来的隐?

    代码中关于对齐的隐患Q很多是隐式的。比如在强制cd转换的时候。例如:
unsigned int i = 0x12345678;
unsigned char *p=NULL;
unsigned short *p1=NULL;

p=&i;
*p=0x00;
p1=(unsigned short *)(p+1);
*p1=0x0000;
最后两句代码,从奇数边界去讉Kunsignedshort型变量,昄不符合对齐的规定?br />在x86上,cM的操作只会媄响效率,但是在MIPS或者sparc上,可能是一个error,因ؓ它们要求必须字节寚w.

?如何查找与字节对齐方面的问题:

如果出现寚w或者赋值问题首先查?br />1. ~译器的big little端设|?br />2. 看这U体pLw是否支持非寚w讉K
3. 如果支持看设|了寚w与否,如果没有则看讉K旉要加某些Ҏ的修饰来标志其特D访问操作?/p>

?相关文章:转自http://blog.csdn.net/goodluckyxl/archive/2005/10/17/506827.aspx

 ARM下的寚w处理
from DUI0067D_ADS1_2_CompLib

3.13 type  qulifiers

有部分摘自ARM~译器文档对齐部?/p>

寚w的?
1.__align(num)
   q个用于修改最高别对象的字节边界。在汇编中用LDRD或者STRD?br />   p用到此命令__align(8)q行修饰限制。来保证数据对象是相应对齐?br />   q个修饰对象的命令最大是8个字节限?可以?字节的对象进?字节
   寚w,但是不能?字节的对?字节寚w?br />   __align是存储类修改,他只修饰最高cd对象不能用于l构或者函数对象?br />  
2.__packed
  __packed是进行一字节寚w
  1.不能对packed的对象进行对?br />  2.所有对象的d讉K都进行非寚w讉K
  3.float及包含float的结构联合及未用__packed的对象将不能字节寚w
  4.__packed对局部整形变量无影响
  5.强制由unpacked对象向packed对象转化是未定义,整Ş指针可以合法?br />  义ؓpacked?br />     __packed int* p;  //__packed int 则没有意?br />  6.寚w或非寚wd讉K带来问题
  __packed struct STRUCT_TEST
 {
  char a;
  int b;
  char c;
 }  ;    //定义如下l构此时b的v始地址一定是不对齐的
         //在栈中访问b可能有问?因ؓ栈上数据肯定是对齐访问[from CL]
//下面变量定义成全局静态不在栈?
static char* p;
static struct STRUCT_TEST a;
void Main()
{
 __packed int* q;  //此时定义成__packed来修饰当前q指向为非寚w的数据地址下面的访问则可以

 p = (char*)&a;         
 q = (int*)(p+1);     
 
 *q = 0x87654321;
/*  
得到赋值的汇编指o很清?br />ldr      r5,0x20001590 ; = #0x12345678
[0xe1a00005]   mov      r0,r5
[0xeb0000b0]   bl       __rt_uwrite4  //在此处调用一个写4byte的操作函?
     
[0xe5c10000]   strb     r0,[r1,#0]   //函数q行4ơstrb操作然后q回保证了数据正的讉K
[0xe1a02420]   mov      r2,r0,lsr #8
[0xe5c12001]   strb     r2,[r1,#1]
[0xe1a02820]   mov      r2,r0,lsr #16
[0xe5c12002]   strb     r2,[r1,#2]
[0xe1a02c20]   mov      r2,r0,lsr #24
[0xe5c12003]   strb     r2,[r1,#3]
[0xe1a0f00e]   mov      pc,r14
*/

/*
如果q没有加__packed修饰则汇~出来指令是q样直接会导致奇地址处访问失?br />[0xe59f2018]   ldr      r2,0x20001594 ; = #0x87654321
[0xe5812000]   str      r2,[r1,#0]
*/

//q样可以很清楚的看到非对齐访问是如何产生错误?br />//以及如何消除非对齐访问带来问?br />//也可以看到非寚w讉K和对齐访问的指o差异D效率问题
}


erran 2007-10-16 22:56 发表评论
]]>
转:C++对象内存布局http://www.shnenglu.com/erran/archive/2007/10/14/34184.htmlerranerranSat, 13 Oct 2007 16:37:00 GMThttp://www.shnenglu.com/erran/archive/2007/10/14/34184.htmlhttp://www.shnenglu.com/erran/comments/34184.htmlhttp://www.shnenglu.com/erran/archive/2007/10/14/34184.html#Feedback0http://www.shnenglu.com/erran/comments/commentRss/34184.htmlhttp://www.shnenglu.com/erran/services/trackbacks/34184.html引用Qhttp://www.shnenglu.com/stdyh/archive/2007/01/08/17442.html

C++对象内存布局


写这个文章完全是因ؓ惌搞清?vc 怎么布局每个 c++ 对象,以及怎样完成指针的{换的q程.
  先问一个问?两个不同cd的指针相互{换以?他们在数g是一L?比如:

    int nValue = 10;
    int *pInt = &nValue;
    void *pVoid = pInt;
    char *pChar = (char*)pInt;


   q些指针的?不是说指针指向的内存的内?是一L? 如果你的回答? yes,那如果是一个类的承体pd?在承类向基c{换的q程?指针的数D是不变化的么?如果你的回答?不一定会变化,要看cȝ体系是怎么设计? "的话,那恭喜你,不用看下M.如果你还不确定究竟变q是不变,I竟哪些?哪些不变,I竟Z么要变ؓ什么不变的?接着看下?

   c++ 标准不规?c++ 实现的时候的对象的具体的内存布局,除了在某些方面有的限制以外,c++ 对象在内存里面的布局完全是由~译器自行决?q里我也只是讨论 vc++ .net 2003 build 7.1.3091 的实现方?我ƈ没有?vc5 vc6 vc.net 2002 以及其他?2003 build 上面做过试,l论也许不适合那些~译q_.q些属于~译器具体实?ms 保留有在不通知你我的情况下作出更改的权?废话q么?马上开?

  对于 c 的内建指针的转换,l果是不用多讨论?我们只是讨论 c++ 的对?从最单的开?

    class CBase
    {
    public:
      int m_nBaseValue;
    };


  q样的一个类在内存里攄是非常简单的,他占??bytes 的空?不用多说,我们从他z一个类出来.

    class CDerive1 : public CBase
    {
    public:
      int m_nDerive1Value;
    };


   CDerive1 的对象在内存里面是怎么攄? 也很?占有8?bytes 的空???bytes 属于 CBase c?后四? bytes 属于自己.一个CDerive1 的指针{换成一?CBase 的指?l果是一L.下面我们加上多重l承看看.

    class CFinal : public CDerive,public CBase // q里?CDerive 是一个和 CBase 差不多的基类
    {
    public:
      int m_nFinalValue;
    };


   CFinal 的对象在内存里面的布局E微复杂一?但是也很Ҏ惌,他占?12 ?bytes 的空??个属? CDerive,中间4个属?CBase,后面4个才是自q.那一?CFinal 的指针{换成一?CDerive 指针,数g变么? 转换成一?CBase 指针?又会变化?{案?前一个不?后一个要变化,道理非常的明?CFinal 对象的开头刚好是一? CDerive 对象,?CBase 对象却在 CFinal 对象的中?自然是要变化的了,具体怎么变化? ?4 ? ok(自然要检查是否是I指?.

    CBase *pBase = pFinal ? (CBase*)((char*)pFinal + sizeof(CDerive)) : 0;// 当你写下 pBase = pFinal 的时?其实是这L

  q种不带 virtual 的承就q么?只是加上一?offset 而已.下面我们看看如果加上 virtual function 的时候是什么样子的?
q是从简单类开?

    class CBase
    {
    public:
      virtual void VirtualBaseFunction(){}
      int m_nBaseValue;
    };


   q里L没有使用 virtual destructor,因ؓq个函数E微有些不同.q是同样的问?CBase cd内存上占多大的空?q是 4 bytes ? {案?no, 在我的编译器上面?8 bytes,多出来的 4 bytes ?__vfptr(watch H口看见的名?,他是一个指?指向了类?vtable,那什么是 vtable ?他是用来q什么的? vtable 是用来支? virtual function 机制?他其实是一个函数指针数l?q不{同于c/c++语言里面的指针数l?因ؓ他们的类型ƈ不一定是一L.)他的每一个元素都指向了一个你定义? virtual function,q样通过一个中间层来到辑֊态连~的效果,q些指针是在E序q行的时候准备妥当的,而不是在~译的时候准备妥当的,q个是动态联~的 目的,具体是由谁来讄q些指针的呢?constructor/destructor/copy constructor/assignment operator他们完成?不用奇?~译器会在你写的q些函数里面安插些必要的代码用来讄 vtable 的?如果你没有写q些函数,~译器会在适当的时候帮你生成这些函?明白一? vtable 是用来支?virtual function 机制?而需?virtual 机制的类基本上都会由一?__vfptr 指向他自q vtable.在调?virtual function的时?~译器这样完?

   pBase->VirtualBaseFunction(); => pBase->__vfptr[0]();// 0 是你的virtual function ?vtable 中的 slot number,~译器决?/font>

   现在应该很想?CBase 的大了?那这?__vfptr 是放C么位|的? ?m_nBaseValue 之前q是之后? 在我的编译器上看?是在之前,Z么要攑ֈ之前,是因为在通过 指向cL员函数的指针调用 virtual function 的时候能些代码(指汇~代?,q个原因q里׃深入讨论?有兴的同学可以看看 inside the c++ object model 一?
  接下?我们加上l承来看?

    class CDerive1 : public CBase
    {
    public:
      virtual void VirtualDerive1Function();
    };


   q个时候你也许要说,内存布局跟没?virtual 是一L,只不q每个类多了一?__vfptr 而已,?..q个是不对的,在我的编译器上面 两个cd享同一?__vfptr, vtable 里面放有两个指针,一个是两个cd享的,一个只属于 CDerive1 c?调用的时候如何呢?

   pDerive1->VirtualDerive1Function() => pDerive1->__vfptr[1]();
   pDerive1->VirtualBaseFunction() => pDerive1->__vfptr[0]();


  至于指针的相互{?数D是没有变化的(也正是追求这U效?所以把 __vfptr 攑ֈcȝ开?因ؓ调整 this 指针也是要占有运行时的时间的).

   现在加上多重l承瞧瞧,代码我不写上来了,p上面?CFinal, CDerive, CBase 体系一?只是每个cd一个VirtualxxxFunction出来,q个时候的指针调整q是没有什么变?所以我们只是看?vtable 的情?你会?CDerive ?CFinal ׃n一?__vfptr,?CBase 有一个自q __vfptr,?CFinal ? __vfptr ?2 个slot,q个l论是正的. 同时你也会说 通过 CFinal c调?CBase 的函数是要进行指针调整的,yes you'r right,不仅仅是 this 指针调整(?this 指针会成?function 的一个参?,q要调整 vtable 的?

   pFinal->VirtualBaseFunction() => (CBase*)((char*)pFinal + sizeof(CDerive))->__vfptr[0]();

   转换?asm 的代码大U是q样?

   mov eax,[pFinal] ; pFinal is a local object,pFinal will be epb - xx
   add eax,8 ; 8 = sizeof(CDerive)
   mov ecx,eax ; ecx is this pointer
   mov edx,[eax] ; edx = vtable address
   call [edx] ; call vtable[0]


  写到q里也就明白this指针是怎么调整??virtual function 的承也不复?this指针调整也是很简单的,下面看最复杂的部?virtual inheritance.

   我的~译器支持虚拟承的方式和虚函数的方式差不多,都是通过一?table 完成,只是q个q不到 vc 赋予的名字了,我们叫他 vbtable ?~译器同样在c里面加入一个指?vbtable 的指?我们叫他 __vbptr ?q个指针指向?vbtable ,? vbtable 里面的每一对应了一个基c?vbtable 记录了每个基cȝ某一个偏U量,通过q个偏移量就能计出具体cȝ指针的位|?看个单的例子:

   class CBase
   {
   public:
     virtual ~CBase(){}
   };

   class CMid1 : public virtual CBase
   {
   public:
     virtual ~CMid1(){}
     int m_nMid1;
   };

   class CMid2 : public virtual CBase
   {
   public:
     virtual ~CMid2(){}
     int m_nMid2;
   };

   class CFinal : public CMid1,public CMid2
   {
   public:
     virtual ~CFinal(){}
     int m_nFinal;
   };

   CFinal final;
   CFinal *pFinal = &final;    // pFinal = 0x0012feb4;
   CBase *pBase = pFinal; // pBase = 0x0012fec8 = pFinal + 0x14;
   CMid1 *pMid1 = pFinal; // pMid1 = 0x0012feb4 = pFinal;
   CMid2 *pMid2 = pFinal; // pMid2 = 0x004210b4 = pFinal;


   l果让你吃惊? 最奇怪的地方居然?CMid2 ?CMid1 的地址居然是一L,q个是因?vc ?vbtable 攑ֈ? CFinal cȝ开头的原因,而CMid1 ?CMid2 也同栯使用q个 vbtable, 所?q个三个的地址也就必须相同?? CBase 的地址是怎么出来的呢? ?..刚刚我们说了 vbtable 攑ֈ了CFinal 的开?vc 一定会攑֜开头吗?{案是不一?q个E后解释).在我的机器上?final 对应内存的第一?dword ? 0x00426030,查看q个地址,W一个dword ?0 ,W二个就?0x14,刚好?pBase 的偏Uȝ?q个只是巧合,也许你换个类的承体pd完全不同?但是我只是想说明一?基类的偏U计是?vbtable 的值相兌?下面我们来看看 vc 是怎么计算q些偏移?
  vc 在分析我们的代码的时?生成了一份类的承体pM?其中有一个叫 thisDisplacement 的_PMDl构:

    struct _PMD // total undocumented
    {
      int mdisp; // i think the meaning is Multiinheritance DISPlacement
      int pdisp; // Pointer to vbtable DISPlacement
      int vdisp; // Vbtable DISPlacement
    };


   l构的名字和成员变量的名字确实实是 vc 的名??watch H口输入 (_PMD*)0 p看到q个l构的详l信?,每个字段的含义却是我自己猜测出来?mdisp 大概用来表示多重l承(包括单一l承)的时候的偏移?pdisp 表示 vbtable 的偏U量,?vdisp 表示cd vbtable 里面的下?那么有了q个l构怎样才能完成指针的{换呢?假如我们有一个派生类指针 pFinal,要{换成一个特定的基础c?我们首先要知道和q个基类对应?_PMD l构的信?q个信息的获?我暂时没有找C个非常方便的Ҏ,现在我用的Ҏ下面会有描述),有了q个信息以后,转换方便了.首先扑ֈ vbtabel 的地址 *(pFinal + pdisp),然后扑ֈ基类的偏U?*(*(pFinal + pdisp) + vdisp) q个偏移值是相对vbtable?所以还要加?vbtable的偏U?最后加?mdisp的偏U?如下:

  char *pFinal = xxx; // need a init value
  char *pBase; // we must calc
  pBase = pFinal + mdisp + *(int *)(*(int *)(pFinal + pdisp) + vdisp) + pdisp;


  注意: ?pdisp < 0 的时候就表示q个cL?vbtable 直接使用 pFinal + mdisp 得到结果了.
  所以这个结构是一个通用的结?专门用作cd转换,不管是有无虚l承都能使用q个l构q行cd转换.

  通过q个l构,我们也能看到 vc 是怎样布局q个 object ?

  看到q里,也许你要大呼一口气,妈妈呀,一个类型{换要q么的麻烦吗?我直接写 pBase = pFinal 不就可以了吗? 恭喜你还没有被我忽悠得晕头{?哈哈.其实你写下那行语句的时?~译器在帮你做这个{?大约生成下面的代?br />
    mov eax,[pFinal] ;final address
    mov ecx,[eax] ; vbtable address *(int *)(pFinal + pdisp)
    mov edx,eax ; save to edx
    add edx,[ecx + 4] ; ecx + 4 is (*(int *)(pFinal + pdisp) + vdisp)
    mov [pBase],edx ; edx = pFinal + mdisp + *(int *)(*(int *)(pFinal + pdisp) + vdisp) + pdisp;
    ; here mdisp = 0, pdisp = 0, vdisp = 4


   也许你要说了,我要q些东西来干什?要{换的时候直接{换就好了,~译器会帮做,的确,大多数的时候确实是q样,但是,在某些时候却q不如此,现在? 要实C个功?输入一个指?输入一?_PMD l构,你要实现一个AdjustPointer 的函数来生成另一个指?q个时候你也只能这样完成了,因ؓ我没有给你两个指针的名字,ql了你字W串形式的名字也没有??...你也怼?办法 是有?的确是有,模板p实现q种功能,?.q个我们暂时不讨论具体的实现l节.也许你要问了,I竟什么时候会d现这U听都没有听q的功能,其实q? 个函数是真正存在?只不q不是由你来实现?而是 ms 的h实现?你只用写一?带有 c++ 异常的程?使用 ida 反汇~?然后查找函数,p扑ֈq个函数?他用来在异常处理时创?catch 所需要的 object.至于q个详细的信?h?我会最快速度写出关于 vc 是怎样实现 c++ 异常的文章来.

  最后了,说说那个 _PMD l构的获取方?看的时候不要吃?Ҏ比较的麻?比如我想知道?CFinal cȝ关的 _PMD 信息,先新建工?写下 throw pFinal q样的语?~译,在这个语句的地方讄断点,q行,转到反汇~?q入 __CxxThrowException@8 函数,q个时候不出意外你能看C个叫 pThrowInfo 的东?如果看不?h开"昄W号?选项),?watch H口里面输入pThrowInfo,展开?看到一个pCatchableTypeArray,记录下他? nCacthableTypes的?然后?watch 里面输入
pThrowInfo->pCatchableTypeArray->arrayOfCatchableTypes[0] ?pThrowInfo->pCatchableTypeArray->arrayOfCatchableTypes[n], n 是你刚刚记录的值减1,再展开他们,你就能看C?thisDisplacement 的数?l箋展开是 mdisp {等?很是ȝ??.你已l猜C,q个是和异常有关pȝ.

  后记: q段旉,我一直在M反汇~之后的代码,也颇有些心得,所以才有想法写一些文?探讨 vc ~译器鲜Zh?太过狂妄?的秘?q个斚w的文章也有h写过,那些文章也给我不的启发,我不认ؓ自己是第一个发现这些秘密的?但是臛_我自q? ?我是W一个把q些东西写出来的?文章里面作墨多的部分都是自己发现?p个文章里面的内容来说,inside the c++ object model 是有比较详细的描?但是他ƈ不是转换针对 vc q个~译器的实现,?_PMD q个l构我也没有在什么地方见有h描述q?只是? windows develop network ?002q?2月的杂志上看有h提到q这个结?可惜他却没有了解(臛_他在他发表文章的时候是如是说的)q个l构的用?正是因ؓq个原因,我才有写 q个文章以及后箋文章的冲?.所?q个文章也算是我自己的原创吧.q个文g虽然和游戏制造没有太大的关系,但是?T 自视清高,不愿意自q文章被一帮不懂的h评hȝ,所以也没有发到那些著名?xxx |站,只发 goldpoint.转蝲h明出??T 对自qW一个原创文章比较珍?比较重视,谢谢).




erran 2007-10-14 00:37 发表评论
]]>
转:关于调用U定(cdecl、fastcall、、thiscall) 的一点知?/title><link>http://www.shnenglu.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.shnenglu.com/erran/archive/2007/10/14/34182.html</guid><wfw:comment>http://www.shnenglu.com/erran/comments/34182.html</wfw:comment><comments>http://www.shnenglu.com/erran/archive/2007/10/14/34182.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/erran/comments/commentRss/34182.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/erran/services/trackbacks/34182.html</trackback:ping><description><![CDATA[ <div id="1111161" class="postbody"> <div id="1116111" class="tit">引用Qhttp://www.shnenglu.com/oosky/archive/2007/01/08/17422.html<br /><br />函数调用规范<br /><br /><div id="vjtlfj5" class="cnt"><p align="left">当高U语a函数被编译成机器码时Q有一个问题就必须解决Q因为CPU没有办法知道一个函数调用需要多个、什么样的参数。即计算Z知道怎么l这个函C递参敎ͼ<font color="#0000ff">传递参数的工作必须由函数调用者和函数本n来协?/font>。ؓ此,计算机提供了一U被UCؓ栈的数据l构来支持参C递?</p><p align="left">   函数调用Ӟ调用者依ơ把参数压栈Q然后调用函敎ͼ函数被调用以后,在堆栈中取得数据Qƈq行计算。函数计结束以后,或者调用者、或者函数本w修改堆栈,使堆栈恢复原装。在参数传递中Q有两个很重要的问题必须得到明确说明Q?/p><p align="left"> 1) 当参C数多于一个时Q按照什么顺序把参数压入堆栈Q?br />2) 函数调用后,p来把堆栈恢复原装?br /><font color="#0000ff" size="2">3Q函数的q回值放在什么地?/font></p>在高U语a中,通过函数<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 很多时候被UCؓpascal调用规范Q因为pascal是早期很常见的一U教学用计算机程序设计语aQ其语法严}Q用的函数调用U定是stdcall? 在Microsoft C++pd的C/C++~译器中Q常常用PASCAL宏来声明q个调用U定Q类似的宏还有WINAPI和CALLBACK?</p><p align="left">stdcall调用规范声明的语法ؓQ?/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的调用约定意味着Q?</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"> 1Q参C叛_左压入堆栈;<br /> 2Q函数自w修改堆栈;<br /> 3) 函数名自动加前导的下划线Q后面紧跟一个@W号Q其后紧跟着参数的尺寸?/font><br /></pre></div><div align="left">以上q这个函Cؓ例,参数b首先被压栈,然后是参数aQ函数调用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 W二个参数入?br />   push 1 W一个参数入?br />   call function 调用参数Q注意此时自动把cs:eip入栈</font></pre></div><div align="left">而对于函数自w,则可以翻译ؓQ?</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寄存器,该寄存器用来保存堆栈的栈顶指针Q可以在函数退出时恢复<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">而在~译Ӟq个函数的名字被译成_function@8 </p><p align="left">注意不同~译器会插入自己的汇~代码以提供~译的通用性,但是大体代码如此。其中在函数开始处保留esp到ebp中,在函数结束恢复是~译器常用的Ҏ?</p><p align="left">从函数调用看Q??依次被pushq堆栈,而在函数中又通过相对于ebp(卛_q函数时的堆栈指针)的偏U量存取参数。函数结束后Qret 8表示清理8个字节的堆栈Q函数自己恢复了堆栈?</p><h2 align="left"> <font size="4">cdecl调用规范</font></h2><p align="left">cdecl调用U定又称为C调用U定Q是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调用U定</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调用U定</font></font></pre></div><p align="left">  cdecl调用U定的参数压栈顺序是和stdcall是一LQ参数首先由有向左压入堆栈。所不同的是Q函数本w不清理堆栈Q调用者负责清理堆栈。由于这 U变化,C调用U定允许函数的参数的个数是不固定的,q也是C语言的一大特艌Ӏ对于前面的function函数Q用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 注意Q这里调用者在恢复堆栈<br />   被调用函数_function?br />   push ebp 保存ebp寄存器,该寄存器用来保存堆栈的栈顶指针Q可以在函数退出时恢复<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 注意Q这里没有修改堆?/font></pre></div><p align="left">MSDN中说Q该修饰自动在函数名前加前导的下划线Q因此函数名在符可中被记录为_function?<br /></p><p align="left">׃参数按照从右向左序压栈Q因此最开始的参数在最接近栈顶的位|,因此当采用不定个数参数时Q第一个参数在栈中的位|肯定能知道Q只要不定的参数个数能够ҎW一个后者后l的明确的参数确定下来,可以用不定参敎ͼ例如对于sprintf函数Q定义ؓQ?/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定Q因此用不定个数的参数是没有问题的?</div><h2 align="left"> <font size="4">fastcall调用规范</font></h2><div align="left">fastcall调用U定和stdcallcMQ它意味着Q?</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) 函数的第一个和W二个DWORD参数Q或者尺寸更的Q通过ecx和edx传递,其他参数通过从右向左的顺序压栈;<br /> 2) 被调用函数清理堆栈;<br /> 3) 函数名修改规则同stdcall?/font></pre></div><div align="left">其声明语法ؓQint __fastcall function(int a,int b) </div><h2 align="left"> <font size="4">thiscall调用规范</font></h2><p align="left">thiscall是唯一一个不能明指明的函数修饰Q因为thiscall不是关键字。它是C++cL员函数缺省的调用U定。由于成员函数调用还有一个this指针Q因此必ȝD处理,thiscall意味着Q?</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) 参数从右向左入栈Q?br /> 2) 如果参数个数定Qthis指针通过ecx传递给被调用者;如果参数个数不确定,this指针在所有参数压栈后被压入堆栈;<br /> 3) 对参CC定的Q调用者清理堆栈,否则函数自己清理堆栈?/font></pre></div><div align="left">Z说明q个调用U定Q定义如下类和用代码: </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 < 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函数被翻译成汇编后就变成Q?</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 注意Q这里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] q里引入this指针<br />   00401C34 push eax<br />   00401C35 call function2<br />   00401C3A add esp,14h</font></pre></div><div align="left"><font size="2">可见Q对于参C数固定情况下Q它cM于stdcallQ不定时则类似cdecl</font></div><h2 align="left"> <font size="4">naked call调用规范</font></h2><div align="left">q是一个很见的调用约定,一般程序设计者徏议不要用。编译器不会l这U函数增加初始化和清理代码,更特D的是,不能用returnq回q回|只能用插入汇~返回结果。这一般用于实模式驱动E序设计Q假讑֮义一个求和的加法E序Q可以定义ؓQ?</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">注意Q这个函数没有显式的returnq回|q回通过修改eax寄存器实玎ͼ而且q退出函数的ret指o都必L式插入。上面代码被译成汇~以后变成: </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">注意q个修饰是和__stdcall及cdecll合使用的,前面是它和cdecll合使用的代码,对于和stdcalll合的代码,则变成: </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">//注意后面?</font><br />    }</font></pre></div><div align="left">至于q种函数被调用,则和普通的cdecl及stdcall调用函数一致?</div><h2 align="left"> <font size="4">函数调用U定D的常见问?/font></h2><div align="left">如果定义的约定和使用的约定不一_则将D堆栈被破坏,D严重问题Q下面是两种常见的问题: </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) 函数原型声明和函C定义不一?br /> 2) DLL导入函数时声明了不同的函数约?/font></pre></div></div></div> </div> <br /> <br /> <img src ="http://www.shnenglu.com/erran/aggbug/34182.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/erran/" target="_blank">erran</a> 2007-10-14 00:33 <a href="http://www.shnenglu.com/erran/archive/2007/10/14/34182.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转:C++资源之不完全导引Q完整版Q?/title><link>http://www.shnenglu.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.shnenglu.com/erran/archive/2007/10/14/34178.html</guid><wfw:comment>http://www.shnenglu.com/erran/comments/34178.html</wfw:comment><comments>http://www.shnenglu.com/erran/archive/2007/10/14/34178.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/erran/comments/commentRss/34178.html</wfw:commentRss><trackback:ping>http://www.shnenglu.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 id="jtph3fp" class="bvTitle" id="subjcns!1p5qP-LmQlonNx_ujZCY3OgA!128"> <strong> <font size="3">C++资源之不完全导引Q完整版Q?/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++资源之不完全导引Q完整版Q?/p> <p>来源Q?a ><u><font color="#0000ff">www.csdn.net</font></u></a></p> <p>撰文Q曾毅、陶?/p> <p>声明Q本?004q?月首发于《CSDN开发高手》,版权归该杂志与《程序员》杂志社<br />所有?/p> <p>------------------------------------------------------------------------<br />--------</p> </td> </tr> </tbody> </table> <p>  1Q前a</p> <p>  无数ơ听到“我要开始学习C++!”的呐喊Q无数次听到“C++太复杂了Q我真的<br />学不会”的无奈。Stan Lippman先生曑֜《C++ Primer》一书中指出“C++是最为难<br />学的高E序设计语言之一”,Z常将“之一”去掉以表达自己对C++的敬畏。诚<br />ӞC++E序设计语言对于学习者的有很多难以逾越的`沟,体系l构的庞大,?br />接不暇ƈ不断扩充的特性……除此之外,参考资料之多与冗杂使它的学习者望而却<br />步,Ʋ求深入者苦不堪a。希望这一份不完全导引能够成ؓ您C++学习之\上的引\<br />灯?/p> <p>  撰写本文的初衷ƈ不打带领大家体验古老的C++历史Q如果你想了解C++的历<br />史与其前期发展中诸多技术的演变Q你应当d考Bjarne的《The Design and Evo<br />lution of C++》。当然也不打给大家一个无所不包的宝典(q不想Q其一是因<br />水^有限Q其二无奈C++之博大精深)Q所l出的仅仅是一些我们认为对于想学习C<br />++的广大读者来说最重要q且触手可及的开发与学习资源?/p> <p>  本文介绍q分析了一些编译器Q开发环境,库,量的书c以及参考网站,q?br />且尽可能试着l出一个利用这些资源的导引Q望对如同我们一L初学者能够有<br />所裨益?/p> <p>------------------------------------------------------------------------<br />--------</p> <p>  2Q编译器</p> <p>  在C++之外的Q何语a中,~译器都从来没有受到q如此之重视。因为C++是一<br />门相当复杂的语言Q所以编译器也难于构建。直到最q我们才开始能够用上完全<br />W合C++标准的编译器Q哦Q你可能会责怪那些编译器厂商不能早的提供符合标?br />的编译器Q这只能怪他们各自维pȝ自n的一套别Z愿接受的标准Q。什么??br />说这无关紧要Q哦Q不Q你所需要的是和标准化C++高度兼容的编译环境。长q来?br />Q只有这L~译器对C++开发h员来说才是最有意义的工具Q尤其是对于E序设计<br />语言的学习者。一x让代码具备可移植性,q让一门语a及其库的应用更ؓq泛<br />。嗯Q是的,我们q里只打介l一些公认的优秀~译器?/p> <p>  2.1 Borland C++</p> <p>  q个是Borland C++ Builder和Borland C++ Builder Xq两U开发环境的后台<br />~译器。(哦,我之所以将之分ZU开发环境你应当能明白ؓ什么,正如Delphi<br />7到Delphi8的{变,是革命性的两代。)Borland C++p牌开发工具厂商Borland<br />們֊打造。该公司的编译器素以速度快,I间效率高著UͼBorland C++ pd~译<br />器秉承了q个传统Q属于非怼质的~译器。标准化斚w早在5.5版本的编译器中对<br />标准化C++的兼容就辑ֈ?2.73%。目前最新版本是Borland C++ Builder X中的6.<br />0版本Q官方称100%W合ANSI/ISO的C++标准以及C99标准。嗯…这正是我前面所指的<br />“完全符合C++标准的编译器”?/p> <p>  2.2 Visual C++</p> <p>  q个正是我们熟知的Visual Studio ?Visual Studio.net 2002, 2003以及2<br />005 Whidbey中带的C++~译器。由Microsoft公司研制。在Visual Studio 6.0中,<br />因ؓ~译器有太多地方不能与后来出现的C++标准相吻合而饱受批评(x你在使用<br />STL的时候编译时报出的那些o人厌恶的error和warning吧)。VC++6.0Ҏ准化C+<br />+的兼容只?3.43%。但是随着C++~译器设计大师Stanley Lippman以及诸多C++C?br />达人的加盟Q在Visual Studio.NET 2003中,Visual C++~译器已l成Z个非<br />常成熟可靠的C++~译器了。Dr.Dobb's Journal的评显CVisual C++7.1Ҏ准C<br />++的兼Ҏ高?8.22%Q一度成为CBX之前兼容性最好的~译器。结合强大的Visua<br />l Studio.NET开发环境,是一个非怸错的选择。至于Whidbey时代的Visual C++,<br />g微Y所最x的是C++/CLI……我们不惌论微软下一代的C++~译器对标准?br />兼容如何Q但他确实越来越适合.NET (其实你和我的感觉可能是一LQ微软不?br />当把标准C++q块肥肉丢给Borland,然而微软可能ƈ不这栯??/p> <p>  2.3 GNU C++</p> <p>  著名的开源C++~译器。是cUnix操作pȝ下编写C++E序的首选。特Ҏ有非<br />常好的移植性,你可以在非常q泛的^C使用它,同时也是~写跨^収ͼ嵌入?br />E序很好的选择。另外在W合标准q个斚w一直都非常好,GCC3.3大概能够辑ֈ96<br />.15%。但是由于其跨^台的Ҏ,在代码尺寔R度{优化上略微差一炏V?/p> <p>  ZGNU C++的编译器有很多,比如Q?/p> <p>  (1) Mingw</p> <p>  <a ><u><font color="#0000ff">http://www.mingw.org/</font></u></a></p> <p>  GCC的一个Windows的移植版本(Dev-C++的后収ͼ</p> <p>  (2) Cygwin</p> <p>  <a ><u><font color="#0000ff">http://sources.redhat.com/cygwin/</font></u></a></p> <p>  GCC的另外一个WindowsUL版本是Cygwin的一部分QCygwin是Windows下的一?br />Unix仿真环境。严格的说是模拟GNU的环境,q也是"Gnu's Not Unix"要表辄?br />思,噢,扯远了,qƈ不是我们在这里关心的实质内容?/p> <p>  (3) Djgpp</p> <p>  <a ><u><font color="#0000ff">http://www.delorie.com/djgpp/</font></u></a></p> <p>  q是GCC的DOSUL版本?/p> <p>  (4) RSXNT</p> <p>  <a ><u><font color="#0000ff">http://www.mathematik.uni-bielefeld.de/~rainer/</font></u></a></p> <p>  q是GCC的DOS和WindowsUL版本?/p> <p>  (5) Intel C++</p> <p>  著名CPU刉厂商Intel出品的编译器QSpecial Design for Intel x86Q对?br />Intel x86l构的CPUl过特别的优化。在有些应用情况下,特别是数D等高?br />能应用,仅仅采用Intel的编译器~译p大幅度的提高性能?/p> <p>  (6) Digital Mars C++</p> <p>  |络上提供免费下载,Zortech/Symantec C++的承者,其前w在当年惨烈?br />C++四国战中也是主角之一?/p> <p>------------------------------------------------------------------------<br />--------</p> <p>  3Q开发环?/p> <p>  开发环境对于程序员的作用不a而喻。选择自己朝夕相处的环境也不是Ҏ?br />事情Q特别是在IDE如此丰富的情况下。下面就是我们推荐的一些常见的C++开发环<br />境,q没有包括一些小型的Q罕见的IDE。其中Q何一N是功能丰富,可以用作?br />常开发用的。对于不同层面的开发者,请参见内文关于适用对象的描q?/p> <p>  3.1 Visual Studio 6.0</p> <p>  q个虽然是Microsoft公司的老版本的开发环境,但是鉴于其后l版本Visual<br />Studio.NET的庞大nw,以及初学者ƈ不那么高的功能要求,所以推荐这个开发环<br />境给C++的初学者,供其学习C++的最基本的部分,比如C的那部分子集Q当然你别指<br />望他能够支持最新的C99标准。在日常的开发中Q仍然有很多公司使用q个l典E_<br />的环境,比如W者就看曾亲见有些公司其~译器替换ؓGCC做手机开发之用?/p> <p>  3.2 Visual Studio.NET 2003</p> <p>  作ؓMicrosoft公司官方正式发布的最新版本开发环境,其中有太多激动h心的<br />功能。结合其最新的C++~译器。对于机器配|比较好的开发h员来_使用q个开<br />发环境将能满_大部分的要求。这里不打算单独说Visual Studio Whidbey,虽然<br />Visual Studio .NET 2005 - WhidbeyC֌预览版已l推出,但暂不是很稳定,读?br />可以亲nM验?/p> <p>  3.3 Borland C++ Builder 6</p> <p>  q个q不是Borland的C++开发环境的最新版本。选择它的原因是它不是用Java<br />写的IDEQ速度比较快。它有一个很完善的GUIH体设计器,和Delphiq一个VCL?br />׃q些特点Q比较适合初学者上手。但是由于其GUI的中心位|,可能不利于对?br />C++语言的学习。而且其ؓ了支持VCLq个Object Pascal写的库也对C++q行了一?br />U有的扩充。得h们有一个不得不接受的事实:“Borland C++ Builder 6的高?br />几乎都是Delphi高手”?/p> <p>  3.4 Borland C++ Builder X</p> <p>  正如前文所qͼ虽然版本号上和前面那个IDE非常相象Q但是其实它们是完全?br />同的两个集成开发环境。C++Builder更多的是一个和Delphi同步的C++版本的开发环<br />境,C++BuilderX则是完全从C++的角度思考得出的一个功能丰富的IDE。其最大的?br />Ҏ跨^収ͼ跨编译器Q多UFramework的集成,q且有一个WxWindows为基的GU<br />I设计器。尤其是采用了纯C++来重写了整个Framework,摒弃了以前o人无奈的版本<br />。对于C++的开发来_从编译器Q到库,到功能集成都是非常理想的。可以预见,<br />Borland C++ Builder X 2.0很值得C++爱好者期待。唯一令h隑֠之处是作Z?br />C++的开发工P其IDE是用Java写的Q在配置不够理想的机器上h重考虑再安?br />?/p> <p>  3.5 Emacs + GCC</p> <p>  前面讲的大部分是Windows环境下的集成开发环境。Linux上的开发者更們֐?br />使用Emacs来编辑C++的文Ӟ用Makefile来命令GCC做编译。虽然看上去比较松散Q?br />但是q些东西l合hq是一个开0发环境。如果你能够娴熟的用这L环境写程<br />序,你的水^应该_指导我们来写q篇陋文了?/p> <p>  3.6 Dev C++</p> <p>  GCC是一个很好的~译器。在Windows上的C++~译器一直和标准有着一D距ȝ<br />时候,GCC是一个让Windows下开发者流口水的编译器。Dev-C++是能够让GCC?br />在Windows下的工具Q作为集成开发环境,q提供了同专业IDE相媲的语法高亮Q?br />代码提示Q调试等功能。由于用Delphi开发,占用内存,速度很快Q比较适合<br />轻量U的学习和用?/p> <p>  3.7 Eclipse + CDT</p> <p>  Eclipse可是q来大名鼎鼎的开发工兗最C期的Jolt大奖颁l了q个杰出<br />的神物。说其神奇是因ؓQ它本n是用Java写的Q但是拥有比一般Java写的E序?br />得多的速度。而且因ؓ其基于插件组装一切的原则Q得能够有CDTq样的插件把E<br />clipse变成一个C/C++的开发环境。如果你一直用Eclipse写Java的程序,不妨用它<br />体验一下C++开发的乐趣?/p> <p>------------------------------------------------------------------------<br />--------</p> <p>  4Q工?/p> <p>  C++的辅助工L多,我们分门别类的ؓ大家作介l:</p> <p>  4.1 文档c?/p> <p>  (1) Doxygen</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.doxygen.org</font></u></a></p> <p>  Doxygen是一U适合C风格语言Q如C++、C、IDL、Java甚至包括C#和PHPQ的?br />开放源码的、基于命令行的文档生器?/p> <p>  (2) C++2HTML</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.bedaux.net/cpp2html/</font></u></a></p> <p>  把C++代码变成语法高亮的HTML</p> <p>  (3) CodeColorizer</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.chami.com/colorizer/</font></u></a></p> <p>  它能把好几种语言的源代码着色ؓHTML</p> <p>  (4) Doc-O-Matic</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.doc-o-matic.com/</font></u></a></p> <p>  Doc-O_MaticZ的C/C++QC++.netQDelphi/Pascal, VB.NETQC#和JavaE序<br />或者组件生准的文档。Doc-O-Matic使用源代码中的符号和注释以及外部的文?br />文g创徏与流行的文档样式一致的文档?/p> <p>  (5) DocVizor</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.ucancode.net/Products/DocBuilder/Features.htm</font></u></a></p> <p>  DocVizor满了面向对象Y件开发者的基本要求——它让我们能够看到C++工程<br />中的cdơ结构。DocVizor快速地产生完整可供打印的类层次l构图,包括从第?br />方库中来的那些类Q除此之外DocVizorq能从类信息中生HTML文g?/p> <p>  (6) SourcePublisher C++</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.scitools.com/sourcepublisher_c.html</font></u></a></p> <p>  l源代码产生提供快速直观的HTML报表Q包括代码,cdơ结构,调用和被?br />用树Q包含和被包含树。支持多U操作系l?/p> <p>  (7) Understand</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.scitools.com/ucpp.html</font></u></a></p> <p>  分析M规模的C或者C++工程Q帮助我们更好的理解以及~写文档?/p> <p>  4.2 代码c?/p> <p>  (1) CC-Rider</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.cc-rider.com</font></u></a></p> <p>  CC-Rider是用于C/C++E序强大的代码可视化工具Q通过交互式浏览、编辑及?br />动文件来促进E序的维持和发展?/p> <p>  (2) CodeInspect</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.yokasoft.com/</font></u></a></p> <p>  一U新的C/C++代码分析工具。它查我们的源代码找出非标准的,可能的,?br />及普通的错误代码?/p> <p>  (3) CodeWizard</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.parasoft.com</font></u></a></p> <p>  先进的C/C++源代码分析工P使用过500个编码规范自动化地标明危险的Q?br />但是~译器不能检查到的代码结构?/p> <p>  (4) C++ Validation Test Suites</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.plumhall.com/suites.html</font></u></a></p> <p>  一l用于测试编译器和库对于标准dE度的代码库?/p> <p>  (5) CppRefactory</p> <p>  参考站点:<a ><u><font color="#0000ff">http://cpptool.sourceforge.net/</font></u></a></p> <p>  CPPRefactory是一个得开发者能够重构他们的C++代码的程序。目的是使得C<br />++代码的重构能够尽可能的有效率和简单?/p> <p>  (6) Lzz</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.lazycplusplus.com/</font></u></a></p> <p>  Lzz是一个自动化许多C++~程中的体力zȝ工具。它能够节省我们许多事gq?br />且得编码更加有乐趣。给Zpd的声明,Lzz会给我们创徏头文件和源文件?/p> <p>  (7) QA C++ Generation 2000</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.programmingresearch.com/solutions/qacpp.htm</font></u></a></p> <p>  它关注面向对象的C++源代码,Ҏ关于设计Q效率,可靠性,可维护性的部分<br />提出警告信息?/p> <p>  (8) s-mail project - Java to C++DOL</p> <p>  参考站点:<a ><u><font color="#0000ff">http://sadlocha.strefa.pl/s-mail/ja2dol.html</font></u></a></p> <p>  把Java源代码翻译ؓ相应的C++源代码的命o行工兗?/p> <p>  (9) SNIP from Cleanscape Software International</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.cleanscape.net/stdprod/snip/index.html</font></u></a></p> <p>  一个填q编码和设计之间沟壑的易于用的C++开发工P节省大量~辑和调?br />的事Ӟ它还使得开发者能够指定设计模式作为对象模型,自动从对象模型中产生<br />C++的类?/p> <p>  (10) SourceStyler C++</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.ochresoftware.com/</font></u></a></p> <p>  对C/C++源代码提供完整的格式化和排版控制的工兗提供多?5个的格式化?br />以及完全支持ANSI C++?/p> <p>  4.3 ~译c?/p> <p>  (1) Compilercache</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.erikyyy.de/compilercache/</font></u></a></p> <p>  Compilercache是一个对你的C和C++~译器的装脚本。每ơ我们进行编译,?br />装脚本,把编译的l果攑օ~存Q一旦编译相同的东西Q结果将从缓存中取出而不<br />是再ơ编译?/p> <p>  (2) Ccache</p> <p>  参考站点:<a ><u><font color="#0000ff">http://ccache.samba.org/</font></u></a></p> <p>  Ccache是一个编译器~存。它使用h像C/C++~译器的~存预处理器Q编?br />速度通常能提高普通编译过E的5~10倍?/p> <p>  (3) Cmm (C++ with MultiMethods)</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.op59.net/cmm/cmm-0.28/users.html</font></u></a></p> <p>  q是一UC++语言的扩展。读入Cmm源代码输出C++的源代码Q功能是对C++语言<br />d了对multimethod的支持?/p> <p>  (4) The Frost Project</p> <p>  参考站点:<a ><u><font color="#0000ff">http://frost.flewid.de/</font></u></a></p> <p>  Forst使得你能够在C++E序中像原生的C++Ҏ一样用multimethod以及虚函<br />数参数。它是一个编译器的外壟?/p> <p>  4.4 试和调试类</p> <p>  (1) CPPUnit</p> <p>  CppUnit 是个Z LGPL 的开源项目,最初版本移植自 JUnitQ是一个非怼<br />U的开源测试框架。CppUnit ?JUnit 一样主要思想来源于极限编E。主要功能就<br />是对单元试q行理Qƈ可进行自动化试?/p> <p>  (2) C++Test</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.parasoft.com/</font></u></a></p> <p>  C++ Test是一个单元测试工P它自动化了C和C++c,函数或者组件的试?/p> <p> <br />  (3) Cantata++</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.iplbath.com/products/tools/pt400.shtml</font></u></a></p> <p>  设计的目的是Z满在合理的l济开销下用这个工具可以让开发工E师开<br />展单元测试和集成试的需?</p> <p>  (4) Purify</p> <p>  参考站点:<a ><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是一套完整的q行时分析工P旨在提高应用E序?br />可靠性和性能。PurifyPlus内存错误和泄漏、应用程序性能描述、代码覆?br />分析{功能组合在一个单一、完整的工具包中?/p> <p>  (5) BoundsChecker</p> <p>  BoundsChecker是一个C++q行旉误检和调试工具。它通过在Visual Studi<br />o内自动化调试q程加速开发ƈ且羃短上市的周期。BoundsChecker提供清楚Q详l?br />的程序错误分析,许多是对C++独有的ƈ且在staticQstack和heap内存中检和?br />断错误,以及发现内存和资源的泄漏。  (6) Insure++</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.parasoft.com/</font></u></a></p> <p>  一个自动化的运行时E序试工具Q检查难以察觉的错误,如内存覆盖,内存?br />漏,内存分配错误Q变量初始化错误Q变量定义冲H,指针错误Q库错误Q逻辑?br />误和法错误{?/p> <p>  (7) GlowCode</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.glowcode.com/</font></u></a></p> <p>  GlowCode包括内存泄漏查,code profilerQ函数调用跟t等功能。给C++开<br />发者提供完整的错误诊断Q和q行时性能分析工具包?/p> <p>  (8) Stack Spy</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.imperioustech.com/</font></u></a></p> <p>  它能捕捉stack corruption, stack over run, stack overflow{有x的错<br />误?/p> <p>------------------------------------------------------------------------<br />--------</p> <p>  5Q库</p> <p>  在C++中,库的C是非帔R的。C++之父 Bjarne Stroustrup先生多次表示?br />设计库来扩充功能要好q设计更多的语法的言论。现实中QC++的库门类J多Q解?br />的问题也是极其广泛,库从轻量U到重量U的都有。不都是让人眼界大开Q亦?br />是望而生叹的思维C。由于库的数量非常庞大,而且限于W者水qI其中很多q?br />不了解。所以文中所提的一些库都是比较著名的大型库?/p> <p>  5.1 标准?/p> <p>  标准库中提供了C++E序的基本设施。虽然C++标准库随着C++标准折腾了许多年<br />Q直到标准的出台才正式定型,但是在标准库的实C却很令hƣ慰得看到多U实<br />玎ͼq且已被实践证明为有工业U别强度的佳作?/p> <p>  (1) Dinkumware C++ Library</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.dinkumware.com/</font></u></a></p> <p>  P.J. Plauger~写的高品质的标准库。P.J. Plauger博士是Dr. Dobb'sE序?br />计杰出奖的获得者。其~写的库长期被Microsoft采用Qƈ且最qBorland也取得了<br />其OEM的licenseQ在其C/C++的品中采用Dinkumware的库?/p> <p>  (2) RogueWave Standard C++ Library</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.roguewave.com/</font></u></a></p> <p>  q个库在Borland C++ Builder的早期版本中曄被采用,后来被其他的库给?br />换了。笔者不推荐使用?/p> <p>  (3) SGI STL</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.roguewave.com/</font></u></a></p> <p>  SGI公司的C++标准模版库?/p> <p>  (4) STLport</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.stlport.org/</font></u></a></p> <p>  SGI STL库的跨^台可UL版本?/p> <p>  5.2 “准”标准库 - Boost</p> <p>  参考站点:<a ><u><font color="#0000ff">http://www.boost.org</font></u></a></p> <p>  国内镜像Q?a ><u><font color="#0000ff">http://www.c-view.org/tech/lib/boost/index.htm</font></u></a></p> <p>  Boost库是一个经q千锤百点{可UL、提供源代码的C++库,作ؓ标准库的?br />备,是C++标准化进E的发动Z一?Boost库由C++标准委员会库工作l成员发?br />Q在C++C֌中媄响甚大,其成员已q?000人?Boost库ؓ我们带来了最新、最酗?br />最实用的技术,是不折不扣的“准”标准库?/p> <p>  Boost中比较有名气的有q么几个库:</p> <p>  Regex</p> <p>  正则表达式库</p> <p>  Spirit</p> <p>  LL parser frameworkQ用C++代码直接表达EBNF</p> <p>  Graph</p> <p>  囄件和法</p> <p>  Lambda</p> <p>  在调用的地方定义短小匿名的函数对象,很实用的functional功能</p> <p>  concept check</p> <p>  查泛型编E中的concept</p> <p> </p> <p>  Mpl</p> <p>  用模板实现的元编E框?/p> <p> </p> <p>  Thread</p> <p>  可移植的C++多线E库</p> <p> </p> <p>  Python</p> <p>  把C++cd函数映射到Python之中</p> <p>  Pool</p> <p>  内存池管?/p> <p> </p> <p>  smart_ptr</p> <p>  5个智能指针,学习指针必读Q一份不错的参考是来自CUJ的文章:</p> <p>  Smart Pointers in BoostQ哦Q这文章可以查刎ͼCUJ是提供在U浏览的?br />中文版见W者在《Dr. Dobb's Journal软g研发杂志》第7辑上的译文?/p> <p>  BoostM来说是实用h值很高,质量很高的库。ƈ且由于其对跨q_的强调,<br />Ҏ准C++的强调,是编写^台无养ICC++的开发者必备的工具。但是Boost中也<br />有很多是实验性质的东西,在实际的开发中实用需要}慎。ƈ且很多Boost中的库功<br />能堪U对语言功能的扩展,其构造用精巧的手法Q不要N然的p旉研读。Bo<br />ost另外一面,比如Graphq样的库则是h工业强度Q结构良好,非常值得研读?br />_֓代码Qƈ且也可以攑ֿ的在产品代码中多多利用?/p> <p>  5.3 GUI</p> <p>  在众多C++的库中,GUI部分的库是比较J荣Q也比较引h注目的。在实际开<br />发中QGUI库的选择也是非常重要的一件事情,下面我们lD一下可选择的GUI库,<br />各自的特点以及相兛_L支持?/p> <p>  (1) MFC</p> <p>  大名鼎鼎的微软基cdQMicrosoft Foundation ClassQ。大凡学qVC++?br />人都应该知道q个库。虽然从技术角度讲QMFC是不大漂亮的Q但是它构徏于Windo<br />ws API 之上Q能够ɽE序员的工作更容?~程效率高,减少了大量在建立 Windo<br />ws E序时必ȝ写的代码Q同时它q提供了所有一?C++ ~程的优点,例如l承<br />和封装。MFC ~写的程序在各个版本的Windows操作pȝ上是可移植的Q例如,?br />Windows 3.1下编写的代码可以很容易地UL?Windows NT ?Windows 95 上。但<br />是在最q发展以及官Ҏ持上日渐势微?/p> <p>  (2) QT</p> <p>  参考网站:<a ><u><font color="#0000ff">http://www.trolltech.com/</font></u></a></p> <p>  Qt是Trolltech公司的一个多q_的C++囑Ş用户界面应用E序框架。它提供l?br />应用E序开发者徏立艺术的图形用L面所需的所用功能。Qt是完全面向对象的<br />很容易扩展,q且允许真正地组件编E。自?996q早些时候,Qtq入商业领域Q?br />它已l成为全世界范围内数千种成功的应用程序的基础。Qt也是行的Linux桌面?br />境KDE 的基Q同时它q支持Windows、Macintosh、Unix/X11{多U^台?/p> <p>  (3) WxWindows</p> <p>  参考网站:<a ><u><font color="#0000ff">http://www.wxwindows.org/</font></u></a></p> <p>  跨^台的GUI库。因为其cdơ极像MFCQ所以有文章介绍从MFC到WxWindows?br />代码UL以实现跨q_的功能。通过多年的开发也是一个日完善的GUI库,支持?br />样不׃前面两个库。ƈ且是完全开放源代码的。新q的C++ Builder X的GUI设计<br />器就是基于这个库的?/p> <p>  (4) Fox</p> <p>  参考网站:<a ><u><font color="#0000ff">http://www.fox-toolkit.org/</font></u></a></p> <p>  开放源代码的GUI库。作者从自己亲n的开发经验中得出了一个理想的GUI库应<br />该是什么样子的感受出发Q从而开始了对这个库的开发。有兴趣的可以尝试一下?/p> <p> <br />  (5) WTL</p> <p>  ZATL的一个库。因Z用了大量ATL的轻量手法Q模板等技术,在代码尺<br />寸,以及速度优化斚w做得非常C。主要面向的使用体是开发COM轻量U供|络<br />下蝲的可视化控g的开发者?/p> <p>  (6) GTK</p> <p>  参考网站:<a ><u><font color="#0000ff">http://gtkmm.sourceforge.net/</font></u></a></p> <p>  GTK是一个大名鼎鼎的C的开源GUI库。在Linux世界中有Gnomeq样的杀手应用?br />而GTK是q个库的C++装版本?/p> <p>  5.4 |络通信</p> <p>  (1) ACE</p> <p>  参考网站:<a ><u><font color="#0000ff">http://www.cs.wustl.edu/~schmidt/ACE.html</font></u></a></p> <p>  C++库的代表Q超重量U的|络通信开发框架。ACE自适配通信环境QAdaptive<br /> Communication EnvironmentQ是可以自由使用、开放源代码的面向对象框Ӟ?br />其中实现了许多用于ƈ发通信软g的核心模式。ACE提供了一l丰富的可复用C++?br />装外观(Wrapper FacadeQ和框架lgQ可跨越多种q_完成通用的通信软gd<br />Q其中包括:事g多\分离和事件处理器分派、信号处理、服务初始化、进E间?br />信、共享内存管理、消息\由、分布式服务动态(重)配置、ƈ发执行和同步Q等<br />{?/p> <p>  (2) StreamModule</p> <p>  参考网站:<a ><u><font color="#0000ff">http://www.omnifarious.org/StrMod/</font></u></a></p> <p>  设计用于化编写分布式E序的库。尝试着使得~写处理异步行ؓ的程序更?br />易,而不是用同步的外壛_起异步的本质?/p> <p>  (3) SimpleSocket</p> <p>  参考网站:<a ><u><font color="#0000ff">http://home.hetnet.nl/~lcbokkers/simsock.htm</font></u></a></p> <p>  q个cd让编写基于socket的客?服务器程序更加容易?/p> <p>  (4) A Stream Socket API for C++</p> <p>  参考网站:<a ><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 ><u><font color="#0000ff">http://xml.apache.org/xerces-c/</font></u></a></p> <p>  Xerces-C++ 是一个非常健壮的XML解析器,它提供了验证Q以及SAX和DOM API<br />。XML验证在文档类型定?Document Type DefinitionQDTD)斚w有很好的支持Q?br />q且?001q?2月增加了支持W3C XML Schema 的基本完整的开放标准?/p> <p>  (2) XMLBooster</p> <p>  参考网站:<a ><u><font color="#0000ff">http://www.xmlbooster.com/</font></u></a></p> <p>  q个库通过产生特制的parser的办法极大的提高了XML解析的速度Qƈ且能够<br />生相应的GUIE序来修改这个parser。在DOM和SAX两大LXML解析办法之外提供?br />另外一个可行的解决Ҏ?/p> <p>  (3) Pull Parser</p> <p>  参考网站:<a ><u><font color="#0000ff">http://www.extreme.indiana.edu/xgws/xsoap/xpp/</font></u></a></p> <p>  q个库采用pullҎ的parser。在每个SAX的parser底层都有一个pull的parse<br />rQ这个xpp把这层暴露出来直接给大家使用。在要充分考虑速度的时候值得试?/p> <p> <br />  (4) Xalan</p> <p>  参考网站:<a ><u><font color="#0000ff">http://xml.apache.org/xalan-c/</font></u></a></p> <p>  Xalan是一个用于把XML文档转换为HTMLQ纯文本或者其他XMLcd文档的XSLT?br />理器?/p> <p>  (5) CMarkup</p> <p>  参考网站:<a ><u><font color="#0000ff">http://www.firstobject.com/xml.htm</font></u></a></p> <p>  q是一U用EDOM的XML解析器。在很多思\上面非常灉|实用。值得大家在D<br />OM和SAX之外L一点灵感?/p> <p>  (6) libxml++</p> <p>  <a ><u><font color="#0000ff">http://libxmlplusplus.sourceforge.net/</font></u></a></p> <p>  libxml++是对著名的libxml XML解析器的C++装版本</p> <p>  5.6 U学计算</p> <p>  (1) Blitz++</p> <p>  参考网站:<a ><u><font color="#0000ff">http://www.oonumerics.org/blitz/</font></u></a></p> <p>  Blitz++ 是一个高效率的数D函数库Q它的设计目的是希望建立一套既?br />像C++ 一h便,同时又比Fortran速度更快的数D环境。通常Q用C++所写出<br />的数值程序,?Fortran?0%左右Q因此Blitz++正是要改掉这个缺炏V方法是?br />用C++的template技术,E序执行甚至可以比Fortran更快。Blitz++目前仍在发展?br />Q对于常见的SVDQFFTsQQMRES{常见的U性代数方法ƈ不提供,不过使用者可?br />很容易地利用Blitz++所提供的函数来构徏?/p> <p>  (2) POOMA</p> <p>  参考网站:<a ><u><font color="#0000ff">http://www.codesourcery.com/pooma/pooma</font></u></a></p> <p>  POOMA是一个免费的高性能的C++库,用于处理q行式科学计。POOMA的面向对<br />象设计方便了快速的E序开发,对ƈ行机器进行了优化以达到最高的效率Q方便在<br />工业和研I环境中使用?/p> <p>  (3) MTL</p> <p>  参考网站:<a ><u><font color="#0000ff">http://www.osl.iu.edu/research/mtl/</font></u></a></p> <p>  Matrix Template Library(MTL)是一个高性能的泛型组件库Q提供了各种格式<br />矩阵的大量线性代数方面的功能。在某些应用使用高性能~译器的情况下,比如In<br />tel的编译器Q从产生的汇~代码可以看出其与手写几乎没有两L效能?/p> <p>  (4) CGAL</p> <p>  参考网站:<a ><u><font color="#0000ff">www.cgal.org</font></u></a></p> <p>  Computational Geometry Algorithms Library的目的是把在计算几何斚w的大<br />部分重要的解x案和Ҏ以C++库的形式提供l工业和学术界的用户?/p> <p>  5.7 游戏开?/p> <p>  (1) Audio/Video 3D C++ Programming Library</p> <p>  参考网站:<a ><u><font color="#0000ff">http://www.galacticasoftware.com/products/av/</font></u></a></p> <p>  ***3D是一个跨q_Q高性能的C++库。主要的Ҏ是提供3D囑ŞQ声效支持(S<br />B,以及S3MQ,控制接口Q键盘,鼠标和遥感)QXMS?/p> <p>  (2) KlayGE</p> <p>  参考网站:<a ><u><font color="#0000ff">http://home.g365.net/enginedev/</font></u></a></p> <p>  国内游戏开发高手自qC++开发的游戏引擎。KlayGE是一个开放源代码、跨q?br />台的游戏引擎Qƈ使用Python作脚本语a。KlayGE在LGPL协议下发行。感谢龚敏敏<br />先生Z国游戏开发事业所做出的A献?/p> <p>  (3) OGRE</p> <p>  参考网站:<a ><u><font color="#0000ff">http://www.ogre3d.org</font></u></a></p> <p>  OGREQ面向对象的囑Ş渲染引擎Q是用C++开发的Q用灵zȝ面向对象3D引擎<br />。它的目的是让开发者能更方便和直接地开发基?Dg讑֤的应用程序或游戏?br />引擎中的cdҎ底层的系l库Q如QDirect3D和OpenGLQ的全部使用l节q行?br />抽象Qƈ提供了基于现实世界对象的接口和其它类?/p> <p>  5.8 U程</p> <p>  (1) C++ Threads</p> <p>  参考网站:<a ><u><font color="#0000ff">http://threads.sourceforge.net/</font></u></a></p> <p>  q个库的目标是给E序员提供易于用的c,q些c被l承以提供在Linux环境<br />中很隄到的大量的线E方面的功能?/p> <p>  (2) ZThreads</p> <p>  参考网站:<a ><u><font color="#0000ff">http://zthread.sourceforge.net/</font></u></a></p> <p>  一个先q的面向对象Q跨q_的C++U程和同步库?/p> <p>  5.9 序列?/p> <p>  (1) s11n</p> <p>  参考网站:<a ><u><font color="#0000ff">http://s11n.net/</font></u></a></p> <p>  一个基于STL的C++库,用于序列化PODQSTL容器以及用户定义的类型?/p> <p>  (2) Simple XML Persistence Library</p> <p>  参考网站:<a ><u><font color="#0000ff">http://sxp.sourceforge.net/</font></u></a></p> <p>  q是一个把对象序列化ؓXML的轻量的C++库?/p> <p>  5.10 字符?/p> <p>  (1) C++ Str Library</p> <p>  参考网站:<a ><u><font color="#0000ff">http://www.utilitycode.com/str/</font></u></a></p> <p>  操作字符串和字符的库Q支持Windows和支持gcc的多U^台。提供高度优化的<br />代码Qƈ且支持多U程环境和UnicodeQ同时还有正则表辑ּ的支持?/p> <p>  (2) Common Text Transformation Library</p> <p>  参考网站:<a ><u><font color="#0000ff">http://cttl.sourceforge.net/</font></u></a></p> <p>  q是一个解析和修改STL字符串的库。CTTL substringcd以用来比较,插入Q?br />替换以及用EBNF的语法进行解析?/p> <p>  (3) GRETA</p> <p>  参考网站:<a ><u><font color="#0000ff">http://research.microsoft.com/projects/greta/</font></u></a></p> <p>  q是由微软研I的研Ih员开发的处理正则表达式的库。在型匚w的情?br />下有非常优秀的表现?/p> <p>  5.11 l合</p> <p>  (1) P::Classes</p> <p>  参考网站:<a ><u><font color="#0000ff">http://pclasses.com/</font></u></a></p> <p>  一个高度可UL的C++应用E序框架。当前关注类型和U程安全的signal/slot<br />机制Qi/opȝ包括Z插g的网l协议透明的i/o架构Q基于插件的应用E序消息<br />日志框架Q访问sql数据库的cȝ{?/p> <p>  (2) ACDK - Artefaktur Component Development Kit</p> <p>  参考网站:<a ><u><font color="#0000ff">http://acdk.sourceforge.net/</font></u></a></p> <p>  q是一个^台无关的C++lg框架Q类gJava或?NET中的框架Q反机Ӟ<br />U程QUnicodeQ废料收集,I/OQ网l,实用工具QXMLQ等{)Q以及对Java, P<br />erl, Python, TCL, Lisp, COM ?CORBA的集成?/p> <p>  (3) dlib C++ library</p> <p>  参考网站:<a ><u><font color="#0000ff">http://www.cis.ohio-state.edu/~kingd/dlib/</font></u></a></p> <p>  各种各样的类的一个综合。大整数QSocketQ线E,GUIQ容器类,以及览?br />录的API{等?/p> <p>  (4) Chilkat C++ Libraries</p> <p>  参考网站:<a ><u><font color="#0000ff">http://www.chilkatsoft.com/cpp_libraries.asp</font></u></a></p> <p>  q是提供zipQe-mailQ编码,S/MIMEQXML{方面的库?/p> <p>  (5) C++ Portable Types Library (PTypes)</p> <p>  参考网站:<a ><u><font color="#0000ff">http://www.melikyan.com/ptypes/</font></u></a></p> <p>  q是STL的比较简单的替代品,以及可移植的多线E和|络库?/p> <p>  (6) LFC</p> <p>  参考网站:<a ><u><font color="#0000ff">http://lfc.sourceforge.net/</font></u></a></p> <p>  哦,q又是一个尝试提供一切的C++?/p> <p>  5.12 其他?/p> <p>  (1) Loki</p> <p>  参考网站:<a ><u><font color="#0000ff">http://www.moderncppdesign.com/</font></u></a></p> <p>  哦,你可能抱怨我早该和Boost一起介l它Q一个实验性质的库。作者在loki?br />把C++模板的功能发挥到了极致。ƈ且尝试把cM设计模式q样思想层面的东襉K过<br />库来提供。同时还提供了智能指针这h较实用的功能?/p> <p>  (2) ATL</p> <p>  ATL(Active Template Library)</p> <p>  是一l小巧、高效、灵zȝc,q些cMؓ创徏可互操作的COMlg提供了基本的<br />设施?/p> <p>  (3) FC++: The Functional C++ Library</p> <p>  q个库提供了一些函数式语言中才有的要素。属于用库来扩充语言的一个代?br />作。如果想要在OOP之外L另一分的乐趣Q可以去看看函数式程序设计的世界。大<br />师Peter Norvig?“Teach Yourself Programming in Ten Years”一文中将?br />数式语言列ؓ臛_应当学习?cȝE语a之一?/p> <p>  (4) FACT!</p> <p>  参考网站:<a ><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>  提供处理密码Q消息验证,单向hashQ公匙加密系l等功能的免费库?/p> <p>  q有很多非常Ȁ动h心或者是极其实用的C++库,限于我们的水q以及文章的?br />q不能包括进来。在对于q些已经包含q来的库的介l中Q由于ƈ不是每一个我?br />都用过Q所以难免有偏颇之处Q请读者见谅?/p> <p>------------------------------------------------------------------------<br />--------</p> <p>  6Q书c?/p> <p>  以前熊节先生曾撰文评论相对于JavaE序设计语言QC++的好书多如牛毛。荣耀<br />先生在《程序员》杂志上撰文《C++E序设计之四书五l》也本领域内几乎所有的<br />l典书籍作了全面的介l?M关于书的评论此时看来便是很多余的了。个人浅见,<br />除非你打以C++作ؓ唯一兴趣或者生存之本,一般读者确实没有够的旉和必?br />?0余本书籍全部阅读。更有参考h值的是荣耀先生的另一文章:《至应该阅<br />ȝ九本C++著作》,可以从下面的地址览到此文:</p> <p>  <a ><u><font color="#0000ff">http://www.royaloo.com/articles/articles_2003/9CppBooks.htm</font></u></a></p> <p>  下面几本书对于走在C++初学之\上的读者是我们最愿意推荐l大家的Q?/p> <p>  (1) 《C++ Primer?/p> <p>  哦,也许你会抱怨我们ؓ什么不先介lTCPL,但对于走在学习之路上的入门者,<br />本书内容更ؓ全面Q更l易懂,我们U它为“C++的超U宝典”ƈ不过分。配?br />一本不错的习题解答《C++ Primer Answer Book》可以辅助你的学习之路?/p> <p>  (2) 《Essential C++?/p> <p>  如果说《C++ Primer》是C++领域的超U宝典,那么此书作ؓ掌握C++的大局?br />当之无愧。正如?NET大局观》一书能够让读者全?NETQ本书讲qCC++中最核心<br />的全部主题。书虽不厚,内容_Q不׃ؓ《C++ Primer》读者茶余饭后的主题?br />之作?/p> <p>  (3) 《The C++ Programming Language?/p> <p>  BjarneZ带来的C++教程Q真正能够告诉你怎么用才叫真正的C++的唯一一?br />书。虽然如同“某某程序设计语a”这L书籍会给大家一个内容全揽,入门到精<br />通的感觉Q但本书实不太适合初学者阅诅R如果你自认为是一名很有经验的C++E?br />序员Q那臛_也要反复咀嚼Bjarne先生所的若q内宏V?/p> <p>  (4) 《Effective C++》,《More Effective C++?/p> <p>  是的Q正如一些C++爱好者经总读过与没有读q上qC本作品来区分你是否是<br />C++高手。我们也极力推崇q两本著作。在各种介绍C++专家l验的书c里面,q两<br />本是最贴近语言本质Q看后最能够有脱胎换骨感觉的书,L书你需每日三省汝n<br />?/p> <p>  技术书c仁者见仁,q多的评论反无太多意义,p者喜好选择最适合自己?br />书方Z{?/p> <p>------------------------------------------------------------------------<br />--------</p> <p>  7Q资源网?/p> <p>  正如我们可以通过计算机历史上的重要h物了解计机史的发展QC++相关人物<br />的网站也可以使我们得到最有h值的参考与借鉴Q下面的人物我们认ؓ没有介绍?br />必要Q只因下面的人物在C++领域的地位众所周知Q我们只相关的资源q行|列?br />供读者学习,他们有的工作于贝实验室Q有的工作于知名~译器厂商,有的在不<br />断推q语a的标准化Q有的ؓ读者撰写了多部千古奇作…?br />  (1) Bjarne Stroustrup<br />  <a ><u><font color="#0000ff">http://www.research.att.com/~bs/</font></u></a></p> <p>  (2) Stanley B. Lippman<br />  <a ><u><font color="#0000ff">http://blogs.msdn.com/slippman/</font></u></a><br />  中文?<a ><u><font color="#0000ff">http://www.zengyihome.net/slippman/index.htm</font></u></a></p> <p>  (3) Scott Meyers<br />  <a ><u><font color="#0000ff">http://www.aristeia.com/</font></u></a></p> <p>  (4) David Musser<br />  <a ><u><font color="#0000ff">http://www.cs.rpi.edu/~musser/</font></u></a></p> <p>  (5) Bruce Eckel<br />  <a ><u><font color="#0000ff">http://www.bruceeckel.com</font></u></a></p> <p>  (6) Nicolai M. Josuttis<br />  <a ><u><font color="#0000ff">http://www.josuttis.com/</font></u></a></p> <p>  (7) Herb Sutter<br />  <a ><u><font color="#0000ff">http://www.gotw.ca/</font></u></a></p> <p>  (8) Andrei Alexandrescu<br />  <a ><u><font color="#0000ff">http://www.coderncppdesign.com/</font></u></a></p> <p>  (9) 侯捷先生<br />  <a ><u><font color="#0000ff">http://www.jjhou.com</font></u></a></p> <p>  (10) 孟岩先生<br />  先生J忙于工作,痴迷于技术,暂无个h主页Q关于先生的作品可以通过CSDN<br />的专栏和侯先生的主页讉K到?/p> <p>  (11) 荣耀先生<br />  <a ><u><font color="#0000ff">http://www.royaloo.com/</font></u></a></p> <p>  (12) 潘爱民先?br />  <a ><u><font color="#0000ff">http://www.icst.pku.edu.cn/panaimin/pam_homepage.htm</font></u></a></p> <p>  除了上述大师的主外Q以下的l合cC++学习参考站Ҏ我们非常愿意向大?br />推荐的:</p> <p>  (1) CodeProject<br />  <a ><u><font color="#0000ff">http://www.codeproject.com</font></u></a></p> <p>  (2) CodeGuru<br />  <a ><u><font color="#0000ff">http://www.codeguru.com</font></u></a></p> <p>  (3) Dr. Dobb's Journal<br />  <a ><u><font color="#0000ff">http://www.ddj.com</font></u></a></p> <p>  (4) C/C++ Users Journal<br />  <a ><u><font color="#0000ff">http://www.cuj.com</font></u></a></p> <p>  (5) Cl视?br />  <a ><u><font color="#0000ff">http://www.c-view.org</font></u></a></p> <p>  (6) allaboutprogram<br />  <a ><u><font color="#0000ff">http://www.allaboutprogram.com</font></u></a><br />  其他资料</p> <p>  (1) ISO IEC JTC1/SC22/WG21 - C++Q标准C++的权威参?br />  <a ><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 ><u><font color="#0000ff">http://www.sunistudio.com/cppfaq/index.html</font></u></a><br />  C/C++ 新闻l:<br />  你不妨尝试从q里提问和回{问题,很多不错的Q&A资源......</p> <p>  (1) .alt.comp.lang.learn.c-c++<br />  q个单些Q如果你和我一h个菜?/p> <p>  (2) .comp.lang.c++.moderated<br />    嗯,q个昄水^高一?/p> <p>  (3) .comp.std.c++<br />  如果你需要讨论标准C++相关话题的话</p> <p>------------------------------------------------------------------------<br />--------</p> <p>  8Q不得不写的l束?/p> <p>  l束的时候也是ȝ现状Q展望未来的时候。虽然C++从脱胎于C开始,一路艰<br />隑֝L走过来,但是无论如何C++已经取得了工业基的地位。文章列丄大量相关<br />资源是最好的证明Q而业界的大量用C++写成的品代码以及大量的C++职业工程<br />师则是最直接的证明。同Ӟ我们可以看到各个高校的计机专业都开设有C++q门<br />评Q网l上对于C++的学习讨Z从来都没有停q。但是,在Java?NET两大企业<br />开发^台的围攻下,lh的感觉是C++来“不行”了?/p> <p>  C++在面向企业的软g开发中Q在开发便h等斚w的确要比Java和C#差很多,<br />其中一个问题是C++语言本n比较复杂Q学习曲U比较陡峭,另外一个问题是C++?br />准化的时间太长,丧失了很多的壮大ZQ耗费了很多精力在厂商的之间的斗争?br />Q而C++的标准库M个完善的E序开发框架还~少太多太多的内容,各个W三方的<br />cd和框架又在一致性和完整性上没法和随q_提供的框架相提ƈ论。难道C++真的<br />要退出历史舞CQ?/p> <p>  从C++目前的活跃程度,以及应用现状来说是完全能够肯定C++仍然是Y件工?br />的基Q也不会退出历史舞台的。另外从BoostQLokiq些库中我们也能够看到C++<br />的发展非常活跃,对于新技术新思维非常Ȁq,C++仍然q泛受到x。从ACE在高<br />性能通信领域的应用,以及MTLq样的库在数D领域的表现Q我们可以看?br />C++在高性能应用场合下的不可替代的作用,而嵌入式pȝq样的内存受限开发^?br />Q比如Symbian OS上,C++已经发挥着q且发挥更大的作用。可以预见的是以后的<br />软g无论上层的应用怎么变,它的底层核心都会是由C/C++q样的系l软g~写?br />Q比如Java虚拟机,.NET Framwork。因为只有这LpȝUY件才能完全彻底的?br />挥机器的功能?/p> <p>  需要看到的是两个趋势,一个趋势是C++变得更加复杂Q更加学院派Q通过模板<br />{有潜力的语法因素构造越来越_y的库成ؓ了现代C++的热点,虽然在利用库实现<br />新的~程范式Q乃臌计模式等斚w很有开创意义,也确实生了一些能够便捷开<br />发的工具Q但是更多的是把C++变得更加强大Q更加复杂,也更加难懂,g也更?br />学院z,不得不说它正在向边缘化道路发展。另一个趋势是C++在主的企业应用开<br />发中已经逐渐退ZQERPq样的企业Y件开发中基本上不会考虑C++Q除非需要?br />虑性能或者和遗留代码的集成这些因素。C++退守到pȝU别语言Q成Y件工业的<br />基础是大势所。然而反思一下,真的是退守么Q自从STL出现Q无数的人风起云?br />的开始支持C++,他们狂呼“我看到深夜消失了,目标软g工程的出现。我看到了可<br />l护的代码。”是的,STL在可l护性下做得如此。但是又怎样呢?STL为C++?br />q了C软g工程的道路,而在上层应用E序软g开发领域这块场地早不单独属?br />C++,很多E序设计语言都做得很Q疯狂的支持者会毫不犹U地说我们应当支持<br />C++,因ؓ它是世界上最的语言。而坦率地_你的腰杆真的那么么Q也许只?br />在逃避一些事实。C++是优U的,q不可否认,STL的出现让C++一度走上了最辉煌?br />时刻Q然而现在看来……我的一位恩师曾aQ真正能够将STL应用得淋漓尽致的人很<br />保守地说国内也不过200人,或许不加入STL能够使C++向着它应当发展的方向发展<br />的更好,而现在看来,C++也应当回首到真正属于他的那一片圣C…?/p> <br /> <img src ="http://www.shnenglu.com/erran/aggbug/34178.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/erran/" target="_blank">erran</a> 2007-10-14 00:14 <a href="http://www.shnenglu.com/erran/archive/2007/10/14/34178.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转:C++?U类型{?http://www.shnenglu.com/erran/archive/2007/10/13/34150.htmlerranerranSat, 13 Oct 2007 13:27:00 GMThttp://www.shnenglu.com/erran/archive/2007/10/13/34150.htmlhttp://www.shnenglu.com/erran/comments/34150.htmlhttp://www.shnenglu.com/erran/archive/2007/10/13/34150.html#Feedback0http://www.shnenglu.com/erran/comments/commentRss/34150.htmlhttp://www.shnenglu.com/erran/services/trackbacks/34150.html 原文Qhttp://blog.csdn.net/stanleyrprose/archive/2006/01/25/588083.aspx
作者:


C++?U类型{?


一、C 风格QC-styleQ强制{型如下:

    (T) expression // cast expression to be of type T
    函数风格QFunction-styleQ强制{型用这L语法Q?br />    T(expression) // cast expression to be of type T
    q两UŞ式之间没有本质上的不同,它纯_就是一个把括号攑֜哪的问题。我把这两种形式UCؓ旧风|old-styleQ的强制转型?

   二?C++的四U强制{型Ş式:

  C++ 同时提供了四U新的强制{型Ş式(通常UCؓ新风格的?C++ 风格的强制{型)Q?
  const_cast(expression)
  dynamic_cast(expression)
  reinterpret_cast(expression)
  static_cast(expression)

  每一U适用于特定的目的Q?

  ·dynamic_cast 主要用于执行“安全的向下转型Qsafe downcastingQ”,也就是说Q要定一个对象是否是一个承体pM的一个特定类型。它是唯一不能用旧风格语法执行的强制{型,也是唯一可能有重大运行时代h的强制{型?br />   
    ·static_cast 可以被用于强刉型{换(例如Qnon-const 对象转型?const 对象Qint 转型? doubleQ等{)Q它q可以用于很多这L转换的反向{换(例如Qvoid* 指针转型为有cd指针Q基cL针{型ؓzcL针)Q但是它不能一?const 对象转型?non-const 对象Q只? const_cast 能做刎ͼQ它最接近于C-style的{换?br />   
  ·const_cast 一般用于强制消除对象的帔R性。它是唯一能做到这一点的 C++ 风格的强制{型?

  ·reinterpret_cast 是特意用于底层的强制转型Q导致实C赖(implementation-dependentQ(是_不可ULQ的l果Q例如,一个指针{型ؓ一个整数。这L强制转型在底层代码以外应该极为罕见?br />  
   旧风格的强制转型依然合法Q但是新的Ş式更可取。首先,在代码中它们更容易识别(无论是hq是?grep q样的工具都是如此)Q这样就化了在代码中Lcdpȝ被破坏的地方的过E。第二,更精地指定每一个强制{型的目的Q得编译器诊断使用错误成ؓ? 能。例如,如果你试图用一?const_cast 以外的新风格强制转型来消除常量性,你的代码无法编译?

== 
==  dynamic_cast .vs. static_cast
==

class B { ... };
class D : public B { ... };

void f(B* pb)
{
   D* pd1 = dynamic_cast<D*>(pb);
   D* pd2 = static_cast<D*>(pb);
}

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.

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.

    即dynamic_cast可用于承体pM的向下{型,卛_基类指针转换为派生类指针Q比static_cast更严格更安全? dynamic_cast在执行效率上比static_cast要差一?但static_cast在更宽上范围内可以完成映?q种不加限制的映伴? 着不安全?static_cast覆盖的变换类型除cdơ的静态导航以?q包括无映射变换,H化变换(q种变换会导致对象切?丢失信息),? VOID*的强制变?隐式cd变换{?..


==
==  static_cast .vs. reinterpret_cast
==

    reinterpret_cast是ؓ了映到一个完全不同类型的意?q个关键词在我们需要把cd映射回原有类型时用到?我们映射到的cd仅仅是ؓ了故弄玄虚和其他目的,q是所有映中最危险?(q句话是C++~程思想中的原话)

    static_cast ?reinterpret_cast 操作W修改了操作数类? 它们不是互逆的; static_cast 在编译时使用cd信息执行转换, 在{换执行必要的?诸如指针界计算, cd?. 其操作数相对是安全的. 另一斚w, reinterpret_cast 仅仅是重新解释了l出的对象的比特模型而没有进行二q制转换, 例子如下:

    int n=9; double d=static_cast < double > (n);

    上面的例子中, 我们一个变量从 int 转换?double. q些cd的二q制表达式是不同? 要将整数 9 转换?双精度整?9, static_cast 需要正地为双_ֺ整数 d 补比特? 其结果ؓ 9.0. 而reinterpret_cast 的行为却不同:

    int n=9;
    double d=reinterpret_cast<double & > (n);

    q次, l果有所不同. 在进行计以? d 包含无用? q是因ؓ reinterpret_cast 仅仅是复?n 的比特位?d, 没有q行必要的分?

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=588083

erran 2007-10-13 21:27 发表评论
]]>
转:堆和栈的区别 http://www.shnenglu.com/erran/archive/2007/10/13/34148.htmlerranerranSat, 13 Oct 2007 13:12:00 GMThttp://www.shnenglu.com/erran/archive/2007/10/13/34148.htmlhttp://www.shnenglu.com/erran/comments/34148.htmlhttp://www.shnenglu.com/erran/archive/2007/10/13/34148.html#Feedback0http://www.shnenglu.com/erran/comments/commentRss/34148.htmlhttp://www.shnenglu.com/erran/services/trackbacks/34148.html 参见http://kb.csdn.net/.net/Articles/200605/80f93200-6a0c-4e21-82d8-4212844da589.html


堆和栈的区别


一般认为在c中分几个存储?
1?- 有编译器自动分配释放
2?- 一般由E序员分配释放,若程序员不释放,E序l束时可能由OS回收
3全局区(静态区Q,全局变量和静态变量的存储是放在一块的Q初始化的全局变量和静
态变量在一块区域,未初始化的全局变量和未初始化的静态变量在盔R的另一块区域?
- E序l束释放
4另外q有一个专门放帔R的地斏V?- E序l束释放
在函C中定义的变量通常是在栈上Q用malloc, calloc, realloc{分配内存的函数?
配得到的是在堆上。在所有函C外定义的是全局量,加了static修饰W后不管在哪
里都存放在全局区(静态区Q?在所有函C外定义的static变量表示在该文g中有效,
不能extern到别的文件用Q在函数体内定义的static表示只在该函C内有效。另外,
函数中的"adgfdf"q样的字W串存放在常量区?
比如Q?
int a = 0; 全局初始化区
char *p1; 全局未初始化?
main()
{
int b; ?
char s[] = "abc";?
char *p2; ?
char *p3 = "123456"; 123456\0在常量区Qp3在栈上?
static int c =0Q?全局Q静态)初始化区
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
分配得来?0?0字节的区域就在堆区?
strcpy(p1, "123456"); 123456\0攑֜帔R区,~译器可能会它与p3所指向?12345
6"优化成一块?
}
q有是函数调用时会在栈上有一pd的保留现场及传递参数的操作?
栈的I间大小有限定,vc的缺省是2M。栈不够用的情况一般是E序中分配了大量数组?
递归函数层次太深。有一点必ȝ道,当一个函数调用完q回后它会释放该函数中所?
的栈I间。栈是由~译器自动管理的Q不用你操心?
堆是动态分配内存的Qƈ且你可以分配使用很大的内存。但是用不好会生内存泄漏?
q且频繁地malloc和free会生内存碎片(有点cM盘片Q,因ؓc分配动态内存时
是寻扑֌配的内存的。而用栈则不会产生片?
在栈上存取数据比通过指针在堆上存取数据快些?
一般大家说的堆栈和栈是一LQ就是栈(stack)Q而说堆时才是堆heap.
栈是先入后出的,一般是由高地址向低地址生长?


?heap)和栈(stack)是C/C++~程不可避免会碰到的两个基本概念?br />首先Q这两个概念都可以在讲数据结构的书中扑ֈQ他们都是基本的数据l构Q虽然栈更ؓ单一些。在具体的C/C++~程框架中,q两个概念ƈ不是q行的。对底层机器代码的研I可以揭C,栈是机器pȝ提供的数据结构,而堆则是C/C++函数库提供的?具体地说Q现代计机(串行执行机制)Q都直接在代码底层支持栈的数据结构。这体现在,有专门的寄存器指向栈所在的地址Q有专门的机器指令完成数据入栈出栈的操作? q种机制的特Ҏ效率高,支持的数据有限,一般是整数Q指针,点数等pȝ直接?持的数据cdQƈ不直接支持其他的数据l构。因为栈的这U特点,Ҏ的用在E序中是非常频繁的。对子程序的调用是直接利用栈完成的。机器的call指o里隐含了把返回地址推入栈,然后跌{臛_E序地址的操作,而子E序中的ret指o则隐含从堆栈中弹回地址q蟩转之的操作。C/C++中的自动变量是直接利用栈的例子,q也是Z么当函数q回Ӟ该函数的自动变量自动失效的原?因ؓ 颜换指戳说饔们暗 状?? 和栈不同Q堆的数据结构ƈ不是ql?无论是机器系l还是操作系l?支持的,而是由函数库提供的。基本的malloc/realloc/free函数l护了一套内部的堆数据结构。当E序使用q些函数去获得新的内存空间时Q这套函数首先试图从内部堆中L可用的内存空_如果没有可以使用的内存空_则试囑ֈ用系l调用来动态增加程序数据段的内存大,新分配得到的I间首先被组l进内部堆中去,然后再以适当的Ş式返回给调用者。当E序释放分配的内存空间时Q这片内存空间被q回内部堆结构中Q可能会被适当的处?比如和其他空闲空间合q成更大的空闲空?Q以更适合下一ơ内存分配申诗?br />q套复杂的分配机制实际上相当于一个内存分配的~冲?Cache)Q用这套机制有如下若干原因Q?
1. pȝ调用可能不支持Q意大的内存分配。有些系l的pȝ调用只支持固定大及其倍数的内存请?按页分配)Q这L话对于大量的内存分cL说会造成费?br />2. pȝ调用甌内存可能是代h늚。系l调用可能涉及用h和核心态的转换?
3. 没有理的内存分配在大量复杂内存的分配释放操作下很容易造成内存片?

堆和栈的Ҏ 从以上知识可知,栈是pȝ提供的功能,特点是快速高效,~点是有限制Q数据不灉|Q而栈是函数库提供的功能,特点是灵zL便,数据适应面广泛,但是效率有一定降低。栈是系l数据结构,对于q程/U程是唯一的;堆是函数库内部数据结构,不一定唯一。不同堆分配的内存无法互相操作。栈I间分静态分配和动态分配两U。静态分配是~译器完成的Q比如自动变?auto)的分配。动态分配由alloca函数完成。栈的动态分配无需释放(是自动的)Q也没有释攑և数。ؓ可移植的E序赯Q栈的动态分配操作是不被鼓励的!堆空间的分配L动态的Q虽然程序结束时所有的数据I间都会被释攑֛pȝQ但是精的甌内存/释放内存匚w是良好程序的基本要素?
所以计机中的堆和栈经常时放一块讲?
nod 一般不是必要就不要动态创建,最讨厌把new出来的东西当局部变量用Q?br />用万了马上delete 的做?

 理由
 1.栈分配比堆快Q只需要一条指令就呢给配所有的局部变?
2.栈不会出现内存碎?
3。栈对象好管?

当然Q某些情况下也要那么?比如
1.对象很大
2.对象需要在某个特定的时L造或析够
3.cd允许对象动态创?比如VCL的大多数c? 当然Q必ȝ堆对象时也不能躲?br /> 
http://kb.csdn.net/.net/Articles/200605/80f93200-6a0c-4e21-82d8-4212844da589.html

erran 2007-10-13 21:12 发表评论
]]>
C++中成员函数的重蝲、覆盖与隐藏http://www.shnenglu.com/erran/archive/2007/10/13/34128.htmlerranerranSat, 13 Oct 2007 09:52:00 GMThttp://www.shnenglu.com/erran/archive/2007/10/13/34128.htmlhttp://www.shnenglu.com/erran/comments/34128.htmlhttp://www.shnenglu.com/erran/archive/2007/10/13/34128.html#Feedback0http://www.shnenglu.com/erran/comments/commentRss/34128.htmlhttp://www.shnenglu.com/erran/services/trackbacks/34128.html
   
成员函数的重载、覆盖(overrideQ与隐藏很容易؜淆,C++E序员必要搞清楚概念,否则错误防不胜阌Ӏ?span>

 

 

8.2.1 重蝲与覆?span>

    成员函数被重载的特征Q?span>

Q?span>1Q相同的范围Q在同一个类中)Q?span>

Q?span>2Q函数名字相同;

Q?span>3Q参C同;

Q?span>4Q?span>virtual关键字可有可无?/span>

    覆盖是指zcd数覆盖基cd敎ͼ特征是:

Q?span>1Q不同的范围Q分别位于派生类与基c)Q?span>

Q?span>2Q函数名字相同;

Q?span>3Q参数相同;

Q?span>4Q基cd数必Lvirtual关键字?span>

    CZ8-2-1中,函数Base::f(int)?span>Base::f(float)怺重蝲Q?span>Base::g(void)?span>Derived::g(void)覆盖?span>

 

 

#include <iostream.h>

    class Base

{

public:

             void f(int x){ cout << "Base::f(int) " << x << endl; }

void f(float x){ cout << "Base::f(float) " << x << endl; }

     virtual void g(void){ cout << "Base::g(void)" << endl;}

};

 

 

    class Derived : public Base

{

public:

     virtual void g(void){ cout << "Derived::g(void)" << endl;}

};

 

 

    void main(void)

    {

     Derived d;

     Base *pb = &d;

     pb->f(42);        // Base::f(int) 42

     pb->f(3.14f);     // Base::f(float) 3.14

     pb->g();          // Derived::g(void)

}

CZ8-2-1成员函数的重载和覆盖

   

8.2.2 令hqh的隐藏规?/span>

    本来仅仅区别重蝲与覆盖ƈ不算困难Q但?span>C++的隐藏规则问题复杂性陡然增加。这?#8220;隐藏”是指zcȝ函数屏蔽了与其同名的基类函数Q规则如下:

Q?span>1Q如果派生类的函C基类的函数同名,但是参数不同。此Ӟ不论有无virtual关键字,基类的函数将被隐藏(注意别与重蝲hQ?span>

Q?span>2Q如果派生类的函C基类的函数同名,q且参数也相同,但是基类函数没有virtual关键字。此Ӟ基类的函数被隐藏Q注意别与覆盖؜淆)?/span>

    CZE序8-2-2Q?span>aQ中Q?span>

Q?span>1Q函?span>Derived::f(float)覆盖?span>Base::f(float)?span>

Q?span>2Q函?span>Derived::g(int)隐藏?span>Base::g(float)Q而不是重载?span>

Q?span>3Q函?span>Derived::h(float)隐藏?span>Base::h(float)Q而不是覆盖?span>

 

 

#include <iostream.h>

    class Base

{

public:

    virtual void f(float x){ cout << "Base::f(float) " << x << endl; }

void g(float x){ cout << "Base::g(float) " << x << endl; }

            void h(float x){ cout << "Base::h(float) " << x << endl; }

};

    class Derived : public Base

{

public:

    virtual void f(float x){ cout << "Derived::f(float) " << x << endl; }

void g(int x){ cout << "Derived::g(int) " << x << endl; }

            void h(float x){ cout << "Derived::h(float) " << x << endl; }

};

CZ8-2-2Q?span>aQ成员函数的重蝲、覆盖和隐藏

 

 

    据作者考察Q很?span>C++E序员没有意识到?#8220;隐藏”q回事。由于认识不够深刻,“隐藏”的发生可谓神出鬼没,常常产生令hqh的结果?span>

CZ8-2-2Q?span>bQ中Q?span>pb?span>pd指向同一地址Q按理说q行l果应该是相同的Q可事实qq样?span>

 

 

void main(void)

{

Derived d;

Base *pb = &d;

Derived *pd = &d;

// Good : behavior depends solely on type of the object

pb->f(3.14f); // Derived::f(float) 3.14

pd->f(3.14f); // Derived::f(float) 3.14

 

 

// Bad : behavior depends on type of the pointer

pb->g(3.14f); // Base::g(float) 3.14

pd->g(3.14f); // Derived::g(int) 3        (surprise!)

 

 

// Bad : behavior depends on type of the pointer

pb->h(3.14f); // Base::h(float) 3.14      (surprise!)

pd->h(3.14f); // Derived::h(float) 3.14

}

CZ8-2-2Q?span>bQ?重蝲、覆盖和隐藏的比?/span>

8.2.3 摆脱隐藏

    隐藏规则引v了不麻烦。示?chsdate w:st="on" isrocdate="False" islunardate="False" day="3" month="2" year="2008">8-2-3E序中,语句pd->f(10)的本意是惌用函?span>Base::f(int)Q但?span>Base::f(int)不幸?span>Derived::f(char *)隐藏了。由于数?span>10不能被隐式地转化为字W串Q所以在~译时出错?span>

 

 

class Base

{

public:

void f(int x);

};

class Derived : public Base

{

public:

void f(char *str);

};

void Test(void)

{

Derived *pd = new Derived;

pd->f(10);    // error

}

CZ8-2-3 ׃隐藏而导致错?/span>

 

 

    从示?chsdate w:st="on" isrocdate="False" islunardate="False" day="3" month="2" year="2008">8-2-3看来Q隐藏规则似乎很愚蠢。但是隐藏规则至有两个存在的理由:

u       写语?span>pd->f(10)的h可能真的惌?span>Derived::f(char *)函数Q只是他误将参数写错了。有了隐藏规则,~译器就可以明确指出错误Q这未必不是好事。否则,~译器会静悄悄地错错Q程序员很隑֏现这个错误,下根?span>

u       假如c?span>Derived有多个基c(多重l承Q,有时搞不清楚哪些基类定义了函?span>f。如果没有隐藏规则,那么pd->f(10)可能会调用一个出乎意料的基类函数f。尽隐藏规则看h不怎么有道理,但它的确能消灭这些意外?span>

 

 

CZ8-2-3中,如果语句pd->f(10)一定要调用函数Base::f(int)Q那么将c?span>Derived修改为如下即可?span>

class Derived : public Base

{

public:

void f(char *str);

void f(int x) { Base::f(x); }

};



erran 2007-10-13 17:52 发表评论
]]>
转:C++cd介绍http://www.shnenglu.com/erran/archive/2007/10/13/34119.htmlerranerranSat, 13 Oct 2007 08:42:00 GMThttp://www.shnenglu.com/erran/archive/2007/10/13/34119.htmlhttp://www.shnenglu.com/erran/comments/34119.htmlhttp://www.shnenglu.com/erran/archive/2007/10/13/34119.html#Feedback1http://www.shnenglu.com/erran/comments/commentRss/34119.htmlhttp://www.shnenglu.com/erran/services/trackbacks/34119.html原文Q?a >http://hi.baidu.com/chplj/blog/item/08d8f6368def16310a55a931.html
作者:

C++cd介绍


再次体现了C++保持核心语言的效率同时大力发展应用库的发展趋?!在C++中,库的C是非帔R的。C++之父 Bjarne Stroustrup先生多次表示了设计库来扩充功能要好过设计更多的语法的a论。现实中QC++的库门类J多Q解决的问题也是极其q泛Q库从轻量到重量的都有。不都是让人眼界大开Q亦或是望而生叹的思维C。由于库的数量非常庞大,而且限于W者水qI其中很多q不了解。所以文中所提的一些库都是比较著名的大型库。?/p>

标准库?/strong>

标准库中提供了C++E序的基本设施。虽然C++标准库随着C++标准折腾了许多年Q直到标准的出台才正式定型,但是在标准库的实C却很令hƣ慰得看到多U实玎ͼq且已被实践证明为有工业U别强度的佳作。?/p>

1、 Dinkumware C++ Library 

参考站点:http://www.dinkumware.com

P.J. Plauger~写的高品质的标准库。P.J. Plauger博士是Dr. Dobb'sE序设计杰出奖的获得者。其~写的库长期被Microsoft采用Qƈ且最qBorland也取得了其OEM的licenseQ在其C/C+ +的品中采用Dinkumware的库。?/p>

2、 RogueWave Standard C++ Library 

参考站点:http://www.roguewave.com/ 

q个库在Borland C++ Builder的早期版本中曄被采用,后来被其他的库给替换了。笔者不推荐使用。?/p>

3、SGI STL 

参考站点:http://www.roguewave.com/
 SGI公司的C++标准模版库。?/p>

4、STLport 

参考站点:http://www.stlport.org/
 SGI STL库的跨^台可UL版本。?/p>

准标准库——Boost 

Boost 库是一个经q千锤百点{可UL、提供源代码的C++库,作ؓ标准库的后备Q是C++标准化进E的发动Z一。 Boost库由C++标准委员会库工作l成员发P在C++C֌中媄响甚大,其成员已q?000人。 Boost库ؓ我们带来了最新、最酗最实用的技术,是不折不扣的"?标准库。?/p>

Boost中比较有名气的有q么几个库: 

 Regex 
 正则表达式库 

Spirit 
 LL parser frameworkQ用C++代码直接表达EBNF 

Graph 
 囄件和法 

Lambda 
 在调用的地方定义短小匿名的函数对象,很实用的functional功能 

concept check 
 查泛型编E中的concept 

Mpl 
 用模板实现的元编E框架?/p>

Thread 
 可移植的C++多线E库 

Python 
 把C++cd函数映射到Python之中 

Pool 
 内存池管理?/p>

smart_ptr 
 5个智能指针,学习指针必读Q一份不错的参考是来自CUJ的文章: 

Smart Pointers in Boost,哦,q篇文章可以查到QCUJ是提供在U浏览的。中文版见笔者在《Dr. Dobb's Journal软g研发杂志》第7辑上的译文。?/p>

Boost M来说是实用h值很高,质量很高的库。ƈ且由于其对跨q_的强调,Ҏ准C++的强调,是编写^台无养ICC++的开发者必备的工具。但是Boost 中也有很多是实验性质的东西,在实际的开发中实用需要}慎。ƈ且很多Boost中的库功能堪U对语言功能的扩展,其构造用精巧的手法Q不要N然的p旉研读。Boost另外一面,比如Graphq样的库则是h工业强度Q结构良好,非常值得研读的精品代码,q且也可以放心的在品代码中多多利用。?/p>

参考站点:http://www.boost.orgQ国内镜像:http://www.c-view.org/tech/lib/boost/index.htmQ?/p>

GUI 

在众多C++的库中,GUI部分的库是比较J荣Q也比较引h注目的。在实际开发中QGUI库的选择也是非常重要的一件事情,下面我们lD一下可选择的GUI库,各自的特点以及相兛_L支持。?/p>

1、 MFC 

大名鼎鼎的微软基cdQMicrosoft Foundation ClassQ。大凡学qVC++的h都应该知道这个库。虽然从技术角度讲QMFC是不大漂亮的Q但是它构徏于Windows API 之上Q能够ɽE序员的工作更容?~程效率高,减少了大量在建立 Windows E序时必ȝ写的代码Q同时它q提供了所有一般 C++ ~程的优点,例如l承和封装。MFC ~写的程序在各个版本的Windows操作pȝ上是可移植的Q例如,在 Windows 3.1下编写的代码可以很容易地UL刊WWindows NT 或 Windows 95 上。但是在最q发展以及官Ҏ持上日渐势微。?/p>

2、 QT 

参考网站:http://www.trolltech.com
Qt 是Trolltech公司的一个多q_的C++囑Ş用户界面应用E序框架。它提供l应用程序开发者徏立艺术的图形用L面所需的所用功能。Qt是完全面向对象的很容易扩展,q且允许真正地组件编E。自?996q早些时候,Qtq入商业领域Q它已经成ؓ全世界范围内数千U成功的应用E序的基。Qt也是行的Linux桌面环境KDE 的基Q同时它q支持Windows、Macintosh、Unix/X11{多U^台。?/p>

3、WxWindows 

参考网站:http://www.wxwindows.org/

跨^台的GUI库。因为其cdơ极像MFCQ所以有文章介绍从MFC到WxWindows的代码移植以实现跨^台的功能。通过多年的开发也是一个日完善的 GUI库,支持同样不弱于前面两个库。ƈ且是完全开放源代码的。新q的C++ Builder X的GUI设计器就是基于这个库的。?/p>

4、Fox 

开放源代码的GUI库。作者从自己亲n的开发经验中得出了一个理想的GUI库应该是什么样子的感受出发Q从而开始了对这个库的开发。有兴趣的可以尝试一下。?/p>

参考网站:http://www.fox-toolkit.org/ 

5、 WTL 

ZATL的一个库。因Z用了大量ATL的轻量手法Q模板等技术,在代码尺寸,以及速度优化斚w做得非常C。主要面向的使用体是开发COM轻量U供|络下蝲的可视化控g的开发者。?/p>

6、 GTK 

参考网站:http://gtkmm.sourceforge.net/ 

GTK是一个大名鼎鼎的C的开源GUI库。在Linux世界中有Gnomeq样的杀手应用。而GTK是q个库的C++装版本。?/p>

|络通信?/p>

ACE 

参考网站:http://www.cs.wustl.edu/~schmidt/ACE.html 
 ACE|络~程开发论坛:http://www.acejoy.com

C+ +库的代表Q超重量U的|络通信开发框架。ACE自适配通信环境QAdaptive Communication EnvironmentQ是可以自由使用、开放源代码的面向对象框Ӟ在其中实C许多用于q发通信软g的核心模式。ACE提供了一l丰富的可复用C++ 包装外观QWrapper FacadeQ和框架lgQ可跨越多种q_完成通用的通信软gdQ其中包括:事g多\分离和事件处理器分派、信号处理、服务初始化、进E间通信、共享内存管理、消息\由、分布式服务动态(重)配置、ƈ发执行和同步Q等{。?/p>

StreamModule 

参考网站:http://www.omnifarious.org/StrMod/ 

设计用于化编写分布式E序的库。尝试着使得~写处理异步行ؓ的程序更ҎQ而不是用同步的外壛_起异步的本质。?/p>

SimpleSocket 

参考网站:http://home.hetnet.nl/~lcbokkers/simsock.htm 

q个cd让编写基于socket的客?服务器程序更加容易。?/p>

A Stream Socket API for C++ 

 参考网站:http://www.pcs.cnu.edu/~dgame/sockets/socketsC++/sockets.html 

又一个对Socket的封装库。?/p>

XML 

Xerces 

参考网站:http://xml.apache.org/xerces-c/ 

Xerces-C++ 是一个非常健壮的XML解析器,它提供了验证Q以及SAX和DOM API。XML验证在文档类型定?Document Type DefinitionQDTD)斚w有很好的支持Qƈ且在2001q?2月增加了支持W3C XML Schema 的基本完整的开放标准。?/p>

XMLBooster 

参考网站:http://www.xmlbooster.com/ 

q个库通过产生特制的parser的办法极大的提高了XML解析的速度Qƈ且能够生相应的GUIE序来修改这个parser。在DOM和SAX两大主XML解析办法之外提供了另外一个可行的解决Ҏ。?/p>

Pull Parser 

参考网站:http://www.extreme.indiana.edu/xgws/xsoap/xpp/ 

q个库采用pullҎ的parser。在每个SAX的parser底层都有一个pull的parserQ这个xpp把这层暴露出来直接给大家使用。在要充分考虑速度的时候值得试。?/p>

Xalan 

参考网站:http://xml.apache.org/xalan-c/ 

Xalan是一个用于把XML文档转换为HTMLQ纯文本或者其他XMLcd文档的XSLT处理器。?/p>

CMarkup 

参考网站:http://www.firstobject.com/xml.htm 

 q是一U用EDOM的XML解析器。在很多思\上面非常灉|实用。值得大家在DOM和SAX之外L一点灵感。?/p>

libxml++ 

http://libxmlplusplus.sourceforge.net/ 

libxml++是对著名的libxml XML解析器的C++装版本 

U学计算 

Blitz++ 

参考网站:http://www.oonumerics.org/blitz/ 

Blitz++ 是一个高效率的数D函数库Q它的设计目的是希望建立一套既具像C++ 一h便,同时又比Fortran速度更快的数D环境。通常Q用C++所写出的数值程序,比 Fortran?0%左右Q因此Blitz++正是要改掉这个缺炏V方法是利用C++的template技术,E序执行甚至可以比Fortran更快。 Blitz++目前仍在发展中,对于常见的SVDQFFTsQQMRES{常见的U性代数方法ƈ不提供,不过使用者可以很Ҏ地利用Blitz++所提供的函数来构徏。?/p>

POOMA 

参考网站:http://www.codesourcery.com/pooma/pooma 

POOMA是一个免费的高性能的C++库,用于处理q行式科学计。POOMA的面向对象设计方便了快速的E序开发,对ƈ行机器进行了优化以达到最高的效率Q方便在工业和研I环境中使用。?/p>

MTL 

参考网站:http://www.osl.iu.edu/research/mtl/ 

Matrix Template Library(MTL)是一个高性能的泛型组件库Q提供了各种格式矩阵的大量线性代数方面的功能。在某些应用使用高性能~译器的情况下,比如Intel的编译器Q从产生的汇~代码可以看出其与手写几乎没有两L效能。?/p>

CGAL 

 参考网站:www.cgal.org 

Computational Geometry Algorithms Library的目的是把在计算几何斚w的大部分重要的解x案和Ҏ以C++库的形式提供l工业和学术界的用户。?/p>

游戏开发?/p>

Audio/Video 3D C++ Programming Library 

参考网站:http://www.galacticasoftware.com/products/av/ 

AV3D是一个跨q_Q高性能的C++库。主要的Ҏ是提供3D囑ŞQ声效支持(SB,以及S3MQ,控制接口Q键盘,鼠标和遥感)QXMS。?/p>

KlayGE 

参考网站:http://home.g365.net/enginedev/ 

国内游戏开发高手自qC++开发的游戏引擎。KlayGE是一个开放源代码、跨q_的游戏引擎,q用Python作脚本语a。KlayGE在LGPL协议下发行。感谢龚敏敏先生Z国游戏开发事业所做出的A献。?/p>

OGRE 

参考网站:http://www.ogre3d.org 

OGRE Q面向对象的囑Ş渲染引擎Q是用C++开发的Q用灵zȝ面向对象3D引擎。它的目的是让开发者能更方便和直接地开发基?Dg讑֤的应用程序或游戏。引擎中的类库对更底层的pȝ库(如:Direct3D和OpenGLQ的全部使用l节q行了抽象,q提供了Z现实世界对象的接口和其它cR?/p>

U程 

C++ Threads 

参考网站:http://threads.sourceforge.net/ 

q个库的目标是给E序员提供易于用的c,q些c被l承以提供在Linux环境中很隄到的大量的线E方面的功能。?/p>

ZThreads 

参考网站:http://zthread.sourceforge.net/ 

一个先q的面向对象Q跨q_的C++U程和同步库。?/p>

序列化?br /> s11n 
 参考网站:http://s11n.net/ 
 一个基于STL的C++库,用于序列化PODQSTL容器以及用户定义的类型。?br /> Simple XML Persistence Library 
 参考网站:http://sxp.sourceforge.net/ 
 q是个把对象序列化ؓXML的轻量的C++库。?/p>

字符串?/p>

C++ Str Library 

参考网站:http://www.utilitycode.com/str/ 

操作字符串和字符的库Q支持Windows和支持gcc的多U^台。提供高度优化的代码Qƈ且支持多U程环境和UnicodeQ同时还有正则表辑ּ的支持。?/p>

Common Text Transformation Library 

参考网站:http://cttl.sourceforge.net/ 

q是一个解析和修改STL字符串的库。CTTL substringcd以用来比较,插入Q替换以及用EBNF的语法进行解析。?/p>

GRETA 

参考网站:http://research.microsoft.com/projects/greta/ 

q是由微软研I的研Ih员开发的处理正则表达式的库。在型匚w的情况下有非怼U的表现。?/p>

l合 

P::Classes 

参考网站:http://pclasses.com/ 

一个高度可UL的C++应用E序框架。当前关注类型和U程安全的signal/slot机制Qi/opȝ包括Z插g的网l协议透明的i/o架构Q基于插件的应用E序消息日志框架Q访问sql数据库的cȝ{。?/p>

ACDK - Artefaktur Component Development Kit 

参考网站:http://acdk.sourceforge.net/ 

q是一个^台无关的C++lg框架Q类gJava或?NET中的框架Q反机ӞU程QUnicodeQ废料收集,I/OQ网l,实用工具QXMLQ等{)Q以及对Java, Perl, Python, TCL, Lisp, COM 和 CORBA的集成。?/p>

dlib C++ library 

参考网站:http://www.cis.ohio-state.edu/~kingd/dlib/ 

各种各样的类的一个综合。大整数QSocketQ线E,GUIQ容器类,以及览目录的API{等。?/p>

Chilkat C++ Libraries 

参考网站:http://www.chilkatsoft.com/cpp_libraries.asp 

q是提供zipQe-mailQ编码,S/MIMEQXML{方面的库。?/p>

C++ Portable Types Library (PTypes) 

参考网站:http://www.melikyan.com/ptypes/ 

q是STL的比较简单的替代品,以及可移植的多线E和|络库。?/p>

LFC 

参考网站:http://lfc.sourceforge.net/ 

哦,q又是一个尝试提供一切的C++库?/p>

 

其他库?/p>

Loki 

参考网站:http://www.moderncppdesign.com/ 

哦,你可能抱怨我早该和Boost一起介l它Q一个实验性质的库。作者在loki中把C++模板的功能发挥到了极致。ƈ且尝试把cM设计模式q样思想层面的东襉K过库来提供。同时还提供了智能指针这h较实用的功能。?/p>

ATL 

ATL(Active Template Library)是一l小巧、高效、灵zȝc,q些cMؓ创徏可互操作的COMlg提供了基本的设施。?/p>

FC++: The Functional C++ Library 

q个库提供了一些函数式语言中才有的要素。属于用库来扩充语言的一个代表作。如果想要在OOP之外L另一分的乐趣Q可以去看看函数式程序设计的世界。大师 Peter Norvig在?Teach Yourself Programming in Ten Years"一文中将函数式语a列ؓ臛_应当学习?cȝE语a之一。?/p>

FACT! 

参考网站:http://www.kfa-juelich.de/zam/FACT/start/index.html 

另外一个实现函数式语言Ҏ的库?/p>

Crypto++ 

提供处理密码Q消息验证,单向hashQ公匙加密系l等功能的免费库。?/p>

q有很多非常Ȁ动h心或者是极其实用的C++库,限于我们的水q以及文章的幅不能包括q来。在对于q些已经包含q来的库的介l中Q由于ƈ不是每一个我们都使用q,所以难免有偏颇之处Q请读者见谅。?/p>

资源|站 

正如我们可以通过计算机历史上的重要h物了解计机史的发展QC++相关人物的网站也可以使我们得到最有h值的参考与借鉴Q下面的人物我们认ؓ没有介绍的必要,只因下面的h物在C++领域的地位众所周知Q我们只相关的资源q行|列以供读者学习,他们有的工作于贝实验室Q有的工作于知名~译器厂商,有的在不断推q语a的标准化Q有的ؓ读者撰写了多部千古奇作...... 

Bjarne Stroustrup http://www.research.att.com/~bs/ 

Stanley B. Lippman 

http: //blogs.msdn.com/slippman/ 中文版 http: //www.zengyihome.net/slippman/index.htm
 Scott Meyers http://www.aristeia.com/ 

David Musser http://www.cs.rpi.edu/~musser/ 

Bruce Eckel http://www.bruceeckel.com 

Nicolai M. Josuttis http://www.josuttis.com/ 

Herb Sutter http://www.gotw.ca/ 

Andrei Alexandrescu http://www.moderncppdesign.com/


 



erran 2007-10-13 16:42 发表评论
]]>
转:Little Endian & Big Endianhttp://www.shnenglu.com/erran/archive/2007/10/13/34115.htmlerranerranSat, 13 Oct 2007 08:23:00 GMThttp://www.shnenglu.com/erran/archive/2007/10/13/34115.htmlhttp://www.shnenglu.com/erran/comments/34115.htmlhttp://www.shnenglu.com/erran/archive/2007/10/13/34115.html#Feedback0http://www.shnenglu.com/erran/comments/commentRss/34115.htmlhttp://www.shnenglu.com/erran/services/trackbacks/34115.html原文Q?a >http://dev.csdn.net/article/39/39864.shtm

 Little Endian & Big Endian    

q个标题中的Endian是什么意思呢Q还是让我们先来看看下面的情况,q是内存中一个WORDg的内容,那么q个WORD中的值是0x1234呢,q是0x3412 ? 

low byte high byte 
0x12      0x34 

熟悉x86汇编的h立刻q道这个值应?x3412Q很对,但在一些情况下Q比如说你在SGI的机器上看到q种情况Q则正好相反Q?x1234才是正确{案Q这与CPU内部处理数据的方式有兟뀂这两种处理方式都存在于不同厂商生的CPU之中Q在上例中若此WORDgؓ0x3412的,我们UC为little-endian, 若ؓ0x1234的,我们UC为big-endianQ这是两U不同的byte orders。MSDN中有比较_的定义如下:

Byte Ordering Byte ordering Meaning 
big-endian The most significant byte is on the left end of a word. 
little-endian The most significant byte is on the right end of a word. 

一般来说我们不用关心byte ordering的问题,但若要涉及跨q_之间的通信和资源共享,则不得不考虑q个问题了。也怽会说Q我永远不会ȝ其它非x86的CPUQ也许是q样Q你甚至可以不必知道我们最常用的IntelQAMD{生产的x86的byte ordering是little-endian的,而且按现在的装机数量来看Q可以说世界上绝大多数CPU是little-endian的,但多了解一些没有什么坏处,也许有用上的一天,实际若您要涉及到|络~程Q了解一些还是有所帮助的,看完本文后您应该知道ؓ何socket~程中ؓ何要用到如 ntohl, htonl, ntohs, htonsq几个看h名字g怪怪的API了,也很Ҏ理解q些函数名的意义了?

假设我们要在不同byte ordering的机器之间传输和交换数据Q那该怎么办呢Q有两个ҎQ一是全部{换成文本来传?如XML使用?Q另一个方法两斚w按照某一方的byte orderQ这时就涉及C不同byte order之间怺转换的问题(|络传输标准如TCP/IP采用W二U方法ƈ且由于历史的原因Qbyte ordering是big-endian的)。两U之间该如何转换呢?Ҏ有很多,我们可以先看看MFC中在处理serialize的代码中所用的Ҏ(List), 虽然代码应该是高效易ȝ, 但我个hq不喜欢? 原因是我觉得q不是一U通用优美的方?下面列出的是我自己写的{换的代码Q?

template
F3D_INLINE T ConvertEndian(T  t)

   T tResult = 0; 
   for (int  I = 0; I < sizeof(T); ++ I) 
   { 
      tResult <<= 8;    
      tResult |= (t & 0xFF) ; 

      t >>= 8; 
   } 
   return  tResult;
}

原理非常单,交换字节序Q我׃多说了,当然q个写法q不是快速的, 只是通用?我没条g? 若有不对之处h?, 若要快速的代码Q可以在不同platform上用与platform相关的代? 如在PowerPC上有 "load word byte-reversed indexed" (lwbrx) 和?load halfword byte-reversed indexed" (lhbrx) 指o, 在x86上还可用BSWAP单个汇编指o{,在类型上专ؓint16, int32写的通用的代码也可以比这快得? 

当然如果在byte ordering相同的情况下Q应该不必用q个转换函数Q所以我们可以定义一个宏来处理不同的byte orderingQ也可以在运行时试byte ordering, 下面的代码给Z一个简单的试Ҏ。?


// Test for endianness.
F3D_INLINE bool IsLittleEndian(void)

   DWORD dwTestValue = 0x12345678L; 
   return  (*((BYTE*)&dwTestValue) == 0x78);
}

但是float比较怪,有可能所涉及C仅仅是byte order的问题,因ؓ有些q_如Alpha不用IEEE的QҎ式,q得自己转换。当然同上,其它的方法一是将所用的float用文本方式输入输出,另一个办法是在某些情况下可将其{换成定点数再处理Q这里我不再深入?

如果是读写第三方已经指定byte order的文件或数据,比如说读SGI的位图文件格式,则可以直接自行按指定的byte orderDv来,不必考虑host机是何种byte ordering。下面我l出相应的代码:


// Read a little-endian TYPE from address
template
F3D_INLINE T GetLittleEndian(const BYTE*  pBuf)

   T tResult = 0; 
   pBuf += sizeof(T) - 1; 
   for (int  I = 0; I < sizeof(T); ++ I) 
   { 
      tResult <<= 8; 
      tResult |= *pBuf --; 
   } 

   return  tResult;
}

// Read a big-endian TYPE from address
template
F3D_INLINE T GetBigEndian(const BYTE*  pBuf)

   T tResult = 0; 
   for (int  I = 0; I < sizeof(T); ++ I) 
   { 
      tResult <<= 8; 
      tResult |= *pBuf ++; 
   } 

   return  tResult;
}

// Set a little-endian TYPE on a address
template
F3D_INLINE void SetLittleEndian(BYTE*  pBuf, T  t)

   for (int  I = 0; I < sizeof(T); ++ I) 
   { 
   *pBuf ++ = BYTE(t & 0xFF); 
   t >>= 8; 
   }
}

// Set a big-endian T on a address
template
F3D_INLINE void SetBigEndian(BYTE*  pBuf, T  t)

   pBuf += sizeof(T) - 1; 
   for (int  I = 0; I < sizeof(T); ++ I) 
   { 
      *pBuf -- = BYTE(t & 0xFF); 
      t >>= 8; 
   }
}

从上文可以看出,byte order挺简单的Q一般应用中可能也用不上Q但若您对写跨^台的E序有兴,则一定要了解的比较清楚才行。以上代码都是从实际使用的源码中取下来的。?

附:常见Processor, OS的byte ordering情况

Processor OS Order 
x86 (Intel, AMD, …? All little-endian 
DEC Alpha All little-endian 
HP-PA NT little-endian 
HP-PA UNIX big-endian 
SUN SPARC All? big-endian 
MIPS NT little-endian 
MIPS UNIX big-endian 
PowerPC NT little-endian 
PowerPC non-NT big-endian 
RS/6000 UNIX big-endian 
Motorola m68k All big-endian 



erran 2007-10-13 16:23 发表评论
]]>
怎样实现数目不定的函数参?/title><link>http://www.shnenglu.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.shnenglu.com/erran/archive/2006/12/28/16959.html</guid><wfw:comment>http://www.shnenglu.com/erran/comments/16959.html</wfw:comment><comments>http://www.shnenglu.com/erran/archive/2006/12/28/16959.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.shnenglu.com/erran/comments/commentRss/16959.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/erran/services/trackbacks/16959.html</trackback:ping><description><![CDATA[     摘要:   怎样实现数目不定的函数参?   2006-12-28 erran   实现Ҏ一Q自定义指针扑ֈ函数参数的下一个参敎ͼ   // 例子 A Q? template<class T> T umin(T _a, ...) {       ...  <a href='http://www.shnenglu.com/erran/archive/2006/12/28/16959.html'>阅读全文</a><img src ="http://www.shnenglu.com/erran/aggbug/16959.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/erran/" target="_blank">erran</a> 2006-12-28 20:21 <a href="http://www.shnenglu.com/erran/archive/2006/12/28/16959.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>函数指针(全局函数/cL员函?、函数对?Function object)http://www.shnenglu.com/erran/archive/2006/12/26/16868.htmlerranerranTue, 26 Dec 2006 05:27:00 GMThttp://www.shnenglu.com/erran/archive/2006/12/26/16868.htmlhttp://www.shnenglu.com/erran/comments/16868.htmlhttp://www.shnenglu.com/erran/archive/2006/12/26/16868.html#Feedback2http://www.shnenglu.com/erran/comments/commentRss/16868.htmlhttp://www.shnenglu.com/erran/services/trackbacks/16868.html阅读全文

erran 2006-12-26 13:27 发表评论
]]>
C/C++头文件一?/title><link>http://www.shnenglu.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.shnenglu.com/erran/archive/2006/05/30/7906.html</guid><wfw:comment>http://www.shnenglu.com/erran/comments/7906.html</wfw:comment><comments>http://www.shnenglu.com/erran/archive/2006/05/30/7906.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/erran/comments/commentRss/7906.html</wfw:commentRss><trackback:ping>http://www.shnenglu.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">、传l?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 <assert.h>//</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 <ctype.h> //</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 <errno.h> //</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 <float.h> //</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 <fstream.h></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>文g输入Q输?/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 <iomanip.h></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 <iostream.h></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 <limits.h>//</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">定义各种数据cd最值常?/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 <locale.h>//</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 <math.h></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 <stdio.h> //</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">定义输入Q输出函?/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 <stdlib.h>//</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 <string.h>//</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 <strstrea.h></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>Z数组的输入/输出</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 <time.h></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 <wchar.h> //</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">宽字W处理及输入Q输?/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 <wctype.h>//</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">宽字W分c?/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> Q同上的不再注释Q?/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 <algorithm></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 <bitset></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 <cctype></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 <cerrno></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 <clocale></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 <cmath></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 <complex> //</span> <span 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 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 <cstdio></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 <cstdlib></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 <cstring></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 <ctime></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 <deque></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 <exception></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>异常处理c?/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 <fstream></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 <functional></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>定义q算函数Q代替运符Q?/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 <limits></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 <list>//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">U性列表容?/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 <map> //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 <iomanip></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 <ios> //</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">基本输入Q输出支?/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 <iosfwd></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>输入Q输出系l用的前置声明</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 <iostream></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 <istream> //</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 <ostream> //</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 <queue></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 <set> //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 <sstream> //</span> <span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">Z字符串的?/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 <stack></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 <stdexcept></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>标准异常c?/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 <streambuf></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>底层输入Q输出支?/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 <string></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 <utility> //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">通用模板c?/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 <vector></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>动态数l容?/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 <cwchar></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 <cwctype></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 <complex.h> //</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 <fenv.h>//</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 <inttypes.h>//</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 <stdbool.h> //</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 <stdint.h></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 <tgmath.h></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>通用cd数学?/span> </p> <img src ="http://www.shnenglu.com/erran/aggbug/7906.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/erran/" target="_blank">erran</a> 2006-05-30 23:35 <a href="http://www.shnenglu.com/erran/archive/2006/05/30/7906.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>我的数据实体里常有的几个函数http://www.shnenglu.com/erran/archive/2006/05/30/7905.htmlerranerranTue, 30 May 2006 15:14:00 GMThttp://www.shnenglu.com/erran/archive/2006/05/30/7905.htmlhttp://www.shnenglu.com/erran/comments/7905.htmlhttp://www.shnenglu.com/erran/archive/2006/05/30/7905.html#Feedback0http://www.shnenglu.com/erran/comments/commentRss/7905.htmlhttp://www.shnenglu.com/erran/services/trackbacks/7905.html在此聊聊我设计数据实体的一些小伎俩^_^ .........     

Z方便数据的组l?span lang=EN-US>.
q算以及数据实体cȝ使用, 一般我会把所有数据实体从同一个实体基cȝ承而来, 基类里有一些常用的函数, 以类CEntiyZ说明如下 :

1.    CEntity(const CEntity& ent);

首先当然是拷贝构造函?span lang=EN-US>, 在实际用实体过E中q个函数很有?span lang=EN-US>, 当然?span lang=EN-US>CEntity的派生类中我也会d现其zcȝ拯构造函?/font> .


2.    virtual ~CEntity();

 
析构函数, q个׃必说?span lang=EN-US>, ?/font> virtual


3.  virtual CString GetTypeID(void) const;

此函数返回一?span lang=EN-US>CStringcd的实体标?span lang=EN-US>, 以标明到底是那个c?span lang=EN-US>, 在基cM我一般这样实?span lang=EN-US>: return  _T("ENT_UNKNOW");   很显然我会在CEntity的每一个派生类中重载这个函?span lang=EN-US>, 有了q个函数, 可以很方便的从一个基cȝ指针知道其实例化的到底是哪一个派生类的对?span lang=EN-US>, q样可以很方便的管理系l中多个怼数据实体可以把所有的数据实体实例化ؓ基类的指?span lang=EN-US>,  关于数据实体的接口都可以用基cȝ指针或者引用类?span lang=EN-US>,  而不用去担心他到底是那个zcȝ对象当然也可?span lang=EN-US> virtual int GetTypeID(void) const;  virtual DWORD GetTypeID(void) const; virtual DWORD GetClassID(void) const;{等?span lang=EN-US>

4.        virtual void Initiate(void);

数据初始化?初始化数据实体的数据.

 

5 Q?span lang=EN-US> virtual void Reset(void);

数据复位操作。把数据实体复位到某一状?span lang=EN-US>.

 

5.        virtual CEntity * Clone(void) const;

克隆数据实体. q个函数一般这样实?span lang=EN-US>: return new CEntity(*this);

 

6.        virtual void Serialize(CArchive& ar);

数据串行?span lang=EN-US>. 以实现数据实体左右移方式的对数据实体赋?span lang=EN-US>,保存{操?span lang=EN-US>. 常把其与CMemFile一起?span lang=EN-US>,感觉效果很好.唯一不的是解决数据实体版本升时的数据一致性的问题很麻?span lang=EN-US>.


7.        virtual BOOL DataSet(const CEntity& ent);

h数据,实现数据实体之间的赋值操?span lang=EN-US>.q个函数主要是ؓ了解决上一所提的问题( C++随笔关于virtual poperator = ( 05-22 01:09) ). 可以把他设ؓprotectedcd, ?span lang=EN-US>operator=l合h使用, ?span lang=EN-US>poperator =调用.


8.           const CEntity& operator=(const CEntity& ent);

赋值操?span lang=EN-US>.在派生类中也会重?span lang=EN-US>operator=, 不是重蝲基类?span lang=EN-US>operator=.


9.        另外如果存在数据比较的话, 会重?span lang=EN-US>operator==操作W?span lang=EN-US>.

 friend bool operator==(const CEntity& ent1, const CEntity& ent2);

 friend bool operator!=(const CEntity& ent1, const CEntity& ent2);

 

谢谢x~~~

以下附三相电电压数据实体部分实C?span lang=EN-US>:

 

class CThreePhaseEntity: public CEntity

{

public:

       CThreePhaseEntity ();

       CThreePhaseEntity (const CSixPhaseEntity& ent);

       ~CSixPhaseEntity();

public:

       CString GetTypeID(void) const;

       void Initiate(void);

       void Reset(void);

 

public:

       CEntity * Clone(void) const;

       void Serialize(CArchive& ar);

       BOOL DataSet(const CEntity& ent);

 

public:

       const CSixPhaseEntity& operator=(const CSixPhaseEntity& ent);

       friend bool operator==(const CSixPhaseEntity& ent1, const CSixPhaseEntity& ent2);

       friend bool operator!=(const CSixPhaseEntity& ent1, const CSixPhaseEntity& ent2);

 

public:

// 获取三相数据 , 内联函数

       const float& GetSixPhaseData(int nDateType, int nPhaseMark) const;

       // 修改三相数据 , 内联函数

       void SetSixPhaseData(int nDataType, int nPhaseMark, const float& fData);

 

private:   

       float m_gfRange[3];  // q?/span> ,

       float m_gfPhase[3];  // ,

       float m_gfFrequency[3];  // 频率

};

 

 

 

///******cpp 文g

 

CThreePhaseEntity:: CThreePhaseEntity ()

{

       Initiate();

}

 

CThreePhaseEntity:: CThreePhaseEntity (const CThreePhaseEntity & ent)

{

       for(int i=0; i<3; i++)

       {

              m_gfRange[i] = ent.m_gfRange[i];

              m_gfPhase[i] = ent.m_gfPhase[i];

              m_gfFrequency[i] = ent.m_gfFrequency[i];

       }

}

 

CThreePhaseEntity::~ CThreePhaseEntity ()

{

}

 

CString CThreePhaseEntity::GetTypeID(void) const

{

       return _T("ENT_THREEPHASE ");

}

 

void CThreePhaseEntity::Initiate()

{

       for(int i=0; i<3; i++)

       {

              m_gfRange[i] = 0.0f;

              m_gfPhase[i] = 0.0f;

              m_gfFrequency[i] = 0.0f;

       }

}

 

void CThreePhaseEntity::Reset(void)

{

       for(int i=0; i<3; i++)

       {

              m_gfRange[i] = 57.740f;

m_gfFrequency[i] = 50.0f;

}

m_ gfPhase [0] = 0.0f

m_ gfPhase [1] = -120.0f

m_ gfPhase [2] = 120.0f

}

 

void CThreePhaseEntity::Serialize(CArchive& ar)

{

       if(ar.IsStoring())

       {

              for(int i=0; i<3; i++)

{

ar<<m_gfRange[i]<<m_gfPhase[i]<<m_gfFrequency[i];

}

       }

       else

       {

              for(int i=0; i<3; i++)

{

ar>>m_gfRange[i]>>m_gfPhase[i]>>m_gfFrequency[i];

}

       }

}

 

BOOL CThreePhaseEntity::DataSet(const CEntity& ent)

{

       if(GetTypeID() != ent.GetTypeID()) return FALSE;

      

       const CThreePhaseEntity * pEnt = reinterpret_cast<const CThreePhaseEntity *>(&ent);

 

       (*this) = (*pEnt);

 

       return TRUE;

}

 

CEntity * CThreePhaseEntity::Clone(void) const

{

       return new CThreePhaseEntity (*this);

}

 

const CThreePhaseEntity & CThreePhaseEntity::operator=(const CThreePhaseEntity & ent)

{

       if(this == &ent) return *this;

 

       for(int i=0; i<3; i++)

       {

              m_gfRange[i] = ent.m_gfRange[i];

              m_gfPhase[i] = ent.m_gfPhase[i];

              m_gfFrequency[i] = ent.m_gfFrequency[i];

       }

 

       return *this;

}

 

bool operator==(const CThreePhaseEntity & ent1, const CThreePhaseEntity & ent2)

{

       for(int i=0; i<3; i++)

       {

              if(ent1.m_gfRange[i] != ent2.m_gfRange[i]) return false;

              if(ent1.m_gfPhase[i] != ent2.m_gfPhase[i]) return false;

              if(ent1.m_gfFrequency[i] != ent2.m_gfFrequency[i]) return false;

       }

 

       return true;

}

 

bool operator!=(const CThreePhaseEntity & ent1, const CThreePhaseEntity & ent2)

{

       return (ent1 == ent2) ? false : true;

}



erran 2006-05-30 23:14 发表评论
]]>
C++随笔 关于virtual operator =http://www.shnenglu.com/erran/archive/2006/05/22/7466.htmlerranerranSun, 21 May 2006 17:09:00 GMThttp://www.shnenglu.com/erran/archive/2006/05/22/7466.htmlhttp://www.shnenglu.com/erran/comments/7466.htmlhttp://www.shnenglu.com/erran/archive/2006/05/22/7466.html#Feedback1http://www.shnenglu.com/erran/comments/commentRss/7466.htmlhttp://www.shnenglu.com/erran/services/trackbacks/7466.html如果在派生类中要重蝲zcȝoperator = Q那么在基类中一般不要重载operator = Q因样会带来很多ȝ.

定义了两个类Q?br> class CBase
{  
public:
   CBase()
   {
        cout<<"CBase constructing ..."<<endl;
    }
   virtual ~CBase()
   {
        cout<<"CBase destructing ..."<<endl;
    }
public:
   CBase & operator=(const CBase & ent)
   {
         cout<<"CBase operator = ... "<<endl;
         return *this;
    }
};

class CDerive: public CBase
{
public:
     CDerive()
     {
           cout<<"CDerive constructing 
     }
     ~CDerive()
     {
            cout<<"CDerive destructing ..."<<endl;
      } 
public:
     CDerive & operator=(const CDerive & ent)
    {
           cout<<"CDerive operator = ... "<<endl;
           return *this;
     }
}

定义如下操作Q?br>
CBase * b1 = new CDerive();
CBase * b2 = new CDerive();

(*b1) = (*b2);

可以看到其输ZؓQ?br>CBase constructing ...
CDerive constructing ...
CBase constructing ...
CDerive constructing ...
CBase operator = ...
CDerive destructing ...
CBase destructing ...
CDerive destructing ...
CBase destructing

而实际上Q操?*b1) = (*b2)是想把b1,b2实际所指类型的两个对象之间q行赋|但是它只是调用了基类的赋值操作,没有执行其本w派生类的赋值操作?br>
发现有两U方法可以解册个问题,如果能够知道基类指针实际所指的是哪个派生类的的对象Q直接类型{换就可以了:

(*((CDerive*)b1)) = (*((CDerive*)b2));

q样可以发现输出了:CDerive operator = ... 。但是当要定义基cȝ指针的时候,往往隐藏了具体的zc,卛_往不知道指针到底实现的是哪个派生类Q所以这U方法有很多局限性?br>
q时候可以采用第二种ҎQ即在派生类中重载基cȝ赋值操作符Q即首先把基cȝoperator=定义为virtual operatorQ,再在zcM重蝲q个Q如Q?br>
CBase & operator=(const CBase & ent)
 {
       const CDerive * p = reinterpret_cast<const CDerive *>(&ent);
       return operator=((*p));
 }

好的Q当再执?(*b1) = (*b2) 的时候就可以看到输出QCDerive operator = ... ?br>

 在此发现在派生类中重载派生类的operator =的时候,如果在基cM也重载operator = Q这样会带来很多ȝQ可能会丢失很多也许不想丢失的数据?br> 
同样Q依ơ还存在问题Q?
CBase * b1 = new CDerive();
CDervie * d1 = new CDerive();

(*b1) = (*d1);

CBase * b2 = new CBase ();
CDervie * d2 = new CDerive();
(*b2) = (*d2);

所以我个h觉得Q如果一个基cL很多个派生类的,而派生类中又重蝲了派生类本n的赋值操作符的时候,则基cM最好不要去重蝲赋值操作符Q不如直接用函数去赋倹{正?c++~程思想>所说那Pq算W重载只是ؓ了一U语法上的方便,是另外一U函数调用方式,如果不能带来方便Q就没必要了Q还不如直接用函数去代替?


.............敬请指点..................


erran 2006-05-22 01:09 发表评论
]]>
C++随笔 关于赋值操?内存丢失http://www.shnenglu.com/erran/archive/2006/05/21/7451.htmlerranerranSat, 20 May 2006 16:47:00 GMThttp://www.shnenglu.com/erran/archive/2006/05/21/7451.htmlhttp://www.shnenglu.com/erran/comments/7451.htmlhttp://www.shnenglu.com/erran/archive/2006/05/21/7451.html#Feedback4http://www.shnenglu.com/erran/comments/commentRss/7451.htmlhttp://www.shnenglu.com/erran/services/trackbacks/7451.html开发中发现在进?nbsp;赋值操作的时候,很容易内存丢失,看实例:

class CEntity
{
public:
    CEntity(char flag);
    ~CEntity();
private: 
    char m_flag;
};

CEntity::CEntity(char flag)
{
    m_flag = flag; 
    cout<<"constructing entity "<<m_flag<<endl; 
}

CEntity::~CEntity()
{
 cout<<"destructing entity "<<m_flag<<endl;
}

执行代码Q?br>int main(int argc, char* argv[])
{
    CEntity m('m'),n('n');
    m = n;
    return 0;
}

输出为:
constructing entity m
constructing entity n
destructing entity n
destructing entity n

q个没有出现M问题Q很成功Q因为在CEntity里面没有newM东西Q如果把CEntity该ؓQ?br>class CEntity
{
enum {SIZE = 10};
public:
    CEntity(char flag);
    ~CEntity();
private:     
    char * m_flag;
};

CEntity::CEntity(char flag)
{
    m_flag = new char[SIZE ];
    m_flag[0] = flag; 
    cout<<"constructing entity "<<m_flag[0]<<endl; 
}

CEntity::~CEntity()
{
 cout<<"destructing entity "<<m_flag[0]<<endl;
delete[] m_flag;
}

执行同样的main函数Q程序将无法q行Qdebug assertion error!

q个问题该怎么解决Q?/font> 先睡?br>

如oosky所_重蝲了赋值操作符Q问题就解决了,


CEntity & CEntity::operator=(const CEntity & ent)
{
    if (ent.m_flag == NULL)
    {
        if (m_flag != NULL)
        {
            delete [] m_flag;
            m_flag = NULL;
        }
    }
    else 
    {
        if (m_flag == NULL)
        {
            m_flag = new char[SIZE];
        }
  
        for(int i=0; i<SIZE; i++)
        {  
               m_flag[i] = ent.m_flag[i];
        }
    }
    return *this;
}

由此可见自定义对象之间的赋值操作要心行事.....

 



erran 2006-05-21 00:47 发表评论
]]>
C++随笔 delete void *http://www.shnenglu.com/erran/archive/2006/05/20/7450.htmlerranerranSat, 20 May 2006 15:48:00 GMThttp://www.shnenglu.com/erran/archive/2006/05/20/7450.htmlhttp://www.shnenglu.com/erran/comments/7450.htmlhttp://www.shnenglu.com/erran/archive/2006/05/20/7450.html#Feedback4http://www.shnenglu.com/erran/comments/commentRss/7450.htmlhttp://www.shnenglu.com/erran/services/trackbacks/7450.html用了q么久的C++Q才发现C++是目前所有的~成语言中最为复杂的一U,C++之\,   艰难.....

   
            delete void *

           q一操作对于一些简单的pȝ内徏cd不会有问题,但如果void*所指向的对象在析构函数里要释放Q进行此造作会丢失内存,因ؓ它不执行析构函数Q例如:                               
                                    
class CEntity
{
public:
    CEntity(char flag);
    ~CEntity();
private:
    void * m_data;
   char   m_flag;
};

CEntity::CEntity(char flag)
{
   m_flag = flag;
    cout<<"constructing entity "<<m_flag<<endl;
    m_data = new char[100]; 
}

CEntity::~CEntity()
{
    cout<<"destructing entity "<<m_flag<<endl;
    delete[] m_data;
}

以上q个cL没什么问题的Q但是看以下的调用:
int main(int argc, char* argv[])
{
       CEntity * a = new CEntity('a');
       delete a;

       void * b = new CEntity('b');
       delete b;
 
       return 0;
}

其输ZؓQ?nbsp;constructing entity a
                       destructing entity a
                       constructing entity b                                    
可见Qdelete b 的时候没有释放m_data所指向的内存,没有执行析构函数?nbsp;              
                     
               



erran 2006-05-20 23:48 发表评论
]]>
ھƷ˾þþþø| þùŷպƷ| պŷþþwwwۺ | 㽶97þ| 999Ʒþþþþ| ҹƷþþþþ˳| 99þѹƷػ| þþþþҹӰԺ| þҹɫƷwww| þþһ| þþþƷһ| ɫͷվþ| þó˾ƷƵ| þþAVҰ| ޾Ʒһþ| 鶹WWWþöڲƷ| 97Ʒ˾þþô߽ | þþþ99ƷƬ| ŷպľþ| þˬ˾ƷƵ | Ʒ99þò| þۺϾþ߾Ʒ | ŷ˾þۺһ | þþŷղ| Ʒþþ99| 99þ99þþþƷ| 2021ھþþƷ| þþþƷ| һþöۺ| þҹɫƷ| þ99Ʒ鶹լլ| ޾Ʒþþþþο| þùƵ| þþƷAɫ| þ99Ʒ鶹| vaþþþúݺ| þþþþüƷþþ| þþƷһĻ| 99þɫĻ| Ʒþþþþø | ۺϾƷ㽶þ|