﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-道。道。道-随笔分类-C/C++/STL/ATL/WTL</title><link>http://www.cppblog.com/eday/category/2953.html</link><description /><language>zh-cn</language><lastBuildDate>Sat, 24 May 2008 10:27:48 GMT</lastBuildDate><pubDate>Sat, 24 May 2008 10:27:48 GMT</pubDate><ttl>60</ttl><item><title>C++代码优化</title><link>http://www.cppblog.com/eday/archive/2007/02/17/18844.html</link><dc:creator>松*</dc:creator><author>松*</author><pubDate>Sat, 17 Feb 2007 14:05:00 GMT</pubDate><guid>http://www.cppblog.com/eday/archive/2007/02/17/18844.html</guid><description><![CDATA[     谈到优化，很多人都会直接想到汇编。难道优化只能在汇编层次吗？当然不是，C++层次一样可以作代码优化，其中有些常常是意想不到的。在C++层次进行优化，比在汇编层次优化具有更好的移植性，应该是优化中的首选做法。 <br />1.确定浮点型变量和表达式是 float 型 <br />    为了让编译器产生更好的代码(比如说产生3DNow! 或SSE指令的代码)，必须确定浮点型变量和表达式是 float 型的。要特别注意的是，以 "；F"； 或 "；f"； 为后缀（比如：3.14f）的浮点常量才是 float 型，否则默认是 double 型。为了避免 float 型参数自动转化为 double，请在函数声明时使用 float。 <br />2.使用32位的数据类型 <br />　　编译器有很多种，但它们都包含的典型的32位类型是：int，signed，signed int，unsigned，unsigned int，long，signed long，long int，signed long int，unsigned long，unsigned long int。尽量使用32位的数据类型，因为它们比16位的数据甚至8位的数据更有效率。 <br />3.明智使用有符号整型变量 <br />　　在很多情况下，你需要考虑整型变量是有符号还是无符号类型的。比如，保存一个人的体重数据时不可能出现负数，所以不需要使用有符号类型。但是，如果是要保存温度数据，就必须使用到有符号的变量。 <br />　　在许多地方，考虑是否使用有符号的变量是必要的。在一些情况下，有符号的运算比较快；但在一些情况下却相反。 <br />　　比如：整型到浮点转化时，使用大于16位的有符号整型比较快。因为x86构架中提供了从有符号整型转化到浮点型的指令，但没有提供从无符号整型转化到浮点的指令。看看编译器产生的汇编代码： <br />　　不好的代码： <br />编译前      编译后 <br />double x；    mov [foo + 4], 0 <br />unsigned int i；   mov eax, i <br />x = i；     mov [foo], eax <br />     flid qword ptr [foo] <br />     fstp qword ptr [x] <br />　　上面的代码比较慢。不仅因为指令数目比较多，而且由于指令不能配对造成的FLID指令被延迟执行。最好用以下代码代替： <br />    推荐的代码： <br />编译前     编译后 <br />double x；    fild dword ptr <br />int i；     fstp qword ptr [x] <br />x = i； <br />　　在整数运算中计算商和余数时，使用无符号类型比较快。以下这段典型的代码是编译器产生的32位整型数除以4的代码： <br />　　不好的代码  <br />编译前      编译后 <br />int i；     mov eax, i <br />i = i / 4；     cdq <br />     and edx, 3 <br />     add eax, edx <br />     sar eax, 2 <br />     mov i, eax <br />    推荐的代码<br />编译前      编译后 <br />unsigned int i；    shr i, 2 <br />i = i / 4； <br />　总结：<br />　无符号类型用于：除法和余数,循环计数,数组下标<br />  有符号类型用于：整型到浮点的转化<br />4.while VS. for <br />　　在编程中，我们常常需要用到无限循环，常用的两种方法是while (1) 和 for (；；)。这两种方法效果完全一样，但那一种更好呢？然我们看看它们编译后的代码： <br />编译前      编译后 <br />while (1)；     mov eax,1 <br />     test eax,eax <br />     je foo+23h <br />     jmp foo+18h <br />编译前      编译后  <br />for (；；)；     jmp foo+23h <br />　　一目了然，for (；；)指令少，不占用寄存器，而且没有判断跳转，比while (1)好。 <br />5.使用数组型代替指针型 <br />　　使用指针会使编译器很难优化它。因为缺乏有效的指针代码优化的方法，编译器总是假设指针可以访问内存的任意地方，包括分配给其他变量的储存空间。所以为了编译器产生优化得更好的代码，要避免在不必要的地方使用指针。一个典型的例子是访问存放在数组中的数据。C++ 允许使用操作符 [] 或指针来访问数组，使用数组型代码会让优化器减少产生不安全代码的可能性。比如，x[0] 和x[2] 不可能是同一个内存地址，但 *p 和 *q 可能。强烈建议使用数组型，因为这样可能会有意料之外的性能提升。 <br />    不好的代码<br />typedef struct<br />{<br />　　float x,y,z,w；<br />} VERTEX；<br />typedef struct 
<p>{<br />　　float m[4][4]；<br />} MATRIX；<br />void XForm(float* res, const float* v, const float* m, int nNumVerts)<br />{<br />　　float dp；<br />　　int i；<br />　　　const VERTEX* vv = (VERTEX *)v；<br />　　　for (i = 0； i &lt;； nNumVerts； i++)<br />　　{<br />　　　　dp = vv-&gt;；x * *m ++；<br />　　　　dp += vv-&gt;；y * *m ++；<br />　　　　dp += vv-&gt;；z * *m ++；<br />　　　　dp += vv-&gt;；w * *m ++；<br />　　　　*res ++ = dp；　　　　　　// 写入转换了的 x<br />　　　　dp = vv-&gt;；x * *m ++；<br />　　　　dp += vv-&gt;；y * *m ++；<br />　　　　dp += vv-&gt;；z * *m ++；<br />　　　　dp += vv-&gt;；w * *m ++；<br />　　　　*res ++ = dp；　　　　　// 写入转换了的 y<br />　　　　dp = vv-&gt;；x * *m ++；<br />　　　　dp += vv-&gt;；y * *m ++；<br />　　　　dp += vv-&gt;；z * *m ++；<br />　　　　dp += vv-&gt;；w * *m ++；<br />　　　　*res ++ = dp；　　　　// 写入转换了的 z<br />　　　　dp = vv-&gt;；x * *m ++；<br />　　　　dp += vv-&gt;；y * *m ++；<br />　　　　dp += vv-&gt;；z * *m ++；<br />　　　　dp += vv-&gt;；w * *m ++；<br />　　　　*res ++ = dp；　　　　// 写入转换了的 w<br />　　　　vv ++；　　　　　　　 // 下一个矢量<br />　　　　m -= 16；<br />　　}<br />}<br />    推荐的代码 <br />typedef struct<br />{<br />　　float x,y,z,w；<br />} VERTEX；<br />typedef struct<br />{<br />　　float m[4][4]；<br />} MATRIX；<br />void XForm (float* res, const float* v, const float* m, int nNumVerts)<br />{<br />　　int i；<br />　　const VERTEX* vv = (VERTEX*)v；<br />　　const MATRIX* mm = (MATRIX*)m；<br />　　VERTEX* rr = (VERTEX*)res；<br />　　for (i = 0； i &lt;； nNumVerts； i++)<br />　　{<br />　　　　rr-&gt;；x = vv-&gt;；x * mm-&gt;；m[0][0] + vv-&gt;；y * mm-&gt;；m[0][1]<br />　　　　　　　　+ vv-&gt;；z * mm-&gt;；m[0][2] + vv-&gt;；w * mm-&gt;；m[0][3]；<br />　　　　rr-&gt;；y = vv-&gt;；x * mm-&gt;；m[1][0] + vv-&gt;；y * mm-&gt;；m[1][1]<br />　　　　　　　　+ vv-&gt;；z * mm-&gt;；m[1][2] + vv-&gt;；w * mm-&gt;；m[1][3]；<br />　　　　rr-&gt;；z = vv-&gt;；x * mm-&gt;；m[2][0] + vv-&gt;；y * mm-&gt;；m[2][1]<br />　　　　　　　　+ vv-&gt;；z * mm-&gt;；m[2][2] + vv-&gt;；w * mm-&gt;；m[2][3]；<br />　　　　rr-&gt;；w = vv-&gt;；x * mm-&gt;；m[3][0] + vv-&gt;；y * mm-&gt;；m[3][1]<br />　　　　　　　　+ vv-&gt;；z * mm-&gt;；m[3][2] + vv-&gt;；w * mm-&gt;；m[3][3]；<br />　　}<br />} <br />　　注意: 源代码的转化是与编译器的代码发生器相结合的。从源代码层次很难控制产生的机器码。依靠编译器和特殊的源代码，有可能指针型代码编译成的机器码比同等条件下的数组型代码运行速度更快。明智的做法是在源代码转化后检查性能是否真正提高了，再选择使用指针型还是数组型。 <br />6.充分分解小的循环 <br />　　要充分利用CPU的指令缓存，就要充分分解小的循环。特别是当循环体本身很小的时候，分解循环可以提高性能。BTW:很多编译器并不能自动分解循环。 <br />不好的代码 推荐的代码 <br />// 3D转化：把矢量 V 和 4x4 矩阵 M 相乘<br />for (i = 0； i &lt;； 4； i ++)<br />{<br />　　r = 0；<br />　　for (j = 0； j &lt;； 4； j ++)<br />　　{<br />　　　　r += M[j]*V[j]；<br />　　}<br />}<br />r[0] = M[0][0]*V[0] + M[1][0]*V[1] + M[2][0]*V[2] + M[3][0]*V[3]；<br />r[1] = M[0][1]*V[0] + M[1][1]*V[1] + M[2][1]*V[2] + M[3][1]*V[3]；<br />r[2] = M[0][2]*V[0] + M[1][2]*V[1] + M[2][2]*V[2] + M[3][2]*V[3]；<br />r[3] = M[0][3]*V[0] + M[1][3]*V[1] + M[2][3]*V[2] + M[3][3]*v[3]； <br />7.避免没有必要的读写依赖 <br />　　当数据保存到内存时存在读写依赖，即数据必须在正确写入后才能再次读取。虽然AMD Athlon等CPU有加速读写依赖延迟的硬件，允许在要保存的数据被写入内存前读取出来，但是，如果避免了读写依赖并把数据保存在内部寄存器中，速度会更快。在一段很长的又互相依赖的代码链中，避免读写依赖显得尤其重要。如果读写依赖发生在操作数组时，许多编译器不能自动优化代码以避免读写依赖。所以推荐程序员手动去消除读写依赖，举例来说，引进一个可以保存在寄存器中的临时变量。这样可以有很大的性能提升。下面一段代码是一个例子： <br />    不好的代码<br />float x[VECLEN], y[VECLEN], z[VECLEN]；<br />...... <br />for (unsigned int k = 1； k &lt;； VECLEN； k ++)<br />{<br />　　x[k] = x[k-1] + y[k]；<br />}<br />for (k = 1； k &lt;； VECLEN； k++)<br />{<br />　　x[k] = z[k] * (y[k] - x[k-1])；<br />}<br />　　 推荐的代码 <br />float x[VECLEN], y[VECLEN], z[VECLEN]；<br />...... <br />float t(x[0])；<br />for (unsigned int k = 1； k &lt;； VECLEN； k ++)<br />{<br />　　t = t + y[k]；<br />　　x[k] = t；<br />}<br />t = x[0]；<br />for (k = 1； k &lt;； VECLEN； k ++)<br />{<br />　　t = z[k] * (y[k] - t)；<br />　　x[k] = t；<br />} <br />8.Switch 的用法 <br />　　Switch 可能转化成多种不同算法的代码。其中最常见的是跳转表和比较链/树。推荐对case的值依照发生的可能性进行排序，把最有可能的放在第一个，当switch用比较链的方式转化时，这样可以提高性能。此外，在case中推荐使用小的连续的整数，因为在这种情况下，所有的编译器都可以把switch 转化成跳转表。 <br />    不好的代码<br />int days_in_month, short_months, normal_months, long_months；<br />...... <br />switch (days_in_month)<br />{<br />　　case 28:<br />　　case 29:<br />　　　　short_months ++；<br />　　　　break；<br />　　case 30:<br />　　　　normal_months ++；<br />　　　　break；<br />　　case 31:<br />　　　　long_months ++；<br />　　　　break；<br />　　default:<br />　　　　cout &lt;；&lt;； "；month has fewer than 28 or more than 31 days"； &lt;；&lt;； endl；<br />　　　　break；<br />}<br />    推荐的代码 <br />int days_in_month, short_months, normal_months, long_months；<br />...... <br />switch (days_in_month)<br />{<br />　　case 31:<br />　　　　long_months ++；<br />　　　　break；<br />　　case 30:<br />　　　　normal_months ++；<br />　　　　break；<br />　　case 28:<br />　　case 29:<br />　　　　short_months ++； <br />　　　　break；<br />　　default:<br />　　　　cout &lt;；&lt;； "；month has fewer than 28 or more than 31 days"； &lt;；&lt;； endl；<br />　　　　break；<br />} <br />9.所有函数都应该有原型定义 <br />　　一般来说，所有函数都应该有原型定义。原型定义可以传达给编译器更多的可能用于优化的信息。 <br />　　尽可能使用常量(const)。C++ 标准规定，如果一个const声明的对象的地址不被获取，允许编译器不对它分配储存空间。这样可以使代码更有效率，而且可以生成更好的代码。 <br />10.提升循环的性能<br />　　要提升循环的性能，减少多余的常量计算非常有用（比如，不随循环变化的计算）。 <br />　　不好的代码(在for()中包含不变的if()) 推荐的代码 <br />for( i ... )<br />{<br />　　if( CONSTANT0 )<br />　　{<br />　　　　DoWork0( i )； // 假设这里不改变CONSTANT0的值<br />　　}<br />　　else<br />　　{<br />　　　　DoWork1( i )； // 假设这里不改变CONSTANT0的值<br />　　}<br />}<br />if( CONSTANT0 )<br />{<br />　　for( i ... )<br />　　{<br />　　　　DoWork0( i )；<br />　　}<br />}<br />else<br />{<br />　　for( i ... )<br />　　{<br />　　　　DoWork1( i )；<br />　　}<br />} <br />　　如果已经知道if()的值，这样可以避免重复计算。虽然不好的代码中的分支可以简单地预测，但是由于推荐的代码在进入循环前分支已经确定，就可以减少对分支预测的依赖。 　　把本地函数声明为静态的(static) <br />　　如果一个函数在实现它的文件外未被使用的话，把它声明为静态的(static)以强制使用内部连接。否则，默认的情况下会把函数定义为外部连接。这样可能会影响某些编译器的优化——比如，自动内联。 <br />11.考虑动态内存分配 <br />　　动态内存分配（C++中的"；new"；）可能总是为长的基本类型（四字对齐）返回一个已经对齐的指针。但是如果不能保证对齐，使用以下代码来实现四字对齐。这段代码假设指针可以映射到 long 型。 <br />　　例子 <br />　　double* p = (double*)new BYTE[sizeof(double) * number_of_doubles+7L]；<br />    double* np = (double*)((long(p) + 7L) &amp;； –8L)； <br />　　现在，你可以使用 np 代替 p 来访问数据。注意：释放储存空间时仍然应该用delete p。 <br />12.使用显式的并行代码 <br />　　尽可能把长的有依赖的代码链分解成几个可以在流水线执行单元中并行执行的没有依赖的代码链。因为浮点操作有很长的潜伏期，所以不管它被映射成 x87 或 3DNow! 指令，这都很重要。很多高级语言，包括C++，并不对产生的浮点表达式重新排序，因为那是一个相当复杂的过程。需要注意的是，重排序的代码和原来的代码在代数上一致并不等价于计算结果一致，因为浮点操作缺乏精确度。在一些情况下，这些优化可能导致意料之外的结果。幸运的是，在大部分情况下，最后结果可能只有最不重要的位（即最低位）是错误的。 <br />　　不好的代码<br />double a[100], sum；<br />int i；<br />sum = 0.0f；<br />for (i=0； i&lt;；100； i++)<br />　　sum += a； <br />    推荐的代码 <br />double a[100], sum1, sum2, sum3, sum4, sum；<br />int i；<br />sum1 = sum2 = sum3 = sum4 = 0.0；<br />for (i = 0； i &lt;； 100； i += 4)<br />{<br />　　sum1 += a；<br />　　sum2 += a[i+1]；<br />　　sum3 += a[i+2]；<br />　　sum4 += a[i+3]；<br />}<br />sum = (sum4+sum3)+(sum1+sum2)； <br />　　要注意的是：使用4 路分解是因为这样使用了4阶段流水线浮点加法，浮点加法的每一个阶段占用一个时钟周期，保证了最大的资源利用率。 <br />13.提出公共子表达式 <br />　　在某些情况下，C++编译器不能从浮点表达式中提出公共的子表达式，因为这意味着相当于对表达式重新排序。需要特别指出的是，编译器在提取公共子表达式前不能按照代数的等价关系重新安排表达式。这时，程序员要手动地提出公共的子表达式（在VC.net里有一项“全局优化”选项可以完成此工作，但效果就不得而知了）。 <br />推荐的代码 <br />float a, b, c, d, e, f；<br />...<br />e = b * c / d；<br />f = b / d * a；<br />float a, b, c, d, e, f；<br />...<br />const float t(b / d)；<br />e = c * t；<br />f = a * t； <br />推荐的代码 <br />float a, b, c, e, f；<br />...<br />e = a / c；<br />f = b / c；<br />float a, b, c, e, f；<br />...<br />const float t(1.0f / c)；<br />e = a * t；<br />f = b * t； <br />14.结构体成员的布局 <br />　　很多编译器有“使结构体字，双字或四字对齐”的选项。但是，还是需要改善结构体成员的对齐，有些编译器可能分配给结构体成员空间的顺序与他们声明的不同。但是，有些编译器并不提供这些功能，或者效果不好。所以，要在付出最少代价的情况下实现最好的结构体和结构体成员对齐，建议采取这些方法： <br />　　A按类型长度排序 <br />　　把结构体的成员按照它们的类型长度排序，声明成员时把长的类型放在短的前面。 <br />　　把结构体填充成最长类型长度的整倍数 <br />　　把结构体填充成最长类型长度的整倍数。照这样，如果结构体的第一个成员对齐了，所有整个结构体自然也就对齐了。下面的例子演示了如何对结构体成员进行重新排序： <br />　　不好的代码，普通顺序 推荐的代码，新的顺序并手动填充了几个字节<br />struct<br />{<br />　　char a[5]；<br />　　long k；<br />　　double x；<br />} baz；<br />struct<br />{<br />　　double x；<br />　　long k；<br />　　char a[5]；<br />char pad[7]；<br />} baz； </p><p>　　这个规则同样适用于类的成员的布局。 <br />　　B按数据类型的长度排序本地变量 <br />　　当编译器分配给本地变量空间时，它们的顺序和它们在源代码中声明的顺序一样，和上一条规则一样，应该把长的变量放在短的变量前面。如果第一个变量对齐了，其它变量就会连续的存放，而且不用填充字节自然就会对齐。有些编译器在分配变量时不会自动改变变量顺序，有些编译器不能产生4字节对齐的栈，所以4字节可能不对齐。下面这个例子演示了本地变量声明的重新排序： <br />　　不好的代码，普通顺序 推荐的代码，改进的顺序 <br />short ga, gu, gi；<br />long foo, bar；<br />double x, y, z[3]；<br />char a, b；<br />float baz；<br />double z[3]；<br />double x, y；<br />long foo, bar；<br />float baz；<br />short ga, gu, gi； <br />14.避免不必要的整数除法 <br />　　整数除法是整数运算中最慢的，所以应该尽可能避免。一种可能减少整数除法的地方是连除，这里除法可以由乘法代替。这个替换的副作用是有可能在算乘积时会溢出，所以只能在一定范围的除法中使用。 <br />　　不好的代码 推荐的代码 <br />int i, j, k, m；<br />m = i / j / k；<br />int i, j, k, m；<br />m = i / (j * k)； <br />15.把频繁使用的指针型参数拷贝到本地变量 <br />　　避免在函数中频繁使用指针型参数指向的值。因为编译器不知道指针之间是否存在冲突，所以指针型参数往往不能被编译器优化。这样是数据不能被存放在寄存器中，而且明显地占用了内存带宽。注意，很多编译器有“假设不冲突”优化开关（在VC里必须手动添加编译器命令行/Oa或/Ow），这允许编译器假设两个不同的指针总是有不同的内容，这样就不用把指针型参数保存到本地变量。否则，请在函数一开始把指针指向的数据保存到本地变量。如果需要的话，在函数结束前拷贝回去。 　　<br />    不好的代码 <br />// 假设 q != r<br />void isqrt(unsigned long a, unsigned long* q, unsigned long* r)<br />{<br />　　*q = a；<br />　　if (a &gt;； 0)<br />　　{<br />　　　　while (*q &gt;； (*r = a / *q))<br />　　　　{<br />　　　　　　*q = (*q + *r) &gt;；&gt;； 1；<br />　　　　}<br />　　}<br />　　*r = a - *q * *q；<br />}<br />    推荐的代码<br />// 假设 q != r<br />void isqrt(unsigned long a, unsigned long* q, unsigned long* r)<br />{<br />　　unsigned long qq, rr；<br />　　qq = a；<br />　　if (a &gt;； 0)<br />　　{<br />　　　　while (qq &gt;； (rr = a / qq))<br />　　　　{<br />　　　　　　qq = (qq + rr) &gt;；&gt;； 1；<br />　　　　}<br />　　}<br />　　rr = a - qq * qq；<br />　　*q = qq；<br />　　*r = rr；<br />} <br />16.赋值与初始化<br />先看看以下代码： <br />class CInt<br />{<br />　　int m_i； <br />public:<br />　　CInt(int a = 0):m_i(a) { cout &lt;；&lt;； "；CInt"； &lt;；&lt;； endl； }<br />　　~CInt() { cout &lt;；&lt;； "；~CInt"； &lt;；&lt;； endl； } <br />　　CInt operator + (const CInt&amp;； a) { return CInt(m_i + a.GetInt())； } <br />　　void SetInt(const int i)　　{ m_i = i； }<br />　　int GetInt() const　　　　　　{ return m_i； }<br />}；<br />    不好的代码 <br />void main()<br />{<br />　　CInt a, b, c；<br />　　a.SetInt(1)；<br />　　b.SetInt(2)；<br />　　c = a + b；<br />}<br />    推荐的代码<br />void main()<br />{<br />　　CInt a(1), b(2)；<br />　　CInt c(a + b)；<br />} <br />　　这两段代码所作的事都一样，但那一个更好呢？看看输出结果就会发现，不好的代码输出了四个"；CInt"；和四个"；~CInt"；，而推荐的代码只输出三个。也就是说，第二个例子比第一个例子少生成一次临时对象。Why? 请注意，第一个中的c用的是先声明再赋值的方法，第二个用的是初始化的方法，它们有本质的区别。第一个例子的"；c = a + b"；先生成一个临时对象用来保存a + b的值，再把该临时对象用位拷贝的方法给c赋值，然后临时对象被销毁。这个临时对象就是那个多出来的对象。第二个例子直接用拷贝构造函数的方法对c初始化，不产生临时对象。所以，尽量在需要使用一个对象时才声明，并用初始化的方法赋初值。 <br />17.尽量使用成员初始化列表 <br />　　在初始化类的成员时，尽量使用成员初始化列表而不是传统的赋值方式。 <br />　　不好的代码 <br />class CMyClass<br />{<br />　　string strName； <br />public:<br />　　CMyClass(const string&amp;； str)；<br />}； <br />CMyClass::CMyClass(const string&amp;； str)<br />{<br />　　strName = str；<br />}<br />    推荐的代码<br />class CMyClass<br />{<br />　　string strName；<br />　　int i；<br />public:<br />　　CMyClass(const string&amp;； str)；<br />}； <br />CMyClass::CMyClass(const string&amp;；str)<br />   :strName(str)<br />{</p><p>} <br />　　不好的例子用的是赋值的方式。这样，strName会先被建立（调用了string的默认构造函数），再由参数str赋值。而推荐的例子用的是成员初始化列表，strName直接构造为str，少调用一次默认构造函数，还少了一些安全隐患。</p><img src ="http://www.cppblog.com/eday/aggbug/18844.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/eday/" target="_blank">松*</a> 2007-02-17 22:05 <a href="http://www.cppblog.com/eday/archive/2007/02/17/18844.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C代码优化</title><link>http://www.cppblog.com/eday/archive/2007/02/17/18843.html</link><dc:creator>松*</dc:creator><author>松*</author><pubDate>Sat, 17 Feb 2007 14:04:00 GMT</pubDate><guid>http://www.cppblog.com/eday/archive/2007/02/17/18843.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: C代码优化方案																																																																																																1、选择合适的算法和数据结构																																										...&nbsp;&nbsp;<a href='http://www.cppblog.com/eday/archive/2007/02/17/18843.html'>阅读全文</a><img src ="http://www.cppblog.com/eday/aggbug/18843.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/eday/" target="_blank">松*</a> 2007-02-17 22:04 <a href="http://www.cppblog.com/eday/archive/2007/02/17/18843.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++资源之不完全导引</title><link>http://www.cppblog.com/eday/archive/2007/02/05/18382.html</link><dc:creator>松*</dc:creator><author>松*</author><pubDate>Mon, 05 Feb 2007 02:07:00 GMT</pubDate><guid>http://www.cppblog.com/eday/archive/2007/02/05/18382.html</guid><description><![CDATA[
		<p>　　1，前言</p>
		<p>　　无数次听到“我要开始学习C++!”的呐喊，无数次听到“C++太复杂了，我真的学不会”的无奈。Stan Lippman先生曾在《C++ Primer》一书中指出“C++是最为难学的高级程序设计语言之一”，人们常将“之一”去掉以表达自己对C++的敬畏。诚然，C++程序设计语言对于学习者的确有很多难以逾越的鸿沟，体系结构的庞大，应接不暇并不断扩充的特性……除此之外，参考资料之多与冗杂使它的学习者望而却步，欲求深入者苦不堪言。希望这一份不完全导引能够成为您C++学习之路上的引路灯。</p>
		<p>　　撰写本文的初衷并不打算带领大家体验古老的C++历史，如果你想了解C++的历史与其前期发展中诸多技术的演变，你应当去参考Bjarne的《The Design and Evolution of C++》。当然也不打算给大家一个无所不包的宝典（并非不想：其一是因水平有限，其二无奈C++之博大精深），所给出的仅仅是一些我们认为对于想学习C++的广大读者来说最重要并且触手可及的开发与学习资源。</p>
		<p>　　本文介绍并分析了一些编译器，开发环境，库，少量的书籍以及参考网站，并且尽可能尝试着给出一个利用这些资源的导引，望对如同我们一样的初学者能够有所裨益。</p>
		<p>    　2，编译器</p>
		<p>　　在C++之外的任何语言中，编译器都从来没有受到过如此之重视。因为C++是一门相当复杂的语言，所以编译器也难于构建。直到最近我们才开始能够使用上完全符合C++标准的编译器（哦，你可能会责怪那些编译器厂商不能尽早的提供符合标准的编译器，这只能怪他们各自维系着自身的一套别人不愿接受的标准）。什么？你说这无关紧要？哦，不，你所需要的是和标准化C++高度兼容的编译环境。长远来看<br />，只有这样的编译器对C++开发人员来说才是最有意义的工具，尤其是对于程序设计语言的学习者。一至性让代码具备可移植性，并让一门语言及其库的应用更为广泛。嗯，是的，我们这里只打算介绍一些公认的优秀编译器。</p>
		<p>　　2.1 Borland C++</p>
		<p>　　这个是Borland C++ Builder和Borland C++ Builder X这两种开发环境的后台编译器。（哦，我之所以将之分为两种开发环境你应当能明白为什么，正如Delphi7到Delphi8的转变，是革命性的两代。）Borland C++由老牌开发工具厂商Borland倾力打造。该公司的编译器素以速度快，空间效率高著称，Borland C++ 系列编译器秉承了这个传统，属于非常优质的编译器。标准化方面早在5.5版本的编译器中对标准化C++的兼容就达到了92.73%。目前最新版本是Borland C++ Builder X中的6.0版本，官方称100%符合ANSI/ISO的C++标准以及C99标准。嗯…这正是我前面所指的“完全符合C++标准的编译器”。</p>
		<p>　　2.2 Visual C++</p>
		<p>　　这个正是我们熟知的Visual Studio 和 Visual Studio.net 2002, 2003以及2005 Whidbey中带的C++编译器。由Microsoft公司研制。在Visual Studio 6.0中，因为编译器有太多地方不能与后来出现的C++标准相吻合而饱受批评（想想你在使用STL的时候编译时报出的那些令人厌恶的error和warning吧）。VC++6.0对标准化C+<br />+的兼容只有83.43%。但是随着C++编译器设计大师Stanley Lippman以及诸多C++社群达人的加盟，在Visual Studio.NET 2003中，Visual C++编译器已经成为一个非常成熟可*的C++编译器了。Dr.Dobb's Journal的评测显示Visual C++7.1对标准C++的兼容性高达98.22%，一度成为CBX之前兼容性最好的编译器。结合强大的Visual Studio.NET开发环境，是一个非常不错的选择。至于Whidbey时代的Visual C++,似乎微软所最关注的是C++/CLI……我们不想评论微软下一代的C++编译器对标准化兼容如何，但他确实越来越适合.NET (其实你和我的感觉可能是一样的，微软不应当把标准C++这块肥肉丢给Borland,然而微软可能并不这样认为)。</p>
		<p>　　2.3 GNU C++</p>
		<p>　　著名的开源C++编译器。是类Unix操作系统下编写C++程序的首选。特点是有非常好的移植性，你可以在非常广泛的平台上使用它，同时也是编写跨平台，嵌入式程序很好的选择。另外在符合标准这个方面一直都非常好，GCC3.3大概能够达到96.15%。但是由于其跨平台的特性，在代码尺寸速度等优化上略微差一点。</p>
		<p>　　基于GNU C++的编译器有很多，比如：</p>
		<p>　　(1) Mingw</p>
		<p>　　<a href="http://www.mingw.org/">http://www.mingw.org/</a></p>
		<p>　　GCC的一个Windows的移植版本（Dev-C++的后台）</p>
		<p>　　(2) Cygwin</p>
		<p>　　<a href="http://sources.redhat.com/cygwin/">http://sources.redhat.com/cygwin/</a></p>
		<p>　　GCC的另外一个Windows移植版本是Cygwin的一部分，Cygwin是Windows下的一个Unix仿真环境。严格的说是模拟GNU的环境，这也就是"Gnu's Not Unix"要表达的意思，噢，扯远了，这并不是我们在这里关心的实质内容。</p>
		<p>　　(3) Djgpp</p>
		<p>　　<a href="http://www.delorie.com/djgpp/">http://www.delorie.com/djgpp/</a></p>
		<p>　　这是GCC的DOS移植版本。</p>
		<p>　　(4) RSXNT</p>
		<p>　　<a href="http://www.mathematik.uni-bielefeld.de/~rainer/">http://www.mathematik.uni-bielefeld.de/~rainer/</a></p>
		<p>　　这是GCC的DOS和Windows移植版本。</p>
		<p>　　(5) Intel C++</p>
		<p>　　著名CPU制造厂商Intel出品的编译器，Special Design for Intel x86！对于Intel x86结构的CPU经过特别的优化。在有些应用情况下，特别是数值计算等高性能应用，仅仅采用Intel的编译器编译就能大幅度的提高性能。</p>
		<p>　　(6) Digital Mars C++</p>
		<p>　　网络上提供免费下载，Zortech/Symantec C++的继承者，其前身在当年惨烈的C++四国战中也是主角之一。</p>
		<p>　　3，开发环境</p>
		<p>　　开发环境对于程序员的作用不言而喻。选择自己朝夕相处的环境也不是容易的事情，特别是在IDE如此丰富的情况下。下面就是我们推荐的一些常见的C++开发环境，并没有包括一些小型的，罕见的IDE。其中任何一款都是功能丰富，可以用作日常开发使用的。对于不同层面的开发者，请参见内文关于适用对象的描述。</p>
		<p>　　3.1 Visual Studio 6.0</p>
		<p>　　这个虽然是Microsoft公司的老版本的开发环境，但是鉴于其后继版本VisualStudio.NET的庞大身躯，以及初学者并不那么高的功能要求，所以推荐这个开发环境给C++的初学者，供其学习C++的最基本的部分，比如C的那部分子集，当然你别指望他能够支持最新的C99标准。在日常的开发中，仍然有很多公司使用这个经典稳定的环境，比如笔者就看曾亲见有些公司将其编译器替换为GCC做手机开发之用。</p>
		<p>　　3.2 Visual Studio.NET 2003</p>
		<p>　　作为Microsoft公司官方正式发布的最新版本开发环境，其中有太多激动人心的功能。结合其最新的C++编译器。对于机器配置比较好的开发人员来说，使用这个开发环境将能满足其大部分的要求。这里不打算单独说Visual Studio Whidbey,虽然Visual Studio .NET 2005 - Whidbey社区预览版已经推出，但暂不是很稳定，读者可以亲身去体验。</p>
		<p>　　3.3 Borland C++ Builder 6</p>
		<p>　　这个并不是Borland的C++开发环境的最新版本。选择它的原因是它不是用Java写的IDE，速度比较快。它有一个很完善的GUI窗体设计器，和Delphi共用一个VCL。由于这些特点，比较适合初学者上手。但是由于其GUI的中心位置，可能不利于对于C++语言的学习。而且其为了支持VCL这个Object Pascal写的库也对C++进行了一些私有的扩充。使得人们有一个不得不接受的事实：“Borland C++ Builder 6的高手<br />几乎都是Delphi高手”。</p>
		<p>　　3.4 Borland C++ Builder X</p>
		<p>　　正如前文所述，虽然版本号上和前面那个IDE非常相象，但是其实它们是完全不同的两个集成开发环境。C++Builder更多的是一个和Delphi同步的C++版本的开发环境，C++BuilderX则是完全从C++的角度思考得出的一个功能丰富的IDE。其最大的特点是跨平台，跨编译器，多种Framework的集成，并且有一个WxWindows为基础的GUI设计器。尤其是采用了纯C++来重写了整个Framework,摒弃了以前令人无奈的版本。对于C++的开发来说，从编译器，到库，到功能集成都是非常理想的。可以预见，Borland C++ Builder X 2.0很值得C++爱好者期待。唯一令人难堪之处是作为一个C++的开发工具，其IDE是用Java写的，在配置不够理想的机器上请慎重考虑再安装。</p>
		<p>　　3.5 Emacs + GCC</p>
		<p>　　前面讲的大部分是Windows环境下的集成开发环境。Linux上的开发者更倾向于使用Emacs来编辑C++的文件，用Makefile来命令GCC做编译。虽然看上去比较松散，但是这些东西综合起来还是一个开0发环境。如果你能够娴熟的使用这样的环境写程序，你的水平应该足够指导我们来写这篇陋文了。</p>
		<p>　　3.6 Dev C++</p>
		<p>　　GCC是一个很好的编译器。在Windows上的C++编译器一直和标准有着一段距离的时候，GCC就是一个让Windows下开发者流口水的编译器。Dev-C++就是能够让GCC跑在Windows下的工具，作为集成开发环境，还提供了同专业IDE相媲美的语法高亮，代码提示，调试等功能。由于使用Delphi开发，占用内存少，速度很快，比较适合轻量级的学习和使用。</p>
		<p>　　3.7 Eclipse + CDT</p>
		<p>　　Eclipse可是近来大名鼎鼎的开发工具。最新一期的Jolt大奖就颁给了这个杰出的神物。说其神奇是因为，它本身是用Java写的，但是拥有比一般Java写的程序快得多的速度。而且因为其基于插件组装一切的原则，使得能够有CDT这样的插件把Eclipse变成一个C/C++的开发环境。如果你一直用Eclipse写Java的程序，不妨用它体验一下C++开发的乐趣。</p>
		<p>--------------------------------------------------------------------------------</p>
		<p>　　4，工具</p>
		<p>　　C++的辅助工具繁多，我们分门别类的为大家作介绍：</p>
		<p>　　4.1 文档类</p>
		<p>　　(1) Doxygen</p>
		<p>　　参考站点：<a href="http://www.doxygen.org/">http://www.doxygen.org/</a></p>
		<p>　　Doxygen是一种适合C风格语言（如C++、C、IDL、Java甚至包括C#和PHP）的、开放源码的、基于命令行的文档产生器。</p>
		<p>　　(2) C++2HTML</p>
		<p>　　参考站点：<a href="http://www.bedaux.net/cpp2html/">http://www.bedaux.net/cpp2html/</a></p>
		<p>　　把C++代码变成语法高亮的HTML</p>
		<p>　　(3) CodeColorizer</p>
		<p>　　参考站点：<a href="http://www.chami.com/colorizer/">http://www.chami.com/colorizer/</a></p>
		<p>　　它能把好几种语言的源代码着色为HTML</p>
		<p>　　(4) Doc-O-Matic</p>
		<p>　　参考站点：<a href="http://www.doc-o-matic.com/">http://www.doc-o-matic.com/</a></p>
		<p>　　Doc-O_Matic为你的C/C++，C++.net，Delphi/Pascal, VB.NET，C#和Java程序或者组件产生准确的文档。Doc-O-Matic使用源代码中的符号和注释以及外部的文档文件创建与流行的文档样式一致的文档。</p>
		<p>　　(5) DocVizor</p>
		<p>　　参考站点：<a href="http://www.ucancode.net/Products/DocBuilder/Features.htm">http://www.ucancode.net/Products/DocBuilder/Features.htm</a></p>
		<p>　　DocVizor满足了面向对象软件开发者的基本要求——它让我们能够看到C++工程中的类层次结构。DocVizor快速地产生完整可供打印的类层次结构图，包括从第三方库中来的那些类，除此之外DocVizor还能从类信息中产生HTML文件。</p>
		<p>　　(6) SourcePublisher C++</p>
		<p>　　参考站点：<a href="http://www.scitools.com/sourcepublisher_c.html">http://www.scitools.com/sourcepublisher_c.html</a></p>
		<p>　　给源代码产生提供快速直观的HTML报表，包括代码，类层次结构，调用和被调用树，包含和被包含树。支持多种操作系统。</p>
		<p>　　(7) Understand</p>
		<p>　　参考站点：<a href="http://www.scitools.com/ucpp.html">http://www.scitools.com/ucpp.html</a></p>
		<p>　　分析任何规模的C或者C++工程，帮助我们更好的理解以及编写文档。</p>
		<p>　　4.2 代码类</p>
		<p>　　(1) CC-Rider</p>
		<p>　　参考站点：<a href="http://www.cc-rider.com/">http://www.cc-rider.com/</a></p>
		<p>　　CC-Rider是用于C/C++程序强大的代码可视化工具，通过交互式浏览、编辑及自动文件来促进程序的维持和发展。</p>
		<p>　　(2) CodeInspect</p>
		<p>　　参考站点：<a href="http://www.yokasoft.com/">http://www.yokasoft.com/</a></p>
		<p>　　一种新的C/C++代码分析工具。它检查我们的源代码找出非标准的，可能的，以及普通的错误代码。</p>
		<p>　　(3) CodeWizard</p>
		<p>　　参考站点：<a href="http://www.parasoft.com/">http://www.parasoft.com/</a></p>
		<p>　　先进的C/C++源代码分析工具，使用超过500个编码规范自动化地标明危险的，但是编译器不能检查到的代码结构。</p>
		<p>　　(4) C++ Validation Test Suites</p>
		<p>　　参考站点：<a href="http://www.plumhall.com/suites.html">http://www.plumhall.com/suites.html</a></p>
		<p>　　一组用于测试编译器和库对于标准吻合程度的代码库。</p>
		<p>　　(5) CppRefactory</p>
		<p>　　参考站点：<a href="http://cpptool.sourceforge.net/">http://cpptool.sourceforge.net/</a></p>
		<p>　　CPPRefactory是一个使得开发者能够重构他们的C++代码的程序。目的是使得C++代码的重构能够尽可能的有效率和简单。</p>
		<p>　　(6) Lzz</p>
		<p>　　参考站点：<a href="http://www.lazycplusplus.com/">http://www.lazycplusplus.com/</a></p>
		<p>　　Lzz是一个自动化许多C++编程中的体力活的工具。它能够节省我们许多事件并且使得编码更加有乐趣。给出一系列的声明，Lzz会给我们创建头文件和源文件。</p>
		<p>　　(7) QA C++ Generation 2000</p>
		<p>　　参考站点：<a href="http://www.programmingresearch.com/solutions/qacpp.htm">http://www.programmingresearch.com/solutions/qacpp.htm</a></p>
		<p>　　它关注面向对象的C++源代码，对有关于设计，效率，可*性，可维护性的部分提出警告信息。</p>
		<p>　　(8) s-mail project - Java to C++DOL</p>
		<p>　　参考站点：<a href="http://sadlocha.strefa.pl/s-mail/ja2dol.html">http://sadlocha.strefa.pl/s-mail/ja2dol.html</a></p>
		<p>　　把Java源代码翻译为相应的C++源代码的命令行工具。</p>
		<p>　　(9) SNIP from Cleanscape Software International</p>
		<p>　　参考站点：<a href="http://www.cleanscape.net/stdprod/snip/index.html">http://www.cleanscape.net/stdprod/snip/index.html</a></p>
		<p>　　一个填平编码和设计之间沟壑的易于使用的C++开发工具，节省大量编辑和调试的事件，它还使得开发者能够指定设计模式作为对象模型，自动从对象模型中产生C++的类。</p>
		<p>　　(10) SourceStyler C++</p>
		<p>　　参考站点：<a href="http://www.ochresoftware.com/">http://www.ochresoftware.com/</a></p>
		<p>　　对C/C++源代码提供完整的格式化和排版控制的工具。提供多于75个的格式化选项以及完全支持ANSI C++。</p>
		<p>　　4.3 编译类</p>
		<p>　　(1) Compilercache</p>
		<p>　　参考站点：<a href="http://www.erikyyy.de/compilercache/">http://www.erikyyy.de/compilercache/</a></p>
		<p>　　Compilercache是一个对你的C和C++编译器的封装脚本。每次我们进行编译，封装脚本，把编译的结果放入缓存，一旦编译相同的东西，结果将从缓存中取出而不是再次编译。</p>
		<p>　　(2) Ccache</p>
		<p>　　参考站点：<a href="http://ccache.samba.org/">http://ccache.samba.org/</a></p>
		<p>　　Ccache是一个编译器缓存。它使用起来就像C/C++编译器的缓存预处理器，编译速度通常能提高普通编译过程的5~10倍。</p>
		<p>　　(3) Cmm (C++ with MultiMethods)</p>
		<p>　　参考站点：<a href="http://www.op59.net/cmm/cmm-0.28/users.html">http://www.op59.net/cmm/cmm-0.28/users.html</a></p>
		<p>　　这是一种C++语言的扩展。读入Cmm源代码输出C++的源代码，功能是对C++语言添加了对multimethod的支持。</p>
		<p>　　(4) The Frost Project</p>
		<p>　　参考站点：<a href="http://frost.flewid.de/">http://frost.flewid.de/</a></p>
		<p>　　Forst使得你能够在C++程序中像原生的C++特性一样使用multimethod以及虚函数参数。它是一个编译器的外壳。</p>
		<p>　　4.4 测试和调试类</p>
		<p>　　(1) CPPUnit</p>
		<p>　　CppUnit 是个基于 LGPL 的开源项目，最初版本移植自 JUnit，是一个非常优秀的开源测试框架。CppUnit 和 JUnit 一样主要思想来源于极限编程。主要功能就是对单元测试进行管理，并可进行自动化测试。<br /><br /></p>
		<p>　　(2) C++Test</p>
		<p>　　参考站点：<a href="http://www.parasoft.com/">http://www.parasoft.com/</a></p>
		<p>　　C++ Test是一个单元测试工具，它自动化了C和C++类，函数或者组件的测试。</p>
		<p>
				<br />　　(3) Cantata++</p>
		<p>　　参考站点：<a href="http://www.iplbath.com/products/tools/pt400.shtml">http://www.iplbath.com/products/tools/pt400.shtml</a></p>
		<p>　　设计的目的是为了满足在合理的经济开销下使用这个工具可以让开发工程师开展单元测试和集成测试的需求.</p>
		<p>　　(4) Purify</p>
		<p>　　参考站点：<a href="http://www-900.ibm.com/cn/software/rational/products/purif">http://www-900.ibm.com/cn/software/rational/products/purif</a><br />yplus/index.shtml</p>
		<p>　　IBM Rational PurifyPlus是一套完整的运行时分析工具，旨在提高应用程序的可*性和性能。PurifyPlus将内存错误和泄漏检测、应用程序性能描述、代码覆盖分析等功能组合在一个单一、完整的工具包中。</p>
		<p>　　(5) BoundsChecker</p>
		<p>　　BoundsChecker是一个C++运行时错误检测和调试工具。它通过在Visual Studio内自动化调试过程加速开发并且缩短上市的周期。BoundsChecker提供清楚，详细的程序错误分析，许多是对C++独有的并且在static，stack和heap内存中检测和诊断错误，以及发现内存和资源的泄漏。　　<br /><br />　　(6) Insure++</p>
		<p>　　参考站点：<a href="http://www.parasoft.com/">http://www.parasoft.com/</a></p>
		<p>　　一个自动化的运行时程序测试工具，检查难以察觉的错误,如内存覆盖，内存泄漏，内存分配错误，变量初始化错误，变量定义冲突，指针错误，库错误，逻辑错误和算法错误等。</p>
		<p>　　(7) GlowCode</p>
		<p>　　参考站点：<a href="http://www.glowcode.com/">http://www.glowcode.com/</a></p>
		<p>　　GlowCode包括内存泄漏检查，code profiler，函数调用跟踪等功能。给C++开发者提供完整的错误诊断，和运行时性能分析工具包。</p>
		<p>　　(8) Stack Spy</p>
		<p>　　参考站点：<a href="http://www.imperioustech.com/">http://www.imperioustech.com/</a></p>
		<p>　　它能捕捉stack corruption, stack over run, stack overflow等有关栈的错误。</p>
		<p>------------------------------------------------------------------------<br />　5，库</p>
		<p>　　在C++中，库的地位是非常高的。C++之父 Bjarne Stroustrup先生多次表示了设计库来扩充功能要好过设计更多的语法的言论。现实中，C++的库门类繁多，解决的问题也是极其广泛，库从轻量级到重量级的都有。不少都是让人眼界大开，亦或是望而生叹的思维杰作。由于库的数量非常庞大，而且限于笔者水平，其中很多并不了解。所以文中所提的一些库都是比较著名的大型库。</p>
		<p>　　5.1 标准库</p>
		<p>　　标准库中提供了C++程序的基本设施。虽然C++标准库随着C++标准折腾了许多年，直到标准的出台才正式定型，但是在标准库的实现上却很令人欣慰得看到多种实现，并且已被实践证明为有工业级别强度的佳作。</p>
		<p>　　(1) Dinkumware C++ Library</p>
		<p>　　参考站点：<a href="http://www.dinkumware.com/">http://www.dinkumware.com/</a></p>
		<p>　　P.J. Plauger编写的高品质的标准库。P.J. Plauger博士是Dr. Dobb's程序设计杰出奖的获得者。其编写的库长期被Microsoft采用，并且最近Borland也取得了其OEM的license，在其C/C++的产品中采用Dinkumware的库。</p>
		<p>　　(2) RogueWave Standard C++ Library</p>
		<p>　　参考站点：<a href="http://www.roguewave.com/">http://www.roguewave.com/</a></p>
		<p>　　这个库在Borland C++ Builder的早期版本中曾经被采用，后来被其他的库给替换了。笔者不推荐使用。</p>
		<p>　　(3) SGI STL</p>
		<p>　　参考站点：<a href="http://www.roguewave.com/">http://www.roguewave.com/</a></p>
		<p>　　SGI公司的C++标准模版库。</p>
		<p>　　(4) STLport</p>
		<p>　　参考站点：<a href="http://www.stlport.org/">http://www.stlport.org/</a></p>
		<p>　　SGI STL库的跨平台可移植版本。</p>
		<p>　　5.2 “准”标准库 - Boost</p>
		<p>　　参考站点：<a href="http://www.boost.org/">http://www.boost.org/</a></p>
		<p>　　国内镜像：<a href="http://www.c-view.org/tech/lib/boost/index.htm">http://www.c-view.org/tech/lib/boost/index.htm</a></p>
		<p>　　Boost库是一个经过千锤百炼、可移植、提供源代码的C++库，作为标准库的后备，是C++标准化进程的发动机之一。 Boost库由C++标准委员会库工作组成员发起，在C++社区中影响甚大，其成员已近2000人。 Boost库为我们带来了最新、最酷、最实用的技术，是不折不扣的“准”标准库。</p>
		<p>　　Boost中比较有名气的有这么几个库：</p>
		<p>　　Regex</p>
		<p>　　正则表达式库</p>
		<p>　　Spirit</p>
		<p>　　LL parser framework，用C++代码直接表达EBNF</p>
		<p>　　Graph</p>
		<p>　　图组件和算法</p>
		<p>　　Lambda</p>
		<p>　　在调用的地方定义短小匿名的函数对象，很实用的functional功能</p>
		<p>　　concept check</p>
		<p>　　检查泛型编程中的concept</p>
		<p> </p>
		<p>　　Mpl</p>
		<p>　　用模板实现的元编程框架</p>
		<p> </p>
		<p>　　Thread</p>
		<p>　　可移植的C++多线程库</p>
		<p> </p>
		<p>　　Python</p>
		<p>　　把C++类和函数映射到Python之中</p>
		<p>　　Pool</p>
		<p>　　内存池管理</p>
		<p> </p>
		<p>　　smart_ptr</p>
		<p>　　5个智能指针，学习智能指针必读，一份不错的参考是来自CUJ的文章：</p>
		<p>　　Smart Pointers in Boost，哦，这篇文章可以查到，CUJ是提供在线浏览的。中文版见笔者在《Dr. Dobb's Journal软件研发杂志》第7辑上的译文。</p>
		<p>　　Boost总体来说是实用价值很高，质量很高的库。并且由于其对跨平台的强调，对标准C++的强调，是编写平台无关，现代C++的开发者必备的工具。但是Boost中也有很多是实验性质的东西，在实际的开发中实用需要谨慎。并且很多Boost中的库功能堪称对语言功能的扩展，其构造用尽精巧的手法，不要贸然的花费时间研读。Boost另外一面，比如Graph这样的库则是具有工业强度，结构良好，非常值得研读的精品代码，并且也可以放心的在产品代码中多多利用。</p>
		<p>　　5.3 GUI</p>
		<p>　　在众多C++的库中，GUI部分的库算是比较繁荣，也比较引人注目的。在实际开发中，GUI库的选择也是非常重要的一件事情，下面我们综述一下可选择的GUI库，各自的特点以及相关工具的支持。</p>
		<p>　　(1) MFC</p>
		<p>　　大名鼎鼎的微软基础类库（Microsoft Foundation Class）。大凡学过VC++的人都应该知道这个库。虽然从技术角度讲，MFC是不大漂亮的，但是它构建于Windows API 之上，能够使程序员的工作更容易,编程效率高，减少了大量在建立 Windows 程序时必须编写的代码，同时它还提供了所有一般 C++ 编程的优点，例如继承和封装。MFC 编写的程序在各个版本的Windows操作系统上是可移植的，例如，在Windows 3.1下编写的代码可以很容易地移植到 Windows NT 或 Windows 95 上。但是在最近发展以及官方支持上日渐势微。</p>
		<p>　　(2) QT</p>
		<p>　　参考网站：<a href="http://www.trolltech.com/">http://www.trolltech.com/</a></p>
		<p>　　Qt是Trolltech公司的一个多平台的C++图形用户界面应用程序框架。它提供给应用程序开发者建立艺术级的图形用户界面所需的所用功能。Qt是完全面向对象的很容易扩展，并且允许真正地组件编程。自从1996年早些时候，Qt进入商业领域，它已经成为全世界范围内数千种成功的应用程序的基础。Qt也是流行的Linux桌面环境KDE 的基础，同时它还支持Windows、Macintosh、Unix/X11等多种平台。</p>
		<p>　　(3) WxWindows</p>
		<p>　　参考网站：<a href="http://www.wxwindows.org/">http://www.wxwindows.org/</a></p>
		<p>　　跨平台的GUI库。因为其类层次极像MFC，所以有文章介绍从MFC到WxWindows的代码移植以实现跨平台的功能。通过多年的开发也是一个日趋完善的GUI库，支持同样不弱于前面两个库。并且是完全开放源代码的。新近的C++ Builder X的GUI设计器就是基于这个库的。</p>
		<p>　　(4) Fox</p>
		<p>　　参考网站：<a href="http://www.fox-toolkit.org/">http://www.fox-toolkit.org/</a></p>
		<p>　　开放源代码的GUI库。作者从自己亲身的开发经验中得出了一个理想的GUI库应该是什么样子的感受出发，从而开始了对这个库的开发。有兴趣的可以尝试一下。</p>
		<p>
				<br />　　(5) WTL</p>
		<p>　　基于ATL的一个库。因为使用了大量ATL的轻量级手法，模板等技术，在代码尺寸，以及速度优化方面做得非常到位。主要面向的使用群体是开发COM轻量级供网络下载的可视化控件的开发者。</p>
		<p>　　(6) GTK</p>
		<p>　　参考网站：<a href="http://gtkmm.sourceforge.net/">http://gtkmm.sourceforge.net/</a></p>
		<p>　　GTK是一个大名鼎鼎的C的开源GUI库。在Linux世界中有Gnome这样的杀手应用。而GTK就是这个库的C++封装版本。</p>
		<p>　　5.4 网络通信</p>
		<p>　　(1) ACE</p>
		<p>　　参考网站：<a href="http://www.cs.wustl.edu/~schmidt/ACE.html">http://www.cs.wustl.edu/~schmidt/ACE.html</a></p>
		<p>　　C++库的代表，超重量级的网络通信开发框架。ACE自适配通信环境（AdaptiveCommunication Environment）是可以自由使用、开放源代码的面向对象框架，在其中实现了许多用于并发通信软件的核心模式。ACE提供了一组丰富的可复用C++包装外观（Wrapper Facade）和框架组件，可跨越多种平台完成通用的通信软件任务，其中包括：事件多路分离和事件处理器分派、信号处理、服务初始化、进程间通<br />信、共享内存管理、消息路由、分布式服务动态（重）配置、并发执行和同步，等等。</p>
		<p>　　(2) StreamModule</p>
		<p>　　参考网站：<a href="http://www.omnifarious.org/StrMod/">http://www.omnifarious.org/StrMod/</a></p>
		<p>　　设计用于简化编写分布式程序的库。尝试着使得编写处理异步行为的程序更容易，而不是用同步的外壳包起异步的本质。</p>
		<p>　　(3) SimpleSocket</p>
		<p>　　参考网站：<a href="http://home.hetnet.nl/~lcbokkers/simsock.htm">http://home.hetnet.nl/~lcbokkers/simsock.htm</a></p>
		<p>　　这个类库让编写基于socket的客户/服务器程序更加容易。</p>
		<p>　　(4) A Stream Socket API for C++</p>
		<p>　　参考网站：<a href="http://www.pcs.cnu.edu/~dgame/sockets/socketsC++/sockets.h">http://www.pcs.cnu.edu/~dgame/sockets/socketsC++/sockets.h</a><br />tml</p>
		<p>　　又一个对Socket的封装库。</p>
		<p>　　5.5 XML</p>
		<p>　　(1) Xerces</p>
		<p>　　参考网站：<a href="http://xml.apache.org/xerces-c/">http://xml.apache.org/xerces-c/</a></p>
		<p>　　Xerces-C++ 是一个非常健壮的XML解析器，它提供了验证，以及SAX和DOM API。XML验证在文档类型定义(Document Type Definition，DTD)方面有很好的支持，并且在2001年12月增加了支持W3C XML Schema 的基本完整的开放标准。</p>
		<p>　　(2) XMLBooster</p>
		<p>　　参考网站：<a href="http://www.xmlbooster.com/">http://www.xmlbooster.com/</a></p>
		<p>　　这个库通过产生特制的parser的办法极大的提高了XML解析的速度，并且能够产生相应的GUI程序来修改这个parser。在DOM和SAX两大主流XML解析办法之外提供了另外一个可行的解决方案。</p>
		<p>　　(3) Pull Parser</p>
		<p>　　参考网站：<a href="http://www.extreme.indiana.edu/xgws/xsoap/xpp/">http://www.extreme.indiana.edu/xgws/xsoap/xpp/</a></p>
		<p>　　这个库采用pull方法的parser。在每个SAX的parser底层都有一个pull的parser，这个xpp把这层暴露出来直接给大家使用。在要充分考虑速度的时候值得尝试。<br /><br />　　(4) Xalan</p>
		<p>　　参考网站：<a href="http://xml.apache.org/xalan-c/">http://xml.apache.org/xalan-c/</a></p>
		<p>　　Xalan是一个用于把XML文档转换为HTML，纯文本或者其他XML类型文档的XSLT处理器。</p>
		<p>　　(5) CMarkup</p>
		<p>　　参考网站：<a href="http://www.firstobject.com/xml.htm">http://www.firstobject.com/xml.htm</a></p>
		<p>　　这是一种使用EDOM的XML解析器。在很多思路上面非常灵活实用。值得大家在DOM和SAX之外寻求一点灵感。</p>
		<p>　　(6) libxml++</p>
		<p>　　<a href="http://libxmlplusplus.sourceforge.net/">http://libxmlplusplus.sourceforge.net/</a></p>
		<p>　　libxml++是对著名的libxml XML解析器的C++封装版本</p>
		<p>　　5.6 科学计算</p>
		<p>　　(1) Blitz++</p>
		<p>　　参考网站：<a href="http://www.oonumerics.org/blitz/">http://www.oonumerics.org/blitz/</a></p>
		<p>　　Blitz++ 是一个高效率的数值计算函数库，它的设计目的是希望建立一套既具像C++ 一样方便，同时又比Fortran速度更快的数值计算环境。通常，用C++所写出的数值程序，比 Fortran慢20%左右，因此Blitz++正是要改掉这个缺点。方法是利用C++的template技术，程序执行甚至可以比Fortran更快。Blitz++目前仍在发展中，对于常见的SVD，FFTs，QMRES等常见的线性代数方法并不提供，不过使用者可以很容易地利用Blitz++所提供的函数来构建。</p>
		<p>　　(2) POOMA</p>
		<p>　　参考网站：<a href="http://www.codesourcery.com/pooma/pooma">http://www.codesourcery.com/pooma/pooma</a></p>
		<p>　　POOMA是一个免费的高性能的C++库，用于处理并行式科学计算。POOMA的面向对象设计方便了快速的程序开发，对并行机器进行了优化以达到最高的效率，方便在工业和研究环境中使用。</p>
		<p>　　(3) MTL</p>
		<p>　　参考网站：<a href="http://www.osl.iu.edu/research/mtl/">http://www.osl.iu.edu/research/mtl/</a></p>
		<p>　　Matrix Template Library(MTL)是一个高性能的泛型组件库，提供了各种格式矩阵的大量线性代数方面的功能。在某些应用使用高性能编译器的情况下，比如Intel的编译器，从产生的汇编代码可以看出其与手写几乎没有两样的效能。</p>
		<p>　　(4) CGAL</p>
		<p>　　参考网站：<a href="http://www.cgal.org/">http://www.cgal.org/</a></p>
		<p>　　Computational Geometry Algorithms Library的目的是把在计算几何方面的大部分重要的解决方案和方法以C++库的形式提供给工业和学术界的用户。</p>
		<p>　　5.7 游戏开发</p>
		<p>　　(1) Audio/Video 3D C++ Programming Library</p>
		<p>　　参考网站：<a href="http://www.galacticasoftware.com/products/av/">http://www.galacticasoftware.com/products/av/</a></p>
		<p>　　AV3D是一个跨平台，高性能的C++库。主要的特性是提供3D图形，声效支持（SB,以及S3M），控制接口（键盘，鼠标和遥感），XMS。</p>
		<p>　　(2) KlayGE</p>
		<p>　　参考网站：<a href="http://home.g365.net/enginedev/">http://home.g365.net/enginedev/</a></p>
		<p>　　国内游戏开发高手自己用C++开发的游戏引擎。KlayGE是一个开放源代码、跨平台的游戏引擎，并使用Python作脚本语言。KlayGE在LGPL协议下发行。感谢龚敏敏先生为中国游戏开发事业所做出的贡献。</p>
		<p>　　(3) OGRE</p>
		<p>　　参考网站：<a href="http://www.ogre3d.org/">http://www.ogre3d.org/</a></p>
		<p>　　OGRE（面向对象的图形渲染引擎）是用C++开发的，使用灵活的面向对象3D引擎。它的目的是让开发者能更方便和直接地开发基于3D硬件设备的应用程序或游戏。引擎中的类库对更底层的系统库（如：Direct3D和OpenGL）的全部使用细节进行了抽象，并提供了基于现实世界对象的接口和其它类。</p>
		<p>　　5.8 线程</p>
		<p>　　(1) C++ Threads</p>
		<p>　　参考网站：<a href="http://threads.sourceforge.net/">http://threads.sourceforge.net/</a></p>
		<p>　　这个库的目标是给程序员提供易于使用的类，这些类被继承以提供在Linux环境中很难看到的大量的线程方面的功能。</p>
		<p>　　(2) ZThreads</p>
		<p>　　参考网站：<a href="http://zthread.sourceforge.net/">http://zthread.sourceforge.net/</a></p>
		<p>　　一个先进的面向对象，跨平台的C++线程和同步库。<br /><br /></p>
		<p>　　5.9 序列化</p>
		<p>　　(1) s11n</p>
		<p>　　参考网站：<a href="http://s11n.net/">http://s11n.net/</a></p>
		<p>　　一个基于STL的C++库，用于序列化POD，STL容器以及用户定义的类型。</p>
		<p>　　(2) Simple XML Persistence Library</p>
		<p>　　参考网站：<a href="http://sxp.sourceforge.net/">http://sxp.sourceforge.net/</a></p>
		<p>　　这是一个把对象序列化为XML的轻量级的C++库。</p>
		<p>　　5.10 字符串</p>
		<p>　　(1) C++ Str Library</p>
		<p>　　参考网站：<a href="http://www.utilitycode.com/str/">http://www.utilitycode.com/str/</a></p>
		<p>　　操作字符串和字符的库，支持Windows和支持gcc的多种平台。提供高度优化的代码，并且支持多线程环境和Unicode，同时还有正则表达式的支持。</p>
		<p>　　(2) Common Text Transformation Library</p>
		<p>　　参考网站：<a href="http://cttl.sourceforge.net/">http://cttl.sourceforge.net/</a></p>
		<p>　　这是一个解析和修改STL字符串的库。CTTL substring类可以用来比较，插入，替换以及用EBNF的语法进行解析。</p>
		<p>　　(3) GRETA</p>
		<p>　　参考网站：<a href="http://research.microsoft.com/projects/greta/">http://research.microsoft.com/projects/greta/</a></p>
		<p>　　这是由微软研究院的研究人员开发的处理正则表达式的库。在小型匹配的情况下有非常优秀的表现。</p>
		<p>　　5.11 综合</p>
		<p>　　(1) P::Classes</p>
		<p>　　参考网站：<a href="http://pclasses.com/">http://pclasses.com/</a></p>
		<p>　　一个高度可移植的C++应用程序框架。当前关注类型和线程安全的signal/slot机制，i/o系统包括基于插件的网络协议透明的i/o架构，基于插件的应用程序消息日志框架，访问sql数据库的类等等。</p>
		<p>　　(2) ACDK - Artefaktur Component Development Kit</p>
		<p>　　参考网站：<a href="http://acdk.sourceforge.net/">http://acdk.sourceforge.net/</a></p>
		<p>　　这是一个平台无关的C++组件框架，类似于Java或者.NET中的框架（反射机制，线程，Unicode，废料收集，I/O，网络，实用工具，XML，等等），以及对Java, Perl, Python, TCL, Lisp, COM 和 CORBA的集成。</p>
		<p>　　(3) dlib C++ library</p>
		<p>　　参考网站：<a href="http://www.cis.ohio-state.edu/~kingd/dlib/">http://www.cis.ohio-state.edu/~kingd/dlib/</a></p>
		<p>　　各种各样的类的一个综合。大整数，Socket，线程，GUI，容器类,以及浏览目录的API等等。</p>
		<p>　　(4) Chilkat C++ Libraries</p>
		<p>　　参考网站：<a href="http://www.chilkatsoft.com/cpp_libraries.asp">http://www.chilkatsoft.com/cpp_libraries.asp</a></p>
		<p>　　这是提供zip，e-mail，编码，S/MIME，XML等方面的库。</p>
		<p>　　(5) C++ Portable Types Library (PTypes)</p>
		<p>　　参考网站：<a href="http://www.melikyan.com/ptypes/">http://www.melikyan.com/ptypes/</a></p>
		<p>　　这是STL的比较简单的替代品，以及可移植的多线程和网络库。</p>
		<p>　　(6) LFC</p>
		<p>　　参考网站：<a href="http://lfc.sourceforge.net/">http://lfc.sourceforge.net/</a></p>
		<p>　　哦，这又是一个尝试提供一切的C++库</p>
		<p>　　5.12 其他库</p>
		<p>　　(1) Loki</p>
		<p>　　参考网站：<a href="http://www.moderncppdesign.com/">http://www.moderncppdesign.com/</a></p>
		<p>　　哦，你可能抱怨我早该和Boost一起介绍它，一个实验性质的库。作者在loki中把C++模板的功能发挥到了极致。并且尝试把类似设计模式这样思想层面的东西通过库来提供。同时还提供了智能指针这样比较实用的功能。</p>
		<p>　　(2) ATL</p>
		<p>　　ATL(Active Template Library)</p>
		<p>　　是一组小巧、高效、灵活的类，这些类为创建可互操作的COM组件提供了基本的设施。</p>
		<p>　　(3) FC++: The Functional C++ Library</p>
		<p>　　这个库提供了一些函数式语言中才有的要素。属于用库来扩充语言的一个代表作。如果想要在OOP之外寻找另一分的乐趣，可以去看看函数式程序设计的世界。大师Peter Norvig在 “Teach Yourself rogramming in Ten Years”一文中就将函数式语言列为至少应当学习的6类编程语言之一。</p>
		<p>　　(4) FACT!</p>
		<p>　　参考网站：<a href="http://www.kfa-juelich.de/zam/FACT/start/index.html">http://www.kfa-juelich.de/zam/FACT/start/index.html</a></p>
		<p>　　另外一个实现函数式语言特性的库</p>
		<p>　　(5) Crypto++</p>
		<p>　　提供处理密码，消息验证，单向hash，公匙加密系统等功能的免费库。</p>
		<p>　　还有很多非常激动人心或者是极其实用的C++库，限于我们的水平以及文章的篇幅不能包括进来。在对于这些已经包含近来的库的介绍中，由于并不是每一个我们都使用过，所以难免有偏颇之处，请读者见谅。</p>
		<p>--------------------------------------------------------------------------------</p>
		<p>　　6，书籍</p>
		<p>　　以前熊节先生曾撰文评论相对于Java程序设计语言，C++的好书多如牛毛。荣耀先生在《程序员》杂志上撰文《C++程序设计之四书五经》也将本领域内几乎所有的经典书籍作了全面的介绍,任何关于书的评论此时看来便是很多余的了。个人浅见，除非你打算以C++作为唯一兴趣或者生存之本，一般读者确实没有足够的时间和必要将20余本书籍全部阅读。更有参考价值的是荣耀先生的另一篇文章：《至少应该阅<br />读的九本C++著作》，可以从下面的地址浏览到此文：</p>
		<p>　　<a href="http://www.royaloo.com/articles/articles_2003/9CppBooks.htm">http://www.royaloo.com/articles/articles_2003/9CppBooks.htm</a></p>
		<p>　　下面几本书对于走在C++初学之路上的读者是我们最愿意推荐给大家的：</p>
		<p>　　(1) 《C++ Primer》</p>
		<p>　　哦，也许你会抱怨我们为什么不先介绍TCPL,但对于走在学习之路上的入门者，本书内容更为全面，更为详细易懂，我们称它为“C++的超级宝典”并不过分。配有一本不错的习题解答《C++ Primer Answer Book》可以辅助你的学习之路。</p>
		<p>　　(2) 《Essential C++》</p>
		<p>　　如果说《C++ Primer》是C++领域的超级宝典，那么此书作为掌握C++的大局观当之无愧。正如《.NET大局观》一书能够让读者全揽.NET，本书讲述了C++中最核心的全部主题。书虽不厚，内容精炼，不失为《C++ Primer》读者茶余饭后的主题回顾之作。</p>
		<p>　　(3) 《The C++ Programming Language》</p>
		<p>　　Bjarne为你带来的C++教程，真正能够告诉你怎么用才叫真正的C++的唯一一本书。虽然如同“某某程序设计语言”这样的书籍会给大家一个内容全揽，入门到精通的感觉，但本书确实不太适合初学者阅读。如果你自认为是一名很有经验的C++程序员，那至少也要反复咀嚼Bjarne先生所强调的若干内容。</p>
		<p>　　(4) 《Effective C++》，《More Effective C++》</p>
		<p>　　是的，正如一些C++爱好者经常以读过与没有读过上述两本作品来区分你是否是C++高手。我们也极力推崇这两本著作。在各种介绍C++专家经验的书籍里面，这两本是最贴近语言本质，看后最能够有脱胎换骨感觉的书，读此书你需每日三省汝身。</p>
		<p>　　技术书籍仁者见仁，过多的评论反无太多意义，由读者喜好选择最适合自己的书方为上策。</p>
		<p>--------------------------------------------------------------------------------</p>
		<p>　　7，资源网站</p>
		<p>　　正如我们可以通过计算机历史上的重要人物了解计算机史的发展，C++相关人物的网站也可以使我们得到最有价值的参考与借鉴，下面的人物我们认为没有介绍的必要，只因下面的人物在C++领域的地位众所周知，我们只将相关的资源进行罗列以供读者学习，他们有的工作于贝尔实验室，有的工作于知名编译器厂商，有的在不断推进语言的标准化，有的为读者撰写了多部千古奇作……<br />　　(1) Bjarne Stroustrup<br />　　<a href="http://www.research.att.com/~bs/">http://www.research.att.com/~bs/</a></p>
		<p>　　(2) Stanley B. Lippman<br />　　<a href="http://blogs.msdn.com/slippman/">http://blogs.msdn.com/slippman/</a><br />　　中文版 <a href="http://www.zengyihome.net/slippman/index.htm">http://www.zengyihome.net/slippman/index.htm</a></p>
		<p>　　(3) Scott Meyers<br />　　<a href="http://www.aristeia.com/">http://www.aristeia.com/</a></p>
		<p>　　(4) David Musser<br />　　<a href="http://www.cs.rpi.edu/~musser/">http://www.cs.rpi.edu/~musser/</a></p>
		<p>　　(5) Bruce Eckel<br />　　<a href="http://www.bruceeckel.com/">http://www.bruceeckel.com/</a></p>
		<p>　　(6) Nicolai M. Josuttis<br />　　<a href="http://www.josuttis.com/">http://www.josuttis.com/</a></p>
		<p>　　(7) Herb Sutter<br />　　<a href="http://www.gotw.ca/">http://www.gotw.ca/</a></p>
		<p>　　(8) Andrei Alexandrescu<br />　　<a href="http://www.coderncppdesign.com/">http://www.coderncppdesign.com/</a></p>
		<p>　　(9) 侯捷先生<br />　　<a href="http://www.jjhou.com/">http://www.jjhou.com/</a></p>
		<p>　　(10) 孟岩先生<br />　　先生繁忙于工作，痴迷于技术，暂无个人主页，关于先生的作品可以通过CSDN的专栏和侯先生的主页访问到。</p>
		<p>　　(11) 荣耀先生<br />　　<a href="http://www.royaloo.com/">http://www.royaloo.com/</a></p>
		<p>　　(12) 潘爱民先生<br />　　<a href="http://www.icst.pku.edu.cn/panaimin/pam_homepage.htm">http://www.icst.pku.edu.cn/panaimin/pam_homepage.htm</a></p>
		<p>　　除了上述大师的主页外，以下的综合类C++学习参考站点是我们非常愿意向大家推荐的：</p>
		<p>　　(1) CodeProject<br />　　<a href="http://www.codeproject.com/">http://www.codeproject.com/</a></p>
		<p>　　(2) CodeGuru<br />　　<a href="http://www.codeguru.com/">http://www.codeguru.com/</a></p>
		<p>　　(3) Dr. Dobb's Journal<br />　　<a href="http://www.ddj.com/">http://www.ddj.com/</a></p>
		<p>　　(4) C/C++ Users Journal<br />　　<a href="http://www.cuj.com/">http://www.cuj.com/</a></p>
		<p>　　(5) C维视点<br />　　<a href="http://www.c-view.org/">http://www.c-view.org/</a></p>
		<p>　　(6) allaboutprogram<br />　　<a href="http://www.allaboutprogram.com/">http://www.allaboutprogram.com/</a><br />　　其他资料</p>
		<p>　　(1) ISO IEC JTC1/SC22/WG21 - C++：标准C++的权威参考<br />　　<a href="http://anubis.dkuug.dk/jtc1/sc22/wg21/">http://anubis.dkuug.dk/jtc1/sc22/wg21/</a></p>
		<p>　　(2) C++ FAQ LITE — Frequently Asked Questions: 最为全面的C++FAQ<br />　　<a href="http://www.sunistudio.com/cppfaq/index.html">http://www.sunistudio.com/cppfaq/index.html</a><br />　　C/C++ 新闻组：<br />　　你不妨尝试从这里提问和回答问题，很多不错的Q&amp;A资源......</p>
		<p>　　(1) .alt.comp.lang.learn.c-c++<br />　　这个简单些，如果你和我一样是个菜鸟</p>
		<p>　　(2) .comp.lang.c++.moderated<br />  嗯，这个显然水平高一些</p>
		<p>　　(3) .comp.std.c++<br />　　如果你需要讨论标准C++相关话题的话</p>
		<p>--------------------------------------------------------------------------------</p>
		<p>　　8，不得不写的结束语</p>
		<p>　　结束的时候也是总结现状，展望未来的时候。虽然C++从脱胎于C开始，一路艰难坎坷的走过来，但是无论如何C++已经取得了工业基础的地位。文章列举的大量相关资源就是最好的证明，而业界的大量用C++写成的产品代码以及大量的C++职业工程师则是最直接的证明。同时，我们可以看到各个高校的计算机专业都开设有C++这门课程，网络上对于C++的学习讨论也从来都没有停过。但是，在Java和.NET两大企业开发平台的围攻下，给人的感觉是C++越来越“不行”了。</p>
		<p>　　C++在面向企业的软件开发中，在开发便捷性等方面的确要比Java和C#差很多，其中一个问题是C++语言本身比较复杂，学习曲线比较陡峭，另外一个问题是C++标准化的时间太长，丧失了很多的壮大机会，耗费了很多精力在厂商的之间的斗争上，而C++的标准库离一个完善的程序开发框架还缺少太多太多的内容，各个第三方的类库和框架又在一致性和完整性上没法和随平台提供的框架相提并论。难道C++真的要退出历史舞台了？</p>
		<p>　　从C++目前的活跃程度，以及应用现状来说是完全能够肯定C++仍然是软件工业的基础，也不会退出历史舞台的。另外从Boost，Loki这些库中我们也能够看到C++的发展非常活跃，对于新技术新思维非常激进，C++仍然广泛受到关注。从ACE在高性能通信领域的应用，以及MTL这样的库在数值计算领域的出色表现，我们可以看到C++在高性能应用场合下的不可替代的作用，而嵌入式系统这样的内存受限开发平台<br />，比如Symbian OS上，C++已经发挥着并且将发挥更大的作用。可以预见的是以后的软件无论上层的应用怎么变，它的底层核心都会是由C/C++这样的系统级软件编写的，比如Java虚拟机，.NET Framwork。因为只有这样的系统级软件才能完全彻底的发挥机器的功能。</p>
		<p>　　需要看到的是两个趋势，一个趋势是C++变得更加复杂，更加学院派，通过模板等有潜力的语法因素构造越来越精巧的库成为了现代C++的热点，虽然在利用库实现新的编程范式，乃至设计模式等方面很有开创意义，也确实产生了一些能够便捷开发的工具，但是更多的是把C++变得更加强大，更加复杂，也更加难懂，似乎也更加学院派，不得不说它正在向边缘化道路发展。另一个趋势是C++在主流的企业应用开<br />发中已经逐渐退出了，ERP这样的企业软件开发中基本上不会考虑C++，除非需要考虑性能或者和遗留代码的集成这些因素。C++退守到系统级别语言，成为软件工业的基础是大势所趋。然而反思一下，真的是退守么？自从STL出现，无数的人风起云涌的开始支持C++,他们狂呼“我看到深夜消失了，目标软件工程的出现。我看到了可维护的代码。”是的，STL在可维护性下做得如此出色。但是又怎样呢？STL为C++铺平了现代软件工程的道路，而在上层应用程序软件开发领域这块场地早不单独属于C++,很多程序设计语言都做得很出色，疯狂的支持者会毫不犹豫地说我们应当支持C++,因为它是世界上最棒的语言。而坦率地说，你的腰杆真的那么硬么？也许只是在逃避一些事实。C++是优秀的，这不可否认，STL的出现让C++一度走上了最辉煌的时刻，然而现在看来……我的一位恩师曾言：真正能够将STL应用得淋漓尽致的人很<br />保守地说国内也不超过200人，或许不加入STL能够使C++向着它应当发展的方向发展的更好，而现在看来，C++也应当回首到真正属于他的那一片圣地上……</p>
<img src ="http://www.cppblog.com/eday/aggbug/18382.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/eday/" target="_blank">松*</a> 2007-02-05 10:07 <a href="http://www.cppblog.com/eday/archive/2007/02/05/18382.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ 类库</title><link>http://www.cppblog.com/eday/archive/2007/01/20/17805.html</link><dc:creator>松*</dc:creator><author>松*</author><pubDate>Fri, 19 Jan 2007 18:58:00 GMT</pubDate><guid>http://www.cppblog.com/eday/archive/2007/01/20/17805.html</guid><description><![CDATA[C++类库介绍 <br />再次体现了C++保持核心语言的效率同时大力发展应用库的发展趋势!!在C++中，库的地位是非常高的。C++之父 Bjarne Stroustrup先生多次表示了设计库来扩充功能要好过设计更多的语法的言论。现实中，C++的库门类繁多，解决的问题也是极其广泛，库从轻量级到重量级的都有。不少都是让人眼界大开，亦或是望而生叹的思维杰作。由于库的数量非常庞大，而且限于笔者水平，其中很多并不了解。所以文中所提的一些库都是比较著名的大型库。 <br /><br />标准库 <br /><br />标准库中提供了C++程序的基本设施。虽然C++标准库随着C++标准折腾了许多年，直到标准的出台才正式定型，但是在标准库的实现上却很令人欣慰得看到多种实现，并且已被实践证明为有工业级别强度的佳作。 <br /><br />1、 Dinkumware C++ Library <br /><br />参考站点：<a href="http://www.dinkumware.com/" target="_blank"><font color="#261cdc">http://www.dinkumware.com/</font></a>'&gt;<a href="http://www.dinkumware.com/" target="_blank"><font color="#261cdc">http://www.dinkumware.com/</font></a> <br /><br />P.J. Plauger编写的高品质的标准库。P.J. Plauger博士是Dr. Dobb's程序设计杰出奖的获得者。其编写的库长期被Microsoft采用，并且最近Borland也取得了其OEM的license，在其C/C+ +的产品中采用Dinkumware的库。 <br /><br />2、 RogueWave Standard C++ Library <br /><br />参考站点：<a href="http://www.roguewave.com/" target="_blank"><font color="#261cdc">http://www.roguewave.com/</font></a>'&gt;<a href="http://www.roguewave.com/" target="_blank"><font color="#261cdc">http://www.roguewave.com/</font></a>'&gt;<a href="http://www.roguewave.com/" target="_blank"><font color="#261cdc">http://www.roguewave.com/</font></a>'&gt;<a href="http://www.roguewave.com/" target="_blank"><font color="#261cdc">http://www.roguewave.com/</font></a> <br /><br />这个库在Borland C++ Builder的早期版本中曾经被采用，后来被其他的库给替换了。笔者不推荐使用。 <br /><br />3、SGI STL <br /><br />参考站点：<a href="http://www.roguewave.com/" target="_blank"><font color="#261cdc">http://www.roguewave.com/</font></a>'&gt;<a href="http://www.roguewave.com/" target="_blank"><font color="#261cdc">http://www.roguewave.com/</font></a>'&gt;<a href="http://www.roguewave.com/" target="_blank"><font color="#261cdc">http://www.roguewave.com/</font></a>'&gt;<a href="http://www.roguewave.com/" target="_blank"><font color="#261cdc">http://www.roguewave.com/</font></a> <br /><br />SGI公司的C++标准模版库。 <br /><br />4、STLport <br /><br />参考站点：<a href="http://www.stlport.org/" target="_blank"><font color="#261cdc">http://www.stlport.org/</font></a>'&gt;<a href="http://www.stlport.org/" target="_blank"><font color="#261cdc">http://www.stlport.org/</font></a> <br /><br />SGI STL库的跨平台可移植版本。 <br /><br /><br /><br />准标准库——Boost <br /><br />Boost 库是一个经过千锤百炼、可移植、提供源代码的C++库，作为标准库的后备，是C++标准化进程的发动机之一。 Boost库由C++标准委员会库工作组成员发起，在C++社区中影响甚大，其成员已近2000人。 Boost库为我们带来了最新、最酷、最实用的技术，是不折不扣的"准"标准库。 <br /><br />Boost中比较有名气的有这么几个库： <br /><br />Regex <br />正则表达式库 <br /><br />Spirit <br />LL parser framework，用C++代码直接表达EBNF <br /><br />Graph <br />图组件和算法 <br /><br />Lambda <br />在调用的地方定义短小匿名的函数对象，很实用的functional功能 <br /><br />concept check <br />检查泛型编程中的concept <br /><br />Mpl <br />用模板实现的元编程框架 <br /><br />Thread <br />可移植的C++多线程库 <br /><br />Python <br />把C++类和函数映射到Python之中 <br /><br />Pool <br />内存池管理 <br /><br />smart_ptr <br />5个智能指针，学习智能指针必读，一份不错的参考是来自CUJ的文章： <br /><br />Smart Pointers in Boost,哦，这篇文章可以查到，CUJ是提供在线浏览的。中文版见笔者在《Dr. Dobb's Journal软件研发杂志》第7辑上的译文。 <br /><br /><br />Boost 总体来说是实用价值很高，质量很高的库。并且由于其对跨平台的强调，对标准C++的强调，是编写平台无关，现代C++的开发者必备的工具。但是Boost 中也有很多是实验性质的东西，在实际的开发中实用需要谨慎。并且很多Boost中的库功能堪称对语言功能的扩展，其构造用尽精巧的手法，不要贸然的花费时间研读。Boost另外一面，比如Graph这样的库则是具有工业强度，结构良好，非常值得研读的精品代码，并且也可以放心的在产品代码中多多利用。 <br /><br />参考站点：<a href="http://www.boost.org/" target="_blank"><font color="#261cdc">http://www.boost.org</font></a>'&gt;<a href="http://www.boost.org/" target="_blank"><font color="#261cdc">http://www.boost.org</font></a>（国内镜像：<a href="http://www.c/" target="_blank"><font color="#261cdc">http://www.c</font></a>'&gt; <a href="http://www.c/" target="_blank"><font color="#261cdc">http://www.c</font></a>'&gt;<a href="http://www.c/" target="_blank"><font color="#261cdc">http://www.c</font></a>'&gt;<a href="http://www.c-view.org/tech/lib/boost/index.htm" target="_blank"><font color="#261cdc">http://www.c-view.org/tech/lib/boost/index.htm</font></a>） <br /><br />GUI <br /><br />在众多C++的库中，GUI部分的库算是比较繁荣，也比较引人注目的。在实际开发中，GUI库的选择也是非常重要的一件事情，下面我们综述一下可选择的GUI库，各自的特点以及相关工具的支持。 <br /><br />1、 MFC <br /><br />大名鼎鼎的微软基础类库（Microsoft Foundation Class）。大凡学过VC++的人都应该知道这个库。虽然从技术角度讲，MFC是不大漂亮的，但是它构建于Windows API 之上，能够使程序员的工作更容易,编程效率高，减少了大量在建立 Windows 程序时必须编写的代码，同时它还提供了所有一般 C++ 编程的优点，例如继承和封装。MFC 编写的程序在各个版本的Windows操作系统上是可移植的，例如，在 Windows 3.1下编写的代码可以很容易地移植到 Windows NT 或 Windows 95 上。但是在最近发展以及官方支持上日渐势微。 <br /><br /><br /><br />2、 QT <br /><br />参考网站：<a href="http://www.trolltech.com/" target="_blank"><font color="#261cdc">http://www.trolltech.com/</font></a>'&gt;<a href="http://www.trolltech.com/" target="_blank"><font color="#261cdc">http://www.trolltech.com/</font></a> <br /><br />Qt 是Trolltech公司的一个多平台的C++图形用户界面应用程序框架。它提供给应用程序开发者建立艺术级的图形用户界面所需的所用功能。Qt是完全面向对象的很容易扩展，并且允许真正地组件编程。自从1996年早些时候，Qt进入商业领域，它已经成为全世界范围内数千种成功的应用程序的基础。Qt也是流行的Linux桌面环境KDE 的基础，同时它还支持Windows、Macintosh、Unix/X11等多种平台。 <br /><br /><br /><br />3、WxWindows <br /><br />参考网站：<a href="http://www.wxwindows.org/" target="_blank"><font color="#261cdc">http://www.wxwindows.org/</font></a>'&gt;<a href="http://www.wxwindows.org/" target="_blank"><font color="#261cdc">http://www.wxwindows.org/</font></a> <br /><br />跨平台的GUI库。因为其类层次极像MFC，所以有文章介绍从MFC到WxWindows的代码移植以实现跨平台的功能。通过多年的开发也是一个日趋完善的 GUI库，支持同样不弱于前面两个库。并且是完全开放源代码的。新近的C++ Builder X的GUI设计器就是基于这个库的。 <br /><br />4、Fox <br /><br />开放源代码的GUI库。作者从自己亲身的开发经验中得出了一个理想的GUI库应该是什么样子的感受出发，从而开始了对这个库的开发。有兴趣的可以尝试一下。 <br /><br />参考网站：<a href="http://www.fox/" target="_blank"><font color="#261cdc">http://www.fox</font></a>'&gt;<a href="http://www.fox-toolkit.org/" target="_blank"><font color="#261cdc">http://www.fox-toolkit.org/</font></a> <br /><br />5、 WTL <br /><br />基于ATL的一个库。因为使用了大量ATL的轻量级手法，模板等技术，在代码尺寸，以及速度优化方面做得非常到位。主要面向的使用群体是开发COM轻量级供网络下载的可视化控件的开发者。 <br /><br />6、 GTK <br /><br />参考网站：<a href="http://gtkmm.sourceforge.net/" target="_blank"><font color="#261cdc">http://gtkmm.sourceforge.net/</font></a> <br /><br />GTK是一个大名鼎鼎的C的开源GUI库。在Linux世界中有Gnome这样的杀手应用。而GTK就是这个库的C++封装版本。 <br /><br />? <br /><br />库 <br /><br /><br />网络通信 <br /><br />ACE <br /><br />参考网站：<a href="http://www.c/" target="_blank"><font color="#261cdc">http://www.c</font></a>'&gt;<a href="http://www.c/" target="_blank"><font color="#261cdc">http://www.c</font></a>'&gt;<a href="http://www.c/" target="_blank"><font color="#261cdc">http://www.c</font></a>'&gt;<a href="http://www.cs.wustl.edu/~schmidt/ACE.html" target="_blank"><font color="#261cdc">http://www.cs.wustl.edu/~schmidt/ACE.html</font></a> <br /><br />C+ +库的代表，超重量级的网络通信开发框架。ACE自适配通信环境（Adaptive Communication Environment）是可以自由使用、开放源代码的面向对象框架，在其中实现了许多用于并发通信软件的核心模式。ACE提供了一组丰富的可复用C++ 包装外观（Wrapper Facade）和框架组件，可跨越多种平台完成通用的通信软件任务，其中包括：事件多路分离和事件处理器分派、信号处理、服务初始化、进程间通信、共享内存管理、消息路由、分布式服务动态（重）配置、并发执行和同步，等等。 <br /><br />StreamModule <br /><br />参考网站：<a href="http://www.omnifarious.org/StrMod/" target="_blank"><font color="#261cdc">http://www.omnifarious.org/StrMod/</font></a>'&gt;<a href="http://www.omnifarious.org/StrMod/" target="_blank"><font color="#261cdc">http://www.omnifarious.org/StrMod/</font></a> <br /><br />设计用于简化编写分布式程序的库。尝试着使得编写处理异步行为的程序更容易，而不是用同步的外壳包起异步的本质。 <br /><br />SimpleSocket <br /><br />参考网站：<a href="http://home.hetnet.nl/~lcbokkers/si" target="_blank"><font color="#261cdc">http://home.hetnet.nl/~lcbokkers/simsock.htm</font></a> <br /><br />这个类库让编写基于socket的客户/服务器程序更加容易。 <br /><br />A Stream Socket API for C++ <br /><br />参考网站：<a href="http://www.pcs.cnu.edu/" target="_blank"><font color="#261cdc">http://www.pcs.cnu.edu/</font></a>'&gt;<a href="http://www.pcs.cnu.edu/~dgame/sockets/socketsC++/sockets.html" target="_blank"><font color="#261cdc">http://www.pcs.cnu.edu/~dgame/sockets/socketsC++/sockets.html</font></a> <br /><br />又一个对Socket的封装库。 <br /><br />XML <br /><br />Xerces <br /><br />参考网站：<a href="http://xml.apache.org/xerces-c/" target="_blank"><font color="#261cdc">http://xml.apache.org/xerces-c/</font></a> <br /><br />Xerces-C++ 是一个非常健壮的XML解析器，它提供了验证，以及SAX和DOM API。XML验证在文档类型定义(Document Type Definition，DTD)方面有很好的支持，并且在2001年12月增加了支持W3C XML Schema 的基本完整的开放标准。 <br /><br />XMLBooster <br /><br />参考网站：<a href="http://www.xmlbooster.com/" target="_blank"><font color="#261cdc">http://www.xmlbooster.com/</font></a>'&gt;<a href="http://www.xmlbooster.com/" target="_blank"><font color="#261cdc">http://www.xmlbooster.com/</font></a> <br /><br />这个库通过产生特制的parser的办法极大的提高了XML解析的速度，并且能够产生相应的GUI程序来修改这个parser。在DOM和SAX两大主流XML解析办法之外提供了另外一个可行的解决方案。 <br /><br />Pull Parser <br /><br />参考网站：<a href="http://www.extreme.indiana.edu/xgws/xsoap/xpp/" target="_blank"><font color="#261cdc">http://www.extreme.indiana.edu/xgws/xsoap/xpp/</font></a>'&gt;<a href="http://www.extreme.indiana.edu/xgws/xsoap/xpp/" target="_blank"><font color="#261cdc">http://www.extreme.indiana.edu/xgws/xsoap/xpp/</font></a> <br /><br />这个库采用pull方法的parser。在每个SAX的parser底层都有一个pull的parser，这个xpp把这层暴露出来直接给大家使用。在要充分考虑速度的时候值得尝试。 <br /><br />Xalan <br /><br />参考网站：<a href="http://xml.apache.org/xalan-c/" target="_blank"><font color="#261cdc">http://xml.apache.org/xalan-c/</font></a> <br /><br />Xalan是一个用于把XML文档转换为HTML，纯文本或者其他XML类型文档的XSLT处理器。 <br /><br />CMarkup <br /><br />参考网站：<a href="http://www.firstobject.com/xml.htm" target="_blank"><font color="#261cdc">http://www.firstobject.com/xml.htm</font></a>'&gt;<a href="http://www.firstobject.com/xml.htm" target="_blank"><font color="#261cdc">http://www.firstobject.com/xml.htm</font></a> <br /><br />这是一种使用EDOM的XML解析器。在很多思路上面非常灵活实用。值得大家在DOM和SAX之外寻求一点灵感。 <br /><br />libxml++ <br /><br /><a href="http://libxmlplusplus.sourceforge.net/" target="_blank"><font color="#261cdc">http://libxmlplusplus.sourceforge.net/</font></a> <br /><br />libxml++是对著名的libxml XML解析器的C++封装版本 <br /><br /><br /><br />科学计算 <br /><br />Blitz++ <br /><br />参考网站：<a href="http://www.oonumerics.org/blitz/" target="_blank"><font color="#261cdc">http://www.oonumerics.org/blitz/</font></a>'&gt;<a href="http://www.oonumerics.org/blitz/" target="_blank"><font color="#261cdc">http://www.oonumerics.org/blitz/</font></a> <br /><br />Blitz++ 是一个高效率的数值计算函数库，它的设计目的是希望建立一套既具像C++ 一样方便，同时又比Fortran速度更快的数值计算环境。通常，用C++所写出的数值程序，比 Fortran慢20%左右，因此Blitz++正是要改掉这个缺点。方法是利用C++的template技术，程序执行甚至可以比Fortran更快。 Blitz++目前仍在发展中，对于常见的SVD，FFTs，QMRES等常见的线性代数方法并不提供，不过使用者可以很容易地利用Blitz++所提供的函数来构建。 <br /><br />POOMA <br /><br />参考网站：<a href="http://www.c/" target="_blank"><font color="#261cdc">http://www.c</font></a>'&gt;<a href="http://www.c/" target="_blank"><font color="#261cdc">http://www.c</font></a>'&gt;<a href="http://www.c/" target="_blank"><font color="#261cdc">http://www.c</font></a>'&gt;<a href="http://www.codesourcery.com/pooma/pooma" target="_blank"><font color="#261cdc">http://www.codesourcery.com/pooma/pooma</font></a> <br /><br />POOMA是一个免费的高性能的C++库，用于处理并行式科学计算。POOMA的面向对象设计方便了快速的程序开发，对并行机器进行了优化以达到最高的效率，方便在工业和研究环境中使用。 <br /><br />MTL <br /><br />参考网站：<a href="http://www.osl.iu.edu/research/mtl/" target="_blank"><font color="#261cdc">http://www.osl.iu.edu/research/mtl/</font></a>'&gt;<a href="http://www.osl.iu.edu/research/mtl/" target="_blank"><font color="#261cdc">http://www.osl.iu.edu/research/mtl/</font></a> <br /><br />Matrix Template Library(MTL)是一个高性能的泛型组件库，提供了各种格式矩阵的大量线性代数方面的功能。在某些应用使用高性能编译器的情况下，比如Intel的编译器，从产生的汇编代码可以看出其与手写几乎没有两样的效能。 <br /><br />CGAL <br /><br />参考网站：<a href="http://www.cgal.org/" target="_blank"><font color="#261cdc">www.cgal.org</font></a> <br /><br />Computational Geometry Algorithms Library的目的是把在计算几何方面的大部分重要的解决方案和方法以C++库的形式提供给工业和学术界的用户。 <br /><br /><br /><br />游戏开发 <br /><br />Audio/Video 3D C++ Programming Library <br /><br />参考网站：<a href="http://www.galacticasoftware.com/products/av/" target="_blank"><font color="#261cdc">http://www.galacticasoftware.com/products/av/</font></a>'&gt;<a href="http://www.galacticasoftware.com/products/av/" target="_blank"><font color="#261cdc">http://www.galacticasoftware.com/products/av/</font></a> <br /><br />AV3D是一个跨平台，高性能的C++库。主要的特性是提供3D图形，声效支持（SB,以及S3M），控制接口（键盘，鼠标和遥感），XMS。 <br /><br />KlayGE <br /><br />参考网站：<a href="http://home.g365.net/enginedev/" target="_blank"><font color="#261cdc">http://home.g365.net/enginedev/</font></a> <br /><br />国内游戏开发高手自己用C++开发的游戏引擎。KlayGE是一个开放源代码、跨平台的游戏引擎，并使用Python作脚本语言。KlayGE在LGPL协议下发行。感谢龚敏敏先生为中国游戏开发事业所做出的贡献。 <br /><br />OGRE <br /><br />参考网站：<a href="http://www.ogre3d.org/" target="_blank"><font color="#261cdc">http://www.ogre3d.org</font></a>'&gt;<a href="http://www.ogre3d.org/" target="_blank"><font color="#261cdc">http://www.ogre3d.org</font></a> <br /><br />OGRE （面向对象的图形渲染引擎）是用C++开发的，使用灵活的面向对象3D引擎。它的目的是让开发者能更方便和直接地开发基于3D硬件设备的应用程序或游戏。引擎中的类库对更底层的系统库（如：Direct3D和OpenGL）的全部使用细节进行了抽象，并提供了基于现实世界对象的接口和其它类。 <br /><br /><br /><br />线程 <br /><br />C++ Threads <br /><br />参考网站：<a href="http://threads.sourceforge.net/" target="_blank"><font color="#261cdc">http://threads.sourceforge.net/</font></a> <br /><br />这个库的目标是给程序员提供易于使用的类，这些类被继承以提供在Linux环境中很难看到的大量的线程方面的功能。 <br /><br />ZThreads <br /><br />参考网站：<a href="http://zthread.sourceforge.net/" target="_blank"><font color="#261cdc">http://zthread.sourceforge.net/</font></a> <br /><br />一个先进的面向对象，跨平台的C++线程和同步库。 <br /><br /><br /><br />序列化 <br /><br />s11n <br /><br />参考网站：<a href="http://s11n.net/" target="_blank"><font color="#261cdc">http://s11n.net/</font></a> <br /><br />一个基于STL的C++库，用于序列化POD，STL容器以及用户定义的类型。 <br /><br />Simple XML Persistence Library <br /><br />参考网站：<a href="http://sxp.sourceforge.net/" target="_blank"><font color="#261cdc">http://sxp.sourceforge.net/</font></a> <br /><br />这是一个把对象序列化为XML的轻量级的C++库。 <br /><br /><br /><br />字符串 <br /><br />C++ Str Library <br /><br />参考网站：<a href="http://www.utilitycode.com/str/" target="_blank"><font color="#261cdc">http://www.utilitycode.com/str/</font></a>'&gt;<a href="http://www.utilitycode.com/str/" target="_blank"><font color="#261cdc">http://www.utilitycode.com/str/</font></a> <br /><br />操作字符串和字符的库，支持Windows和支持gcc的多种平台。提供高度优化的代码，并且支持多线程环境和Unicode，同时还有正则表达式的支持。 <br /><br />Common Text Transformation Library <br /><br />参考网站：<a href="http://cttl.sourceforge.net/" target="_blank"><font color="#261cdc">http://cttl.sourceforge.net/</font></a> <br /><br />这是一个解析和修改STL字符串的库。CTTL substring类可以用来比较，插入，替换以及用EBNF的语法进行解析。 <br /><br />GRETA <br /><br />参考网站：<a href="http://research.microsoft.com/projects/greta/" target="_blank"><font color="#261cdc">http://research.microsoft.com/projects/greta/</font></a> <br /><br />这是由微软研究院的研究人员开发的处理正则表达式的库。在小型匹配的情况下有非常优秀的表现。 <br /><br />综合 <br /><br />P::Classes <br /><br />参考网站：<a href="http://pclasses.com/" target="_blank"><font color="#261cdc">http://pclasses.com/</font></a> <br /><br />一个高度可移植的C++应用程序框架。当前关注类型和线程安全的signal/slot机制，i/o系统包括基于插件的网络协议透明的i/o架构，基于插件的应用程序消息日志框架，访问sql数据库的类等等。 <br /><br />ACDK - Artefaktur Component Development Kit <br /><br />参考网站：<a href="http://acdk.sourceforge.net/" target="_blank"><font color="#261cdc">http://acdk.sourceforge.net/</font></a> <br /><br />这是一个平台无关的C++组件框架，类似于Java或者.NET中的框架（反射机制，线程，Unicode，废料收集，I/O，网络，实用工具，XML，等等），以及对Java, Perl, Python, TCL, Lisp, COM 和 CORBA的集成。 <br /><br />dlib C++ library <br /><br />参考网站：<a href="http://www.c/" target="_blank"><font color="#261cdc">http://www.c</font></a>'&gt;<a href="http://www.c/" target="_blank"><font color="#261cdc">http://www.c</font></a>'&gt;<a href="http://www.c/" target="_blank"><font color="#261cdc">http://www.c</font></a>'&gt;<a href="http://www.cis.ohio-state.edu/~kingd/dlib/" target="_blank"><font color="#261cdc">http://www.cis.ohio-state.edu/~kingd/dlib/</font></a> <br /><br />各种各样的类的一个综合。大整数，Socket，线程，GUI，容器类,以及浏览目录的API等等。 <br /><br />Chilkat C++ Libraries <br /><br />参考网站：<a href="http://www.c/" target="_blank"><font color="#261cdc">http://www.c</font></a>'&gt;<a href="http://www.c/" target="_blank"><font color="#261cdc">http://www.c</font></a>'&gt;<a href="http://www.c/" target="_blank"><font color="#261cdc">http://www.c</font></a>'&gt;<a href="http://www.chilkatsoft.com/cpp_libraries.asp" target="_blank"><font color="#261cdc">http://www.chilkatsoft.com/cpp_libraries.asp</font></a> <br /><br />这是提供zip，e-mail，编码，S/MIME，XML等方面的库。 <br /><br />C++ Portable Types Library (PTypes) <br /><br />参考网站：<a href="http://www.melikyan.com/ptypes/" target="_blank"><font color="#261cdc">http://www.melikyan.com/ptypes/</font></a>'&gt;<a href="http://www.melikyan.com/ptypes/" target="_blank"><font color="#261cdc">http://www.melikyan.com/ptypes/</font></a> <br /><br />这是STL的比较简单的替代品，以及可移植的多线程和网络库。 <br /><br />LFC <br /><br />参考网站：<a href="http://lfc.sourceforge.net/" target="_blank"><font color="#261cdc">http://lfc.sourceforge.net/</font></a> <br /><br />哦，这又是一个尝试提供一切的C++库 <br /><br /><br /><br />其他库 <br /><br />Loki <br /><br />参考网站：<a href="http://www.moderncppdesign.com/" target="_blank"><font color="#261cdc">http://www.moderncppdesign.com/</font></a>'&gt;http: //<a href="http://www.moderncppdesign.com/" target="_blank"><font color="#261cdc">www.moderncppdesign.com/</font></a>'&gt;<a href="http://www.moderncppdesign.com/" target="_blank"><font color="#261cdc">http://www.moderncppdesign.com/</font></a>'&gt;<a href="http://www.moderncppdesign.com/" target="_blank"><font color="#261cdc">http://www.moderncppdesign.com/</font></a> <br /><br />哦，你可能抱怨我早该和Boost一起介绍它，一个实验性质的库。作者在loki中把C++模板的功能发挥到了极致。并且尝试把类似设计模式这样思想层面的东西通过库来提供。同时还提供了智能指针这样比较实用的功能。 <br /><br />ATL <br /><br />ATL(Active Template Library)是一组小巧、高效、灵活的类，这些类为创建可互操作的COM组件提供了基本的设施。 <br /><br />FC++: The Functional C++ Library <br /><br />这个库提供了一些函数式语言中才有的要素。属于用库来扩充语言的一个代表作。如果想要在OOP之外寻找另一分的乐趣，可以去看看函数式程序设计的世界。大师 Peter Norvig在 "Teach Yourself Programming in Ten Years"一文中就将函数式语言列为至少应当学习的6类编程语言之一。 <br /><br />FACT! <br /><br />参考网站：<a href="http://www.kfa/" target="_blank"><font color="#261cdc">http://www.kfa</font></a>'&gt;<a href="http://www.kfa-juelich.de/zam/FACT/start/index.html" target="_blank"><font color="#261cdc">http://www.kfa-juelich.de/zam/FACT/start/index.html</font></a> <br /><br />另外一个实现函数式语言特性的库 <br /><br />Crypto++ <br /><br />提供处理密码，消息验证，单向hash，公匙加密系统等功能的免费库。 <br /><br />还有很多非常激动人心或者是极其实用的C++库，限于我们的水平以及文章的篇幅不能包括进来。在对于这些已经包含近来的库的介绍中，由于并不是每一个我们都使用过，所以难免有偏颇之处，请读者见谅。 <br /><br /><br /><br />资源网站 <br /><br />正如我们可以通过计算机历史上的重要人物了解计算机史的发展，C++相关人物的网站也可以使我们得到最有价值的参考与借鉴，下面的人物我们认为没有介绍的必要，只因下面的人物在C++领域的地位众所周知，我们只将相关的资源进行罗列以供读者学习，他们有的工作于贝尔实验室，有的工作于知名编译器厂商，有的在不断推进语言的标准化，有的为读者撰写了多部千古奇作...... <br /><br />Bjarne Stroustrup <a href="http://www.research.att.com/" target="_blank"><font color="#261cdc">http://www.research.att.com/</font></a>'&gt;<a href="http://www.research.att.com/~bs/" target="_blank"><font color="#261cdc">http://www.research.att.com/~bs/</font></a> <br /><br />Stanley B. Lippman <br /><br />http: //blogs.msdn.com/slippman/(中文版<a href="http://www.zengyihome.net/" target="_blank"><font color="#261cdc">http://www.zengyihome.net</font></a>'&gt;http: //<a href="http://www.zengyihome.net/slippman/index.htm" target="_blank"><font color="#261cdc">www.zengyihome.net/slippman/index.htm</font></a>'&gt;<a href="http://www.zengyihome.net/" target="_blank"><font color="#261cdc">http://www.zengyihome.net</font></a>'&gt;<a href="http://www.zengyihome.net/slippman/index.htm" target="_blank"><font color="#261cdc">http://www.zengyihome.net/slippman/index.htm</font></a>) <br /><br />Scott Meyers <a href="http://www.aristeia.com/" target="_blank"><font color="#261cdc">http://www.aristeia.com/</font></a>'&gt;<a href="http://www.aristeia.com/" target="_blank"><font color="#261cdc">http://www.aristeia.com/</font></a> <br /><br />David Musser <a href="http://www.c/" target="_blank"><font color="#261cdc">http://www.c</font></a>'&gt;<a href="http://www.c/" target="_blank"><font color="#261cdc">http://www.c</font></a>'&gt;<a href="http://www.c/" target="_blank"><font color="#261cdc">http://www.c</font></a>'&gt;<a href="http://www.cs.rpi.edu/~musser/" target="_blank"><font color="#261cdc">http://www.cs.rpi.edu/~musser/</font></a> <br /><br />Bruce Eckel <a href="http://www.bruceeckel.com/" target="_blank"><font color="#261cdc">http://www.bruceeckel.com</font></a>'&gt;<a href="http://www.bruceeckel.com/" target="_blank"><font color="#261cdc">http://www.bruceeckel.com</font></a> <br /><br />Nicolai M. Josuttis <a href="http://www.josuttis.com/" target="_blank"><font color="#261cdc">http://www.josuttis.com/</font></a>'&gt;<a href="http://www.josuttis.com/" target="_blank"><font color="#261cdc">http://www.josuttis.com/</font></a> <br /><br />Herb Sutter <a href="http://www.gotw.ca/" target="_blank"><font color="#261cdc">http://www.gotw.ca/</font></a>'&gt;<a href="http://www.gotw.ca/" target="_blank"><font color="#261cdc">http://www.gotw.ca/</font></a> <br /><br />Andrei Alexandrescu <a href="http://www.moderncppdesign.com/" target="_blank"><font color="#261cdc">http://www.moderncppdesign.com/</font></a>'&gt;<a href="http://www.moderncppdesign.com/" target="_blank"><font color="#261cdc">http://www.moderncppdesign.com/</font></a>'&gt;<a href="http://www.moderncppdesign.com/" target="_blank"><font color="#261cdc">http://www.moderncppdesign.com/</font></a>'&gt;<a href="http://www.moderncppdesign.com/" target="_blank"><font color="#261cdc">http://www.moderncppdesign.com/</font></a><img src ="http://www.cppblog.com/eday/aggbug/17805.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/eday/" target="_blank">松*</a> 2007-01-20 02:58 <a href="http://www.cppblog.com/eday/archive/2007/01/20/17805.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WTL出现GUID错误 Did you forget to pass the LIBID to CComModule::Init?</title><link>http://www.cppblog.com/eday/archive/2007/01/18/17754.html</link><dc:creator>松*</dc:creator><author>松*</author><pubDate>Thu, 18 Jan 2007 08:23:00 GMT</pubDate><guid>http://www.cppblog.com/eday/archive/2007/01/18/17754.html</guid><description><![CDATA[
		<font face="Verdana" size="2">    When using WTL 7.0 with ActiveX controls under ATL 7.1, the framework will ASSERT inside atlcom.h on the following line:<br /></font>
		<span style="FONT-FAMILY: monospace">
				<big>
						<font size="-1">    ATLASSERT(!InlineIsEqualGUID(*m_plibid,GUID_NULL) &amp;&amp; "Did you forget to pass the LIBID to CComModule::Init?");</font>
				</big>
				<br />
				<br />
		</span>
		<font face="Verdana">
				<font size="-1">    This can be solved one of two ways:<br />    1) Change your "Use of ATL" setting to "Dynamic Link to ATL" in your project properties.<br />    2) Change your "Use of ATL" setting to "Static Link to ATL" and instead of using <br />       </font>
		</font>
		<font size="-1">
				<big>
						<span style="FONT-FAMILY: monospace">hRes = _Module.Init(NULL, hInstance);</span>
				</big>
				<br />
		</font>
		<font face="Verdana">
				<font size="-1">       line in your _tWinMain, use this instead:<br /></font>
		</font>
		<font size="-1">
				<span style="FONT-FAMILY: monospace">     <big>GUID guid;</big></span>
				<big>
						<br style="FONT-FAMILY: monospace" />
				</big>
		</font>
		<big>
				<font face="Verdana">
						<font size="-1">
								<big>       </big>
						</font>
				</font>
				<font size="-1">
						<big>
								<span style="FONT-FAMILY: monospace">hRes = _Module.Init(NULL, hInstance, &amp;guid);<br /><br /></span>
						</big>
				</font>
		</big>
		<font face="Verdana">
				<font size="-1">    The ATLASSERT is apparently a bug in ATL 7.0/7.1 because everything works right if you pass a non-null GUID to _Module.Init(). Note that some people prefer to pass the actual LIBID instead of a garbage GUID, but this has no effect on whether the framework works correctly or not.</font>
		</font>
		<br />
		<font face="Verdana">
				<font size="-1">
						<br />
				</font>
		</font>
		<hr style="WIDTH: 100%; HEIGHT: 2px" />
		<font face="Verdana">
				<font size="-1">
						<br />    I was unsure whether to post this under GDI or WTL, but WTL won out since I was using CScrollImpl when I encountered this problem. On one of the views in my WTL program, I was creating controls dynamically on the output screen. This worked fine until the controls I was creating extended beyond the range of the viewport. When I kept using the same RECT coordinates for the created controls in the scrolled view, I started having all sorts of positioning and resizing problems.</font>
		</font>
		<br />
		<font face="Verdana">
				<font size="-1">    Turns out that Create assumes that the RECT coordinates you specify in the call are from the <i>top of the viewport, not the top of the window. </i>This was not at all intuitive to me. Consequently, if you want to keep a common coordinate system when creating controls on a scrolling view, you must either 1) factor in the scroll bar offset yourself, or 2) scroll back to the top left of the window (without updating), place your controls and then scroll back to the proper position.</font>
		</font>
		<font face="Verdana">
				<font size="-1">
				</font>
		</font>
		<p>
		</p>
		<font face="Verdana">
				<font size="-1">    By default, the COM Server code that the WTL AppWizard adds does not have the _Module.RegisterServer function set to TRUE by default. As a result, the type library information never showed up in the registry. A <a href="http://discuss.microsoft.com/SCRIPTS/WA-MSD.EXE?A2=ind9708D&amp;L=ATL&amp;D=0&amp;m=2723&amp;P=8742">message</a> in the ATL Archives relayed the answer to this problem.</font>
		</font>
		<p>
				<font face="Verdana">
						<font size="-1">    After trying to use extended combo boxes within a WTL app and not getting them to load, I knew I must be doing something wrong. I was initializing them with ::InitCommonControlsEx() in OnInitDialog(), which was a little too late. I moved them to DllMain, and that solved the problem. (The Microsoft <a href="http://discuss.microsoft.com/archives/atl.html">ATL mailing list archives</a> saved the day ...)</font>
				</font>
		</p>
		<p>
				<font face="Verdana">
						<font size="-1">    I was trying to modify a WTL frame window by using ModifyStyle in OnCreate(). WTL doesn't like this very well. Instead I discovered that I got the results I was looking for by modifying CFrameWindowImpl to take a customized version of CWinTraits by adding it to the template definition. By the way, this also works for CWindowImpl, which is where I found this trick in the MSDN docs and ATL Internals. Also, this link shows another <a href="http://discuss.microsoft.com/SCRIPTS/WA-MSD.EXE?A2=ind0005A&amp;L=ATL&amp;P=R18857">tricky portion</a> of the whole process.</font>
				</font>
		</p>
		<p>
				<font face="Verdana">
						<font size="-1">    Steps to use CDialogResize (from WTL 3.1):</font>
				</font>
				<br />
				<font face="Verdana">
						<font size="-1">    1) #include &lt;atlframe.h&gt; in your view/dialog class</font>
				</font>
				<br />
				<font face="Verdana">
						<font size="-1">    2) derive your view/dialog from CDialogResize:</font>
				</font>
				<br />
				<font face="Verdana">
						<font size="-1">        class CMyClass: public CDialogImpl&lt;CMyClass&gt;, ....</font>
				</font>
				<br />
				<font face="Verdana">
						<font size="-1">                              public CDialogResize&lt;CMyClass&gt;</font>
				</font>
				<br />
				<font face="Verdana">
						<font size="-1">    3) Add a DLGRESIZE_MAP to your view as follows:</font>
				</font>
				<br />
				<font face="Verdana">
						<font size="-1">         BEGIN_DLGRESIZE_MAP(CMyClass)</font>
				</font>
				<br />
				<font face="Verdana">
						<font size="-1">              DLGRESIZE_CONTROL(IDOK, DLSZ_MOVE_X | DLSZ_SIZE_Y)</font>
				</font>
				<br />
				<font face="Verdana">
						<font size="-1">        END_DLGRESIZE_MAP()</font>
				</font>
				<br />
				<font face="Verdana">
						<font size="-1">        The first parameter in the DLGRESIZE_CONTROL macro is the resource ID of your control. The second parameter(s) is the way that you want that control to be resized; valid values are DLSZ_MOVE_X, DLSZ_MOVE_Y, DLSZ_SIZE_X, DLSZ_SIZE_Y. (Note that you can OR these together with a |). You can also resize controls as a group by enclosing a number of DLGRESIZE_CONTROL macros with BEGIN_DLGRESIZE_GROUP() and END_DLGRESIZE_GROUP(). More on grouping in the next tip.</font>
				</font>
				<br />
				<font face="Verdana">
						<font size="-1">    4) Chain your message map to CDialogResize, i.e.</font>
				</font>
				<br />
				<font face="Verdana">
						<font size="-1">            BEGIN_MSG_MAP(CMyClass)</font>
				</font>
				<br />
				<font face="Verdana">
						<font size="-1">                ....</font>
				</font>
				<br />
				<font face="Verdana">
						<font size="-1">                CHAIN_MSG_MAP(CDialogResize&lt;CMyClass&gt;)</font>
				</font>
				<br />
				<font face="Verdana">
						<font size="-1">            END_MSG_MAP()</font>
				</font>
				<br />
				<font face="Verdana">
						<font size="-1">    5) Initialize the resizing for your view with DlgResize_Init(false, true, WS_CLIPCHILDREN) in OnInitDialog. Normally (for standard dialogs) you would just use DlgResize_Init() and accept the default parameters, but for a view you have to supply the extra settings since the view doesn't need a gripper or a frame like a dialog would.</font>
				</font>
		</p>
		<p>  <font face="Verdana"><font size="-1">Some things I've noticed about grouping controls with CDialogResize:</font></font><br /><font face="Verdana"><font size="-1">   1) You can group controls in one direction and leave them ungrouped in another direction to achieve good effects.</font></font><br /><font face="Verdana"><font size="-1">        For instance, if you had Save, Print and Close buttons running along the bottom of your dialog, centered and spaced evenly apart, you'd probably want to do this grouping:</font></font><br /><font face="Verdana"><font size="-1">       BEGIN_DLGRESIZE_MAP(CMyClass)</font></font><br /><font face="Verdana"><font size="-1">            BEGIN_DLGRESIZE_GROUP()</font></font><br /><font face="Verdana"><font size="-1">                DLGRESIZE_CONTROL(IDC_BTN_SAVE, DLSZ_MOVE_X )</font></font><br /><font face="Verdana"><font size="-1">                DLGRESIZE_CONTROL(IDC_BTN_PRINT, DLSZ_MOVE_X )</font></font><br /><font face="Verdana"><font size="-1">                DLGRESIZE_CONTROL(IDC_BTN_CLOSE, DLSZ_MOVE_X)</font></font><br /><font face="Verdana"><font size="-1">            END_DLGRESIZE_GROUP()</font></font><br /><font face="Verdana"><font size="-1">            DLGRESIZE_CONTROL(IDC_BTN_SAVE, DLSZ_MOVE_Y)</font></font><br /><font face="Verdana"><font size="-1">            DLGRESIZE_CONTROL(IDC_BTN_PRINT, DLSZ_MOVE_Y)</font></font><br /><font face="Verdana"><font size="-1">            DLGRESIZE_CONTROL(IDC_BTN_CLOSE, DLSZ_MOVE_Y)</font></font><br /><font face="Verdana"><font size="-1">       END_DLGRESIZE_MAP()</font></font></p>
		<p>
				<font face="Verdana">
						<font size="-1">       This would keep all of them centered and spaced evenly as you moved them, while also moving them up and down independently.</font>
				</font>
		</p>
		<p>
				<font face="Verdana">
						<font size="-1">    2) As soon as you noticed this little trick, however, you might start to take notice that your buttons don't <i>exactly</i> line up with the other controls on screen. You'd see this as the dialog was sized larger and larger. What's happening is that the leftmost button in the resource (this doesn't mean the top one in the DLGRESIZE_GROUP -- it's unrelated) is acting as an anchor for all the other buttons in the group. <i>So </i>when you resize the dialog, the leftmost button isn't moving ... it's just staying in place.</font>
				</font>
				<br />
				<font face="Verdana">
						<font size="-1">    There may be better ways to solve this problem, but what I did is insert a new invisible button on the resource in the leftmost position to act as the anchor. I then included the button in the DLGRESIZE_GROUP with a DLSZ_MOVE_X command as well so it would make all the other three buttons move together correctly. Like I said -- it works. If you stumble on something better</font>
				</font>
		</p>
<img src ="http://www.cppblog.com/eday/aggbug/17754.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/eday/" target="_blank">松*</a> 2007-01-18 16:23 <a href="http://www.cppblog.com/eday/archive/2007/01/18/17754.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WTL体系结构</title><link>http://www.cppblog.com/eday/archive/2007/01/18/17742.html</link><dc:creator>松*</dc:creator><author>松*</author><pubDate>Thu, 18 Jan 2007 01:49:00 GMT</pubDate><guid>http://www.cppblog.com/eday/archive/2007/01/18/17742.html</guid><description><![CDATA[
		<span style="FONT-WEIGHT: 700; FONT-FAMILY: 宋体">
				<font color="#ff6600" size="5">绪论</font>
		</span>
		<p class="MsoNormal">
				<span lang="zh-cn">     </span>
				<font face="宋体">
						<span lang="EN-US">WTL</span>
				</font>
				<span style="FONT-FAMILY: 宋体">最终来了</span>
				<font face="宋体">
						<span lang="EN-US">,</span>
				</font>
				<span lang="zh-cn" style="FONT-FAMILY: 宋体">而且</span>
				<span style="FONT-FAMILY: 宋体">提供了我所希望的功能</span>
				<font face="宋体">
						<span lang="EN-US">.</span>
				</font>
				<span style="FONT-FAMILY: 宋体">我在</span>
				<font face="宋体">
						<span lang="EN-US">
								<a href="http://www.idevresource.com/com/library/bytesize/wtl.asp">WTL Bytesize</a>
						</span>
				</font>
				<span style="FONT-FAMILY: 宋体">
						<span lang="zh-cn">(<a href="http://www.csdn.net/develop/Read_Article.asp?Id=19178">译文</a>)</span>的文章列出</span>
				<font face="宋体">
						<span lang="EN-US">WTL</span>
				</font>
				<span style="FONT-FAMILY: 宋体">主要特征</span>
				<font face="宋体">
						<span lang="EN-US">.</span>
				</font>
				<span style="FONT-FAMILY: 宋体">在本文中</span>
				<font face="宋体">
						<span lang="EN-US">,</span>
				</font>
				<span style="FONT-FAMILY: 宋体">我将描述一下</span>
				<font face="宋体">
						<span lang="EN-US">WTL</span>
				</font>
				<span style="FONT-FAMILY: 宋体">的体系结构</span>
				<font face="宋体">
						<span lang="EN-US">,</span>
				</font>
				<span style="FONT-FAMILY: 宋体">同时我会给出一些简单的例子来演示如何使用它的那些特征</span>
				<font face="宋体">
						<span lang="EN-US">.</span>
				</font>
				<span style="FONT-FAMILY: 宋体">希望能够对您有<span lang="zh-cn">所帮助</span></span>
				<font face="宋体">
						<span lang="EN-US">.</span>
				</font>
				<span lang="EN-US"> </span>
		</p>
		<p class="MsoNormal">
				<font color="#ff6600">
						<b>
								<font face="宋体">
										<span lang="EN-US">
												<font size="5">WTL</font>
										</span>
								</font>
								<span style="FONT-FAMILY: 宋体">
										<font size="5">应用程序的类型</font>
								</span>
						</b>
				</font>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="zh-cn">     </span>
				<span lang="EN-US">WTL</span>
				<span style="FONT-FAMILY: 宋体">有好几种应用程序类型</span>
				<span lang="EN-US">,</span>
				<span style="FONT-FAMILY: 宋体">供您在</span>
				<span lang="EN-US">AppWizard</span>
				<span style="FONT-FAMILY: 宋体">选取</span>
				<span lang="EN-US">.</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US">
				</span>
		</p>
		<p class="MsoNormal" align="center">
				<span lang="EN-US">
						<?xml:namespace prefix = v /?>
						<v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
								<v:stroke joinstyle="miter">
								</v:stroke>
								<v:formulas>
										<v:f eqn="if lineDrawn pixelLineWidth 0">
										</v:f>
										<v:f eqn="sum @0 1 0">
										</v:f>
										<v:f eqn="sum 0 0 @1">
										</v:f>
										<v:f eqn="prod @2 1 2">
										</v:f>
										<v:f eqn="prod @3 21600 pixelWidth">
										</v:f>
										<v:f eqn="prod @3 21600 pixelHeight">
										</v:f>
										<v:f eqn="sum @0 0 1">
										</v:f>
										<v:f eqn="prod @6 1 2">
										</v:f>
										<v:f eqn="prod @7 21600 pixelWidth">
										</v:f>
										<v:f eqn="sum @8 21600 0">
										</v:f>
										<v:f eqn="prod @7 21600 pixelHeight">
										</v:f>
										<v:f eqn="sum @10 21600 0">
										</v:f>
								</v:formulas>
								<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect">
								</v:path>
								<?xml:namespace prefix = o /?>
								<o:lock v:ext="edit" aspectratio="t">
								</o:lock>
						</v:shapetype>
				</span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">
						<span lang="zh-cn">
								<img src="http://www.cppblog.com/images/cppblog_com/eday/2991/r_wtl_wizard1.JPG" />
								<br />
								<br />    </span>下表对这些应用程序进行了描述</span>
				<span lang="EN-US">. </span>
				<span style="FONT-FAMILY: 宋体">这种弹性构成了</span>
				<span lang="EN-US">WTL</span>
				<span style="FONT-FAMILY: 宋体">体系结构的一部分</span>
				<span lang="EN-US">.</span>
		</p>
		<div align="center">
				<table class="MsoNormalTable" style="WIDTH: 426pt" cellspacing="1" cellpadding="0" width="568" border="1">
						<tbody>
								<tr>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 25%; PADDING-TOP: 5.25pt" valign="top" width="25%">
												<span style="FONT-FAMILY: 宋体">应用程序类型</span>
										</td>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 75%; PADDING-TOP: 5.25pt" valign="top" width="75%">
												<span style="FONT-FAMILY: 宋体">描述</span>
										</td>
								</tr>
								<tr>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 25%; PADDING-TOP: 5.25pt" valign="top" width="25%">
												<span lang="EN-GB">SDI Application</span>
										</td>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 75%; PADDING-TOP: 5.25pt" valign="top" width="75%">
												<span style="FONT-FAMILY: 宋体">单文本界面</span>
												<span lang="EN-GB">– </span>
												<span style="FONT-FAMILY: 宋体">只有一个窗口</span>
										</td>
								</tr>
								<tr>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 25%; PADDING-TOP: 5.25pt" valign="top" width="25%">
												<span lang="EN-GB">Multiple Threads SDI</span>
										</td>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 75%; PADDING-TOP: 5.25pt" valign="top" width="75%">
												<span style="FONT-FAMILY: 宋体">单个进程拥有一个或多个窗口</span>
										</td>
								</tr>
								<tr>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 25%; PADDING-TOP: 5.25pt" valign="top" width="25%">
												<span lang="EN-GB">MDI Application</span>
										</td>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 75%; PADDING-TOP: 5.25pt" valign="top" width="75%">
												<span style="FONT-FAMILY: 宋体">多文本界面</span>
												<span lang="EN-GB">– </span>
												<span style="FONT-FAMILY: 宋体">在框架内</span>
												<span lang="EN-GB">,</span>
												<span style="FONT-FAMILY: 宋体">您可以有零个或多个子窗口</span>
										</td>
								</tr>
								<tr>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 25%; PADDING-TOP: 5.25pt" valign="top" width="25%">
												<span lang="EN-GB">Dialog Based</span>
										</td>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 75%; PADDING-TOP: 5.25pt" valign="top" width="75%">
												<span style="FONT-FAMILY: 宋体">基于对话框模版</span>
										</td>
								</tr>
						</tbody>
				</table>
		</div>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">
						<span lang="zh-cn">    </span>你可能还是首次听说多线程<span lang="EN-US">SDI应用程序,但是不用担心,它的概念很容易理解.一个多线程SDI程序启动后它会有一个窗口, 窗口显示了一个文档. 当你想要程序要再创建一个文档时,问题就出现了--SDI程序只能显示一个文档.为了解决这个问题,多线程SDI创建了另一个SDI窗口.看起来是一个新的实例在运行,实际上它不过是原来的进程创建了一个新的窗口,并把它依附到进程的一个新线程. IE的新建窗口就是这样做的.</span></span>
				<span lang="EN-US" style="FONT-FAMILY: 宋体"> </span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">
						<span lang="zh-cn">    </span>除了多线程<span lang="EN-US">SDI,所有这些应用程序都可以作为COM服务器, 并且应用程序向导(AppWizard)为此提供了一个选项.另外应用程序向导还可以让你指定该程序是否主持ActiveX控件.令人费解的是,不同的程序类型,选取"Host ActiveX Controls"的地方不同.除对话框应用程序外的其他类型在第一页上选取,而对话框类型却放到第二页.</span></span>
				<span lang="EN-US" style="FONT-FAMILY: 宋体"> </span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">
						<span lang="zh-cn">    </span>第二页的其他选项<span lang="EN-US">,对对话框程序以外的类型都是可用的.它们让你指定程序是否需要工具条(toolbar),状态条(status bar)和视窗口(View Window).</span></span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">
						<span lang="EN-US">
						</span>
				</span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">
						<span lang="EN-US">
						</span>
				</span>
				<span style="FONT-FAMILY: 宋体">
						<span lang="EN-US">
								<img src="http://www.cppblog.com/images/cppblog_com/eday/2991/r_wtl_wizard2.JPG" />
								<br />
								<br />    如果选取了"Toolbar"选项,你可以通过"Rebar"选择是否将工具条放入IE Rebar控件中. 如果你选取了Rebar, 你就可以通过框架窗口(frame window)的成员m_hWndToolBar(后边会有详细的描述)来访问它.你可以按照你的意愿,在里边加入其他的工具条. 选取了"Rebar"后, 你可以决定是否选取"Command Bar".</span>
				</span>
				<span lang="EN-US" style="FONT-FAMILY: 宋体">Command bar很像CE的command bar控件.只是WTL是用一个类来实现,而在CE, command bar是一个系统窗口类(system window class). Command bar非常有用,它能够把窗口也加入到工具条中去. 如果你选取了这个选项, 工具条和菜单都将被当做toolbar来实现.这使菜单项也可以有关联的图标,并且当你移动鼠标到一个菜单项上时,该菜单项会被置成高亮.从Office 97以来, Office软件的菜单都具有上述特征.</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: PMingLiU"> </span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">    第二页还有指定程序是否使用视的选项<span lang="EN-US">(多半你想要使用), 同时你可以决定这些视如何实现. 下表列出了所有可选的视.</span></span>
				<font face="宋体">
						<span lang="EN-US"> </span>
				</font>
		</p>
		<div align="center">
				<table class="MsoNormalTable" style="WIDTH: 442.5pt" cellspacing="1" cellpadding="0" width="590" border="1">
						<tbody>
								<tr>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 20%; PADDING-TOP: 5.25pt" valign="top" width="20%">
												<span style="FONT-FAMILY: 宋体">视</span>
										</td>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 80%; PADDING-TOP: 5.25pt" valign="top" width="80%">
												<span style="FONT-FAMILY: 宋体">描述</span>
										</td>
								</tr>
								<tr>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 20%; PADDING-TOP: 5.25pt" valign="top" width="20%">
												<span lang="EN-GB">Generic Window</span>
										</td>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 80%; PADDING-TOP: 5.25pt" valign="top" width="80%">
												<span style="FONT-FAMILY: 宋体">一个简单的窗口</span>
												<span lang="EN-GB">. </span>
												<span style="FONT-FAMILY: 宋体">此类窗口允许程序员编写</span>
												<span lang="EN-GB">WM_PAINT</span>
												<span style="FONT-FAMILY: 宋体">消息的处理函数</span>
												<span lang="EN-GB">. </span>
												<span style="FONT-FAMILY: 宋体">适用于需要直接进行</span>
												<span lang="EN-GB">paint</span>
												<span style="FONT-FAMILY: 宋体">的文档</span>
												<span lang="EN-GB">.</span>
										</td>
								</tr>
								<tr>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 20%; PADDING-TOP: 5.25pt" valign="top" width="20%">
												<span lang="EN-GB">Form</span>
										</td>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 80%; PADDING-TOP: 5.25pt" valign="top" width="80%">
												<span style="FONT-FAMILY: 宋体">这类视具有一个对话框模版</span>
												<span lang="EN-GB">.</span>
												<span style="FONT-FAMILY: 宋体">适用于带</span>
												<span lang="EN-GB">ActiveX </span>
												<span style="FONT-FAMILY: 宋体">控件的窗口</span>
												<span lang="EN-GB">. </span>
												<span style="FONT-FAMILY: 宋体">应用程序来操作这些控件</span>
												<span lang="EN-GB">.</span>
										</td>
								</tr>
								<tr>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 20%; PADDING-TOP: 5.25pt" valign="top" width="20%">
												<span lang="EN-GB">List Box</span>
										</td>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 80%; PADDING-TOP: 5.25pt" valign="top" width="80%">
												<span style="FONT-FAMILY: 宋体">这个视是个</span>
												<span lang="EN-GB">list box.</span>
												<span style="FONT-FAMILY: 宋体">它最简单的形式意味着可以通过调用</span>
												<span class="codeintext1">
														<span lang="EN-GB">AddString()</span>
												</span>
												<span lang="EN-GB">
												</span>
												<span style="FONT-FAMILY: 宋体">方法来添加字符串</span>
												<span lang="EN-GB">.</span>
										</td>
								</tr>
								<tr>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 20%; PADDING-TOP: 5.25pt" valign="top" width="20%">
												<span lang="EN-GB">Edit</span>
										</td>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 80%; PADDING-TOP: 5.25pt" valign="top" width="80%">
												<span style="FONT-FAMILY: 宋体">这个视是个</span>
												<span lang="EN-GB">edit control. </span>
												<span style="FONT-FAMILY: 宋体">本质上</span>
												<span lang="EN-GB">,</span>
												<span style="FONT-FAMILY: 宋体">它提供了一个像</span>
												<span lang="EN-GB">Notepad</span>
												<span style="FONT-FAMILY: 宋体">一样的程序</span>
												<span lang="EN-GB">.</span>
										</td>
								</tr>
								<tr>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 20%; PADDING-TOP: 5.25pt" valign="top" width="20%">
												<span lang="EN-GB">List View</span>
										</td>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 80%; PADDING-TOP: 5.25pt" valign="top" width="80%">
												<span style="FONT-FAMILY: 宋体">这个视是个</span>
												<span lang="EN-GB">list view </span>
												<span style="FONT-FAMILY: 宋体">通用控件</span>
												<span lang="EN-GB">.</span>
												<span style="FONT-FAMILY: 宋体">用这个控件来显示相关的项</span>
												<span lang="EN-GB">(</span>
												<span style="FONT-FAMILY: 宋体">比如</span>
												<span lang="EN-GB">, </span>
												<span style="FONT-FAMILY: 宋体">控制面板是一个</span>
												<span lang="EN-GB">Explorer</span>
												<span style="FONT-FAMILY: 宋体">主持的</span>
												<span lang="EN-GB">List View, </span>
												<span style="FONT-FAMILY: 宋体">所有的项都是控制面板</span>
												<span lang="EN-GB">applet).</span>
										</td>
								</tr>
								<tr>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 20%; PADDING-TOP: 5.25pt" valign="top" width="20%">
												<span lang="EN-GB">Tree View</span>
										</td>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 80%; PADDING-TOP: 5.25pt" valign="top" width="80%">
												<span style="FONT-FAMILY: 宋体">这个视是个</span>
												<span lang="EN-GB">tree view </span>
												<span style="FONT-FAMILY: 宋体">通用控件</span>
												<span lang="EN-GB">. </span>
												<span style="FONT-FAMILY: 宋体">这个适用于具有层次关系的数据</span>
												<span lang="EN-GB">,</span>
												<span style="FONT-FAMILY: 宋体">比如</span>
												<span lang="EN-GB">,</span>
												<span style="FONT-FAMILY: 宋体">可以用它来显示数据库的</span>
												<span lang="EN-GB">schema. </span>
												<span style="FONT-FAMILY: 宋体">顶层分支为表和存储过程</span>
												<span lang="EN-GB">,</span>
												<span style="FONT-FAMILY: 宋体">次级的分支为表中的字段</span>
												<span lang="EN-GB">.</span>
										</td>
								</tr>
								<tr>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 20%; PADDING-TOP: 5.25pt" valign="top" width="20%">
												<span lang="EN-GB">Rich Edit</span>
										</td>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 80%; PADDING-TOP: 5.25pt" valign="top" width="80%">
												<span style="FONT-FAMILY: 宋体">这个视是个</span>
												<span lang="EN-GB">rich edit </span>
												<span style="FONT-FAMILY: 宋体">控件</span>
												<span lang="EN-GB">,</span>
												<span style="FONT-FAMILY: 宋体">像</span>
												<span lang="EN-GB">WordPad.</span>
										</td>
								</tr>
								<tr>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 20%; PADDING-TOP: 5.25pt" valign="top" width="20%">
												<span lang="EN-GB">HTML Page</span>
										</td>
										<td style="PADDING-RIGHT: 5.25pt; PADDING-LEFT: 5.25pt; PADDING-BOTTOM: 5.25pt; WIDTH: 80%; PADDING-TOP: 5.25pt" valign="top" width="80%">
												<span style="FONT-FAMILY: 宋体">这个视主持了一个</span>
												<span lang="EN-GB">IE Web Browser </span>
												<span style="FONT-FAMILY: 宋体">控件</span>
												<span lang="EN-GB">. </span>
												<span style="FONT-FAMILY: 宋体">它把主持的一个</span>
												<span lang="EN-GB">web page</span>
												<span style="FONT-FAMILY: 宋体">当成一个视</span>
												<span lang="EN-GB">.</span>
										</td>
								</tr>
						</tbody>
				</table>
		</div>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">    本文的例子需要一个对话框模版</span>
				<span lang="EN-US">,</span>
				<span style="FONT-FAMILY: 宋体">同时还需要菜单</span>
				<span lang="EN-US">,</span>
				<span style="FONT-FAMILY: 宋体">因此</span>
				<span lang="EN-US">Form view</span>
				<span style="FONT-FAMILY: 宋体">是个理想的选择</span>
				<span lang="EN-US">.<br /><br /></span>
		</p>
		<p>
				<b>
						<font color="#ff6600" size="5">程序线程</font>
				</b>
		</p>
		<p>    跟ATL一样,WTL程序也需要一个<font face="Courier New"><b>_Module</b></font>全局变量来保存全局数据,方便应用级代码访问.在WTL中,这个变量是<font face="Courier New"><b>CAppModule</b></font>或<font face="Courier New"><b>CServerAppModule</b></font>的实例,后者在程序同时作为一个COM服务器时用到.每个应用程序具有一个或者多个UI线程.WTL使用两种方式来管理这些线程.<br /><br />    如果应用程序只有一个UI线程(除了多线程SDI以外,其他程序类型默认只有一个UI线程),线程调用全局函数<b><font face="Courier New">run()</font></b>:</p>
		<p>
				<font face="Fixedsys">int Run(LPTSTR <font color="#008000">/*lpstrCmdLine*/ </font>= NULL, int nCmdShow = SW_SHOWDEFAULT)<br />{<br />    CMessageLoop theLoop;<br />    _Module.AddMessageLoop(&amp;theLoop);<br />    CMainFrame wndMain;<br />    if (wndMain.CreateEx() == NULL)<br />    {<br />        ATLTRACE(_T("Main window creation failed!\n"));<br />        return 0;<br />    }<br />    wndMain.ShowWindow(nCmdShow);<br />    int nRet = theLoop.Run();<br />    _Module.RemoveMessageLoop();<br />    return nRet;<br />}</font>
		</p>
		<p>    线程的消息循环包含在<b><font face="Courier New">CMessageLoop</font></b>内部.函数创建了一个<b><font face="Courier New">CMessageLoop</font></b>实例, 把它放入全局的消息循环映射(message loop map)数组. 以线程ID为索引,线程中运行的其他的代码可以访问到这个实例. 消息循环对象包含了message filter和idle handler. 运行在这个UI线程的UI元件(UI element)可以有它自己的idle handler,在线程的消息队列为空时运行<font face="宋体">【</font>译注:通过<b><font face="Courier New">CMessageLoop::AddIdleHandler()</font></b>把这个UI元件加入到<b><font face="Courier New">CMessageLoop</font></b>的idle handler 数组中<font face="宋体">】</font>.<b><font face="Courier New"> CMessageLoop::Run()</font></b>包含了UI线程的主消息映射(main message map).下边是它的伪代码:<br /><br /><font face="Fixedsys">MSG m_msg;<br />int CMessageLoop::Run()<br />{<br />    for (;;)<br />    {<br />        while (!::PeekMessage(&amp;m_msg, NULL, 0, 0, PM_NOREMOVE))<br />            DoIdleHandlers();<br />        bRet = ::GetMessage(&amp;m_msg, NULL, 0, 0);<br />        if(bRet == -1)<br />            continue; <br />        else if(!bRet)<br />            break;<br />        if (!DoMessageFilters(&amp;m_msg))<br />        {<br />            ::TranslateMessage(&amp;m_msg);<br />            ::DispatchMessage(&amp;m_msg);<br />        }<br />    }<br />    return (int)m_msg.wParam;<br />}</font><br /><br />    可以看到,这个函数推动着消息队列. 没有消息时, 运行注册到线程的idle hander. 如果在队列中检测到消息,把它取出来,传给每个message filter. 如果消息没有被这些函数处理,它将按照通常的方式,发送到目标窗口.<br /><br />    如果程序有超过一个的UI线程,可以用WTL的线程管理器,多线程SDI就是这样做的. 主线程作为一个管理者线程,它会为每个新窗口创建一个新的<span lang="zh-cn">新</span>线程. 主要流程如下:<br /><br /><font face="Fixedsys">int nRet = m_dwCount;<br />DWORD dwRet;<br />while(m_dwCount &gt; 0)<br />{<br /><span lang="zh-cn">    </span>dwRet = ::MsgWaitForMultipleObjects(m_dwCount, m_arrThreadHandles,<br /><span lang="zh-cn">        </span>FALSE, INFINITE, QS_ALLINPUT);<br /><span lang="zh-cn">    </span>if(dwRet &gt;= WAIT_OBJECT_0 &amp;&amp; dwRet &lt;= (WAIT_OBJECT_0 + m_dwCount - 1))<br /><span lang="zh-cn">        </span>RemoveThread(dwRet - WAIT_OBJECT_0);<br /><span lang="zh-cn">    </span>else if(dwRet == (WAIT_OBJECT_0 + m_dwCount))<br /><span lang="zh-cn">    </span>{<br /><span lang="zh-cn">        </span>::GetMessage(&amp;msg, NULL, 0, 0);<br /><span lang="zh-cn">        </span>if(msg.message == WM_USER)<br /><span lang="zh-cn">            </span>AddThread(_T(""), SW_SHOWNORMAL);<br /><span lang="zh-cn">    </span>}<br />}</font><br /><br />那些线程句柄放在一个数组中. 线程通过<b><font face="Courier New">AddThread()</font></b>加入到数组(同时启动线程), <b><font face="Courier New">RemoveThread()</font></b>从数组移走. wait语句在两种情况下会被打断: 线程死亡(将线程从数组中移出) 或线程收到了<b><font face="Courier New">WM_USER</font></b>消息(一个线程在一个新线程里新建了一个窗口). 线程管理者为程序中的一个类,因此可以在循环中加入自己的message handler, 比如,当程序有不止一种窗口类型时. 创建一个新的窗口非常简单,只需在任意一个窗口中调用:<br /><br />:<font face="Fixedsys">:PostThreadMessage(_Module.m_dwMainThreadID, WM_USER, 0, 0L);</font><br /><br />这个循环会一直运行下去,直到所有的UI线程都关闭了. UI线程具有一个thread procedure,它跟单UI线程的Run()方法一样.不过,由于线程管理者使用了<b><font face="Courier New">MsgWaitForMultipleObjects()</font></b>, 这意味者最多只能有<b><font face="Courier New">MAXIMUM_WAIT_OBJECTS</font></b>-1个UI线程,这也意味着最多只能创建63个窗口. <br /><br /><b><font color="#ff6600" size="5">框架</font></b><br /><br /><span lang="zh-cn">    </span>WTL实际上是两类窗口: 框架窗口和视图窗口. 正如名字所暗示的那样, 框架窗口为窗口提供标题栏(caption bar)和边框,你的代码用它来处理工具条(tool bar)和菜单项命令.你看到的程序窗口实际上是视图窗口, 视图覆盖了框架窗口的客户区.客户区是指框架窗口没有被诸如状态条,工具条之类的修饰部件所遮挡的部分.<br /><br /><span lang="zh-cn">    </span>线程会创建主框架窗口的一个实例,创建视图的工作由主框架窗口的<font face="Courier New"><b>WM_CREATE</b></font>消息处理函数完成. 对于SDI程序来说,这个过程很简单. 把视图类的一个实例作为主框架类的一个成员,调用视图类的<b><font face="Courier New">Create()</font></b>方法即可.MDI程序稍微有些不同, MDI主框架窗口通过<b><font face="Courier New">CMDIFrameWindowImpl&lt;&gt;::CreateMDIClient()</font></b>建立一个名为<b><font face="Courier New">MDICLIENT</font></b>的窗口. 这个客户窗口将<font face="Courier New"><b>CMDIChildWindowImpl&lt;&gt;</b></font>窗口当做它的子窗口,子窗口有一个视图.这也反映了这么一个事实,MDI程序可以具有零个或者多个子窗口,每个都有边框和标题栏.<br /><br />框架窗口的OnCreate()很有意思,让我看看:<br /><br /><font face="Fixedsys">LRESULT OnCreate(UINT, WPARAM, LPARAM, BOOL&amp;)<br />{<br /><span lang="zh-cn">    </span><font color="#008000">// create command bar window</font><br /><span lang="zh-cn">    </span>HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault,<br /><span lang="zh-cn">        </span>NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);<br /><span lang="zh-cn">    </span><font color="#008000">// attach menu</font><br /><span lang="zh-cn">    </span>m_CmdBar.AttachMenu(GetMenu());<br /><span lang="zh-cn">    </span><font color="#008000">// load command bar images</font><br /><span lang="zh-cn">    </span>m_CmdBar.LoadImages(IDR_MAINFRAME);<br /><span lang="zh-cn">    </span><font color="#008000">// remove old menu</font><br /><span lang="zh-cn">    </span>SetMenu(NULL);<br /><span lang="zh-cn">    </span>HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME,<br /><span lang="zh-cn">        </span>FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);<br /><span lang="zh-cn">    </span>CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);<br /><span lang="zh-cn">    </span>AddSimpleReBarBand(hWndCmdBar);<br /><span lang="zh-cn">    </span>AddSimpleReBarBand(hWndToolBar, NULL, TRUE);<br /><span lang="zh-cn">    </span>CreateSimpleStatusBar();<br /><span lang="zh-cn">    </span>m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL,<br /><span lang="zh-cn">        </span>WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,<br /><span lang="zh-cn">        </span>WS_EX_CLIENTEDGE);<br /><span lang="zh-cn">    </span>UIAddToolBar(hWndToolBar);<br /><span lang="zh-cn">    </span>UISetCheck(ID_VIEW_TOOLBAR, 1);<br /><span lang="zh-cn">    </span>UISetCheck(ID_VIEW_STATUS_BAR, 1);<br /><span lang="zh-cn">    </span>CMessageLoop* pLoop = _Module.GetMessageLoop();<br /><span lang="zh-cn">    </span>pLoop-&gt;AddMessageFilter(this);<br /><span lang="zh-cn">    </span>pLoop-&gt;AddIdleHandler(this);<br /><span lang="zh-cn">    </span>return 0;<br />}</font><br /><span lang="zh-cn">    </span>这是从一个SDI程序拿来的一段代码,该程序有一个基于command bar的工具条和一个状态条. 函数的第一行创建了一个command bar实例,然后对它进行初始化,在其中加入框架窗口的菜单和工具条位图. 这段代码先将菜单取出,把所有的下拉菜单转换为工具条按钮,并将菜单保存在一个变量中<span lang="zh-cn">,</span>以备后用. 给人的感觉是菜单是由工具条实现的-那我们就把它叫做工具条菜单(menu toolbar)吧. 然后Command Bar将程序工具条的图标装入image list 并将它们的ID保存在数组中. 当点击工具条菜单的按钮时,commandbar会找到对应的子菜单,创建一个弹出菜单. Command bar将子菜单项的ID和它保存的ID进行比较,这些ID跟image list中的工具条按钮图标是相关联的. 如果比较成功, 则将关联的图标加到菜单项上去. 这意味着相同ID的菜单项和工具条按钮具有相同的图标.<br /><br />接下来, 创建工具条并把它关联到commandbar, 然后创建状态条和视图.可以看到视图的<b><font face="Courier New">HWND</font></b>存放在框架窗口的<font face="Courier New"><b>m_hWndClient</b></font>变量中. 这个窗口句柄在框架窗口的<b><font face="Courier New">WM_SIZE</font></b> handler中会用到.当框架窗口改变大小时,它告知视图改变自身,于此同时也要考虑状态条和command bar. <br /><br />在下来的三行(从调用<b><font face="Courier New">UIAddToolBar()</font></b>开始) 用来显示在运行时会改变状态的UI项(UI item).文章后面还会重提这个话题. 最后,访问消息循环(message loop), 你应该还记得该消息循环存放在一全局数组中.<b><font face="Courier New"><span lang="zh-cn"></span>GetMessageLoop()</font></b> 取得当前线程的消息循环,加入框架窗口的message filter和idle handler, 分别默认是<b><font face="Courier New">PreTranslateMessage()</font></b>和<b><font face="Courier New">OnIdle()</font></b>.<br /><br />框架窗口继承于以下类:<br /><br /><font face="Fixedsys">class CMainFrame : <br /><span lang="zh-cn">    </span>public CFrameWindowImpl&lt;CMainFrame&gt;, <br /><span lang="zh-cn">    </span>public CUpdateUI&lt;CMainFrame&gt;, <br /><span lang="zh-cn">    </span>public CMessageFilter, <br /><span lang="zh-cn">    </span>public CIdleHandler</font></p>
		<p>
				<br />后两个抽象类宣称了框架窗口类实现了<b><font face="Courier New">PreTranslateMessage()</font></b>和<b><font face="Courier New">OnIdle()</font></b>. 从<b><font face="Courier New">CUpdateUI&lt;&gt;</font></b>继承表示框架类支持UI update map.<br /><br /></p>
		<p>
				<b>
						<font color="#ff6600" size="5">视图</font>
				</b>
		</p>
		<p>视图窗口<span lang="zh-cn">看起来</span>显得很简单:</p>
		<p>
				<font face="Fixedsys">class CMyView : public CWindowImpl&lt;CMyView&gt;<br />{<br />public:<br /><span lang="zh-cn">    </span>DECLARE_WND_CLASS(NULL)<br /><span lang="zh-cn">    </span>BOOL PreTranslateMessage(MSG* pMsg)<br /><span lang="zh-cn">    </span>{<br /><span lang="zh-cn">    </span>    pMsg;<br /><span lang="zh-cn">        </span>return FALSE;<br /><span lang="zh-cn">    </span>}<br /><span lang="zh-cn">    </span>BEGIN_MSG_MAP(CMyView)<br /><span lang="zh-cn">        </span>MESSAGE_HANDLER(WM_PAINT, OnPaint)<br /><span lang="zh-cn">    </span>END_MSG_MAP()<br /><span lang="zh-cn">    </span>LRESULT OnPaint(UINT, WPARAM, LPARAM, BOOL&amp;)<br /><span lang="zh-cn">    </span>{<br /><span lang="zh-cn">        </span>CPaintDC dc(m_hWnd);<br /><span lang="zh-cn">        </span><font color="#008000">//TODO: Add your drawing code here</font><br /><span lang="zh-cn">        </span>return 0;<br /><span lang="zh-cn">    </span>}<br />};</font>
				<br />
				<br />上面<span lang="zh-cn">是</span>一个SDI程序的视图类. 多线程SDI和MDI的视图类在本质上也<span lang="zh-cn">跟这个</span>一样,但他们没有<b><font face="CourierPS">PreTranslateMessage()</font></b>方法. SDI程序就是使用这个函数,赶在框架类<span lang="zh-cn">处理消息</span>之前<span lang="zh-cn">把消息</span>抓住. <b><font face="CourierPS">PreTranslateMessage()</font></b>在SDI的框架类中的实现是<span lang="zh-cn">，</span>直接<span lang="zh-cn">将</span>消息转发给视图类. <br /><br />这里显示的视图实际上没有做什么工作.你应该<span lang="zh-cn">自己</span>在<b><font face="Courier New">OnPaint()</font></b>函数中加入画出文档<span lang="zh-cn">内容</span>的代码.如果<span lang="zh-cn">需</span>要支持输入,如鼠标的点击和键盘的按键,你应该加入<span lang="zh-cn">相应</span>消息处理函数到类和映射中. 可以看<span lang="zh-cn">到</span>这个窗口是从<font face="Courier New"><b>CWindowImpl</b>&lt;&gt;</font>继承下来的,如果你想让它基于一个Win32控件<span lang="zh-cn">的话</span>,就应该从定义在AtlCtrls.h<span lang="zh-cn">文件</span>中<span lang="zh-cn">某个</span>WTL类继承.<br /><br />如果想在基于<b><font face="Courier New">CWindowImpl&lt;&gt;</font></b>的类里加上滚动条,那么你应该把基类换成<b><font face="Courier New">CScrollWindowImpl&lt;&gt;</font></b>,同时把消息链给它:</p>
		<p>
				<font face="Fixedsys">class CMyView : public CScrollWindowImpl&lt;CMyView&gt;<br />{<br />public:<br /><span lang="zh-cn">    </span>typedef CScrollWindowImpl&lt;CMyView&gt; parent;<br /><span lang="zh-cn">    </span>BEGIN_MSG_MAP(CMyView)<br /><span lang="zh-cn">        </span>CHAIN_MSG_MAP(parent)<br /><span lang="zh-cn">    </span>END_MSG_MAP()<br /><span lang="zh-cn">    </span>void DoPaint(CDCHandle dc)<br /><span lang="zh-cn">    </span>{<br /><span lang="zh-cn">    </span>}<br />}<span lang="zh-cn">；</span><br /></font>
				<br />基类保证窗口具<span lang="zh-cn">备</span>滚动条,并提供滚动条消息的默认处理.视图类不再有<b><font face="Courier New">WM_PAINT</font></b>的处理函数,因为它<span lang="zh-cn">已</span>被<b><font face="Courier New">CScrollWindowImpl&lt;&gt;</font></b>处理.根据滚动条的位置,<b><font face="Courier New">CScrollWindowImpl&lt;&gt;</font></b>画出视图相对应的部分. 取而代之<span lang="zh-cn">的</span>是<span lang="zh-cn">，</span>在你的类里实现<b><font face="Courier New">DoPaint()</font></b>,在这里你需要画出<span lang="zh-cn">整</span>个视图.如果你<span lang="zh-cn">想</span>指定滚动的范围,大小或起点,你需要加上处理<b><font face="Courier New">WM_CREATE</font></b>消息的函数<span lang="zh-cn">，把这些初始化</span>代码放到里边.<br /><br />正如我先前<span lang="zh-cn">所</span>提到的,框架窗口会改变视图窗口的大小,以使它客户区未被状态条和工具条覆盖的部分为视图所填充. 在大多数情况下,<span lang="zh-cn">这样就够了</span>.但是当你想要一个具有Windows Explorer样子的程序时,该怎么办呢? Windows Explorer的窗口包含了一个tree view 和一个list view,还有两者之间的分割条. WTL的解决方案很简单:使用splitter窗口!<br /><br />为此你需要改变一下框架窗口,让它创建splitter窗口的一个实例作为它的视图. 例如, 在你的<span lang="zh-cn">框架</span>类里有如下的数据成员:<br /><br /><font face="Fixedsys">CSplitterWindow m_view;<br />CTreeViewCtrl m_tree;<br />CListViewCtrl m_list;</font><br /><br />你可以在<b><font face="Courier New">OnCreate()</font></b>创建一个splitter窗口:<br /><br /><font color="#008000">// get the frame client rect, so that we set the splitter initial size<br />// and we can get the splitter bar in the centre</font><br /><font face="Fixedsys">RECT rect;<br />GetClientRect(&amp;rect);<br />m_hWndClient = m_view.Create(m_hWnd, rect,<br /><span lang="zh-cn">    </span>NULL, WS_CHILD | WS_VISIBLE);<br />m_tree.Create(m_view, rcDefault, NULL,<br /><span lang="zh-cn">    </span>WS_CHILD | WS_VISIBLE | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT,<br /><span lang="zh-cn">    </span>WS_EX_CLIENTEDGE);<br />m_list.Create(m_view, rcDefault,<br /><span lang="zh-cn">    </span>NULL, WS_CHILD | WS_VISIBLE | LVS_REPORT, WS_EX_CLIENTEDGE);<br />m_view.SetSplitterPanes(m_tree, m_list);<br />m_view.SetSplitterPos();</font><br /><br />Splitter窗口如同一个视图,将框架窗口作为它的父窗口. 在这段代码里,我将框架窗口客户区的实际大小传给<span lang="zh-cn">了</span>splitter窗口. 我<span lang="zh-cn">也</span>可以在这里使用 <b>rcDefault</b>,因为一旦框架窗口<span lang="zh-cn">创建</span>完成,框架窗口<span lang="zh-cn">就</span>会转发<b><font face="Courier New">WM_SIZE</font></b>消息给splitter. 这样splitter<span lang="zh-cn">可以马上</span>改变自身的大小来填充框架. 然而,当我准备使用不<span lang="zh-cn">带</span>参数的<b><font face="Courier New">SetSplitterPos()</font></b>,把分割条设置于窗口中线时,出现了问题.Splitter窗口使用它的大小来决定中线的位置,由于<b>rcDefault</b>告诉窗口它的大小是0<span lang="zh-cn">(因此中线的位置也是0)</span>,从而意味着分割条将出现在<span lang="zh-cn">z最</span>左边,<span lang="zh-cn">将</span>左窗口隐藏了起来.<br /><br />创建了splitter窗口后,你需要创建那些你想要分割的窗口<span lang="zh-cn">了</span>.它们将作为splitter窗口的<span lang="zh-cn">子</span>窗口被创建.最后你将这些子窗口通过<b><font face="Courier New">SetSplitterPanes()</font></b>加到splitter窗口中去,并确定分割条的位置所在.<br /><br /><b><font color="#ff6600" size="5">UI Update</font></b><br /><br />菜单项可以被设置为有效或无效,可以<span lang="zh-cn">带</span>check记号或着像radio按钮一样,<span lang="zh-cn">在</span>一组<span lang="zh-cn">菜单</span>项中同时<span lang="zh-cn">有且</span>只有一个<span lang="zh-cn">能被</span>check.此外,菜单项还可以带图标和文字. 所有的这些状态都可以在运行时根据程序中的某个值进行改变.工具条在某种程度上可以看做是菜单的易见形态,因为它们的按钮可以个别地,或者作为一组的一部<span lang="zh-cn">分</span>被置成有效或无效,推入推出. UI update机制允许你指定哪些UI元件(UI element)的状态可以在运行时改变. WTL使用如下的UI update映射来实现这一功能:</p>
		<p>
				<br />
				<font face="Fixedsys">BEGIN_UPDATE_UI_MAP(CMainFrame)<br /><span lang="zh-cn">    </span>UPDATE_ELEMENT(ID_FILE_SAVERESULTS, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)<br /><span lang="zh-cn">    </span>UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP)<br /><span lang="zh-cn">    </span>UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP)<br />END_UPDATE_UI_MAP()<br /></font>
				<br />这个例子指出三个菜单项在运行时有一个状态需要显示,其中的一个, ID_FILE_SAVERESULTS,<span lang="zh-cn">还</span>有一个工具条按钮跟它相关联. WTL<span lang="zh-cn">通过</span>建立一个数组来保存这些信息.<span lang="zh-cn">为此</span>你需要<span lang="zh-cn">完成</span>两方面的工作<span lang="zh-cn">:</span></p>
		<p>首先是UI元件的状态. 如果是菜单项, 你可以使用<b><font face="Courier New">UIEnable()</font></b>使能该菜单项, <b><font face="Courier New">UISetCheck()</font></b>设置check记号, <b><font face="Courier New">UISetText()</font></b>改变菜单的文字.如果是工具条按钮,那么你使用<b><font face="Courier New">UIEnable()</font></b>使能该按钮, <b><font face="Courier New">UISetCheck()</font></b>或者<font face="Courier New">UISetRadio()</font>决定按钮是推入还是推出.下边的代码根据是否有文本被选中,来使能Cut菜单项和工具条按钮:<br /><br /><font face="Fixedsys">BOOL bSelected = GetSelected();<br />UIEnable(ID_EDIT_CUT, bSelected);</font><br /><br />你可以把这样的代码放入<span lang="zh-cn">相应</span>处理函数中(如一个菜单项<span lang="zh-cn">的状态</span>依赖于另一个菜单项的动作<span lang="zh-cn">,将它放入后者的处理函数中</span>),或者放入<font face="Courier New"><b>OnIdle()</b></font>方法,通过检查某个类变量来决定元件的状态.<br /><br />其次是确定各个UI元件<span lang="zh-cn">是否</span>都被更新了,为此你需要调用<font face="Courier New"><b>CUpdateUI&lt;&gt;</b><span lang="zh-cn">的某个</span></font>方法<span lang="zh-cn">将</span>UI元件<span lang="zh-cn">加入到列表中</span>.主菜单已<span lang="zh-cn">被</span>自动加入,但是其他的任何菜单和所有的工具条必须分别通过调用<b><font face="Courier New">UIAddMenuBar()</font></b>和<b><font face="Courier New">UIAddToolBar()</font></b><span lang="zh-cn">手动</span>加入.<br /><br /><span lang="zh-cn">其他</span>还有一堆事情要注意. 首先,设置了工具条的状态后,使用<b><font face="Courier New">UIUpdateToolBar()</font></b>以使工具条状态更新. 对于菜单,你不需如此,因为子菜单是动态生成的<font face="Courier New">.<b>UIUpdateMenuBar()</b></font>这个方法也存在,但是它<span lang="zh-cn">的作用</span>是把菜单恢复到初始状态,如果你改变过某些项的文字,<font face="宋体"><span lang="zh-cn">调用</span></font><b><font face="Courier New">UIUpdateMenuBar()</font></b>的结果可能不是你所<span lang="zh-cn">期望</span>的(因为菜单项的文字会变成<span lang="zh-cn">老</span>的). <br /><br />尽管还有一个方法<b><font face="Courier New">UISetRadio()</font></b>,但是<span lang="zh-cn">还</span>没有一个把几个菜单项或者工具条按钮当做radio按钮组(也就是说,有一个而且只有一个被选中)<span lang="zh-cn">的机制.</span>如果你希望得到这样<span lang="zh-cn">效果</span>,你必须自己编码,不过它并不难.<br /><br /></p>
		<p>
				<b>
						<font color="#ff9933" size="5">对话框</font>
						<font color="#ff6600" size="5">
								<br />
						</font>
				</b>
				<br />ATL的对话框支持一向很好,对此WTL新增了通用对话框的封装. 本质上是为对话框加入了输入验证和回调函数. 比如, 你想<span lang="zh-cn">在</span>用户<span lang="zh-cn">改变年O</span>pen对话框中<span lang="zh-cn">的文件夹时有所动作,</span>那么你应该从<font face="Courier New"><b>CFileDialogImpl<span lang="zh-cn">&lt;&gt;</span></b></font>继承一个类,实现<font face="Courier New"><b>OnFolderChange()</b></font>:</p>
		<p>
				<font face="Fixedsys">class CMyFileDialog : public CFileDialogImpl&lt;CMyFileDialog&gt;<br />{<br />public:<br /><span lang="zh-cn">    </span>CMyFileDialog(BOOL b) <br /><span lang="zh-cn">        </span>: CFileDialogImpl&lt;CMyFileDialog&gt;(b) { }<br /><span lang="zh-cn">    </span>void OnFolderChange(LPOFNOTIFY lpon)<br /><span lang="zh-cn">    </span>{<br /><span lang="zh-cn">        </span>char strFolder[MAX_PATH];<br /><span lang="zh-cn">        </span>if (GetFolderPath(strFolder, sizeof(strFolder)) &gt; 0)<br /><span lang="zh-cn">        </span>{<br /><span lang="zh-cn">            </span>MessageBox(strFolder);<br /><span lang="zh-cn">        </span>}<br /><span lang="zh-cn">    </span>}<br />};</font>
		</p>
		<p>当文件夹的路径改变时,<b><font face="Courier New">CFileDialogImpl&lt;&gt;</font></b>调用<b><font face="Courier New">OnFolderChange()</font></b>.该函数使用基类的<font face="Courier New"><b>GetFolderPath()</b></font>,来取得新路径.<br /><br /><b><font color="#ff9933" size="5">控件</font></b><br /><br />WTL为所有的Win32和通用控件提供了封装类<span lang="zh-cn">,</span>包括Windows 2000新加入的. 虽然只是简单的包装，但是它们使这些控件更加容易访问.譬如，你能记清楚从List View读出当前选定项的文字的消息和需要传的参数吗？(实际上, 你需要发送两个消息, 一个是得到选定项的索引，另一个是读出它的文字.) WTL的作者<span lang="zh-cn">为你</span>完成了这些烦人的工作, 提供了一个简单的封装函数供你使用.<br /><br />使用这些控件类有两种方法. 如果你的对话框里有一个控件, 你可以将控件的<font face="Courier New"><b>HWND</b></font>依附到一个封装对象,使用封装类的方法来访问控件<span lang="zh-cn">.</span>这种方法简化了你读写控件数据和处理<font face="Courier New"><b>notification</b></font>消息的代码. <br /><br />另外的用法是把这些类加到你的视图类的继承层次中去:<br /><br /><font face="Fixedsys">class CMyView : public CWindowImpl&lt;CMyView, CListBox&gt;<br /></font><br />这表示<font face="Courier New"><b>CWindowImpl&lt;&gt;</b></font>是<font face="宋体"><span lang="zh-cn">从</span></font><b><font face="Courier New">CListBox</font></b>继承而来,因此创建的窗口将是一个list box (因为窗口类的名字是通过调用 <br /><font face="Courier New"><b>CListBox::GetWndClassName()</b></font>得到<span lang="zh-cn">的</span>). 另外, ATL的窗口机制会子类化这个窗口,将发给它的消息路由到你的消息映射中去. 它保留了老的窗口函数,这样,你没有处理的消息将由老的窗口函数来处理.当你的视图类从控件类继承时,WTL就会使用这一技术.<br /><br />在notification消息和子类化这个主题上,有一点很值得指出,那就是当<span lang="zh-cn">某</span>事件发生时,绝大多数窗口控件都会发送notification消息给它们的父窗口.让你窗口来处理这些<font face="Courier New"><b>notification</b></font>消息要比子类化一个已存在控件窗口(或子类化一个已存在的类,然后建立一个实例),从而在控件之前取得消息好得多. 譬如, 你想处理按钮的click事件,你所需要做的只是处理<font face="Courier New"><b>BN_CLICKED</b></font><font face="Courier New"><b>notification</b></font>.它将由按钮发送给你的窗口类.另外的一种方法是从<b><font face="Courier New">CContainedWindow&lt;&gt;</font></b>子类化BUTTON窗口来处理<b><font face="Courier New">click</font></b>消息. <br /><br />我<span lang="zh-cn">之所以</span>说这个是因为一个知名的ATL鼓吹者给我一份代码里就是这么做的.他的代码取得一个简单的按钮<b><font face="Courier New">click</font></b>事件所花的<span lang="zh-cn">时间</span>是别人的3到4倍,因为他子类化了按钮控件,而不是简单的处理<font face="Courier New"><b>BN_CLICKED</b></font><font face="Courier New"><b>notification</b></font>.<br /><br />WTL还提供了一些新的控件,在win32中没有对等者. 你已经看到过一个<span lang="zh-cn"> -- </span>command bar, 实际上还有其他一些非常有用类:</p>
		<p>
		</p>
		<table cellspacing="1" cellpadding="7" width="638" align="center" border="1">
				<tbody>
						<tr>
								<td valign="top" width="34%" height="33">
										<span lang="zh-cn">类</span>
										<span lang="en">  </span>
								</td>
								<td valign="top" width="66%" height="33">
										<span lang="zh-cn">描述</span>
								</td>
						</tr>
						<tr>
								<td valign="top" width="34%" height="33">
										<span class="codeintext">CBitmapButton</span>
								</td>
								<td valign="top" width="66%" height="33">
										<span lang="zh-cn">这是一个用位图替代标题的按钮.你可以提供一个</span>image list<span lang="zh-cn">,里边包含按钮在正常状态,失效, 推入和鼠标落在按钮上的图表</span>.</td>
						</tr>
						<tr>
								<td valign="top" width="34%" height="33">
										<span class="codeintext">CHyperLink</span>
								</td>
								<td valign="top" width="66%" height="33">
										<span lang="zh-cn">让你建立一个static控件,它代表一个</span>hyperlink<span lang="zh-cn">,这样当用户点击它时,默认的web浏览器打开该链接</span>.</td>
						</tr>
						<tr>
								<td valign="top" width="34%" height="33">
										<span class="codeintext">CWaitCursor</span>
								</td>
								<td valign="top" width="66%" height="33">
										<span lang="zh-cn">这不过是在它的构造函数中把鼠标图标改成等待状态,而在析构函数中还原</span>.</td>
						</tr>
						<tr>
								<td valign="top" width="34%" height="33">
										<span class="codeintext">CCheckListViewCtrl</span>
								</td>
								<td valign="top" width="66%" height="33">
										<span lang="zh-cn">在每一项边上都有一个check box的</span>list box<span lang="zh-cn">.</span></td>
						</tr>
						<tr>
								<td valign="top" width="34%" height="33">
										<span class="codeintext">CMultiPaneStatusBarCtrl</span>
								</td>
								<td valign="top" width="66%" height="33">
										<span lang="zh-cn">具有多个pane的状态条</span>
								</td>
						</tr>
				</tbody>
		</table>
		<p>
				<span lang="zh-cn">
				</span> </p>
<img src ="http://www.cppblog.com/eday/aggbug/17742.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/eday/" target="_blank">松*</a> 2007-01-18 09:49 <a href="http://www.cppblog.com/eday/archive/2007/01/18/17742.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在VC8.0下安装boost出错</title><link>http://www.cppblog.com/eday/archive/2006/11/07/14764.html</link><dc:creator>松*</dc:creator><author>松*</author><pubDate>Mon, 06 Nov 2006 17:25:00 GMT</pubDate><guid>http://www.cppblog.com/eday/archive/2006/11/07/14764.html</guid><description><![CDATA[今天想安装boost，但在安装过程中总是出现<br><font color=#ff0000>MakDir1 bin<br>spawn: no such file or directory</font><br>在网上找了很多资料，内容到是挺多，但还是没能解决该问题，郁闷了一天，没办法再找，终于在国外的一个网站（<a href="http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?InstallingBoost%20">http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?InstallingBoost%20</a>?）上找到了答案，而且方法很简单：<br>不用设置在环境变量里添加 bjam 的路径，直接把编译好的 bjam.exe 拷贝到 \boost_1_33_1 目录下，然后在控制台执行:<br>&nbsp;&nbsp; <font color=#0000ff>bjam.exe "-sVC80_ROOT=C:\Program Files\Microsoft Visual Studio 8\VC" -sTOOLS=vc-8_0 install</font><br><br>安装成功!<br><br>至于之前为什么会失败，我也懒得去研究了。 
<img src ="http://www.cppblog.com/eday/aggbug/14764.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/eday/" target="_blank">松*</a> 2006-11-07 01:25 <a href="http://www.cppblog.com/eday/archive/2006/11/07/14764.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>