﻿<?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++博客-Impossible is nothing-文章分类-C++语言</title><link>http://www.cppblog.com/apollo/category/955.html</link><description>　　爱过知情重醉过知酒浓
　　花开花谢终是空
　　缘份不停留像春风来又走
　　女人如花花似梦</description><language>zh-cn</language><lastBuildDate>Tue, 20 May 2008 21:21:14 GMT</lastBuildDate><pubDate>Tue, 20 May 2008 21:21:14 GMT</pubDate><ttl>60</ttl><item><title>Effective C++</title><link>http://www.cppblog.com/apollo/articles/8128.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Sat, 03 Jun 2006 09:50:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/8128.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/8128.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/8128.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/8128.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/8128.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 导读																																																																										Introduction																																																																																				...&nbsp;&nbsp;<a href='http://www.cppblog.com/apollo/articles/8128.html'>阅读全文</a><img src ="http://www.cppblog.com/apollo/aggbug/8128.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-06-03 17:50 <a href="http://www.cppblog.com/apollo/articles/8128.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Essential C++读书笔记</title><link>http://www.cppblog.com/apollo/articles/8127.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Sat, 03 Jun 2006 09:47:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/8127.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/8127.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/8127.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/8127.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/8127.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 面向过程的编程风格																																										  Procedural Programming																																																																										1．  																							...&nbsp;&nbsp;<a href='http://www.cppblog.com/apollo/articles/8127.html'>阅读全文</a><img src ="http://www.cppblog.com/apollo/aggbug/8127.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-06-03 17:47 <a href="http://www.cppblog.com/apollo/articles/8127.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>深度探索c++的对象模型</title><link>http://www.cppblog.com/apollo/articles/8126.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Sat, 03 Jun 2006 09:42:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/8126.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/8126.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/8126.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/8126.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/8126.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Stanley																				 B. Lippman																										 																																										屋檐下的水滴														--读书笔记系列																	...&nbsp;&nbsp;<a href='http://www.cppblog.com/apollo/articles/8126.html'>阅读全文</a><img src ="http://www.cppblog.com/apollo/aggbug/8126.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-06-03 17:42 <a href="http://www.cppblog.com/apollo/articles/8126.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>理解复杂声明</title><link>http://www.cppblog.com/apollo/articles/5390.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Wed, 12 Apr 2006 06:52:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/5390.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/5390.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/5390.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/5390.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/5390.html</trackback:ping><description><![CDATA[
		<p>
				<br />typedef的妙用</p>
		<p>typedef给你一种方式来克服“*只适合于变量而不适合于类型”的弊端。你可以如下使用typedef：</p>
		<p>typedef char * PCHAR;<br />PCHAR p,q;</p>
		<p>这里的p和q都被声明为指针。（如果不使用typedef，q将被声明为一个char变量，这跟我们的第一眼感觉不太一致！）下面有一些使用typedef的声明，并且给出了解释：</p>
		<p>typedef char * a;  // a is a pointer to a char</p>
		<p>typedef a b();     // b is a function that returns<br />                   // a pointer to a char</p>
		<p>typedef b *c;      // c is a pointer to a function<br />                   // that returns a pointer to a char</p>
		<p>typedef c d();     // d is a function returning<br />                   // a pointer to a function<br />                   // that returns a pointer to a char</p>
		<p>typedef d *e;      // e is a pointer to a function <br />                   // returning  a pointer to a <br />                   // function that returns a <br />                   // pointer to a char</p>
		<p>e var[10];         // var is an array of 10 pointers to <br />                   // functions returning pointers to <br />                   // functions returning pointers to chars.</p>
		<p>typedef经常用在一个结构声明之前，如下。这样，当创建结构变量的时候，允许你不使用关键字struct（在C中，创建结构变量时要求使用struct关键字，如struct tagPOINT a；而在C++中，struct可以忽略，如tagPOINT b）。</p>
		<p>typedef struct tagPOINT<br />{<br />    int x;<br />    int y;<br />}POINT;</p>
		<p>POINT p; /* Valid C code */</p>
		<p> </p>
		<p>函数指针</p>
		<p>函数指针可能是最容易引起理解上的困惑的声明。函数指针在DOS时代写TSR程序时用得最多；在Win32和X-Windows时代，他们被用在需要回调函数的场合。当然，还有其它很多地方需要用到函数指针：虚函数表，STL中的一些模板，Win NT/2K/XP系统服务等。让我们来看一个函数指针的简单例子：</p>
		<p>int (*p)(char);</p>
		<p>这里p被声明为一个函数指针，这个函数带一个char类型的参数，并且有一个int类型的返回值。另外，带有两个float类型参数、返回值是char类型的指针的指针的函数指针可以声明如下：</p>
		<p>char ** (*p)(float, float);</p>
		<p>那么，带两个char类型的const指针参数、无返回值的函数指针又该如何声明呢？参考如下：</p>
		<p>void * (*a[5])(char * const, char * const);</p>
		<p> </p>
		<p>“右左法则”[重要！！！]</p>
		<p>The right-left rule: Start reading the declaration from the innermost parentheses, go right, and then go left. When you encounter parentheses, the direction should be reversed. Once everything in the parentheses has been parsed, jump out of it. Continue till the whole declaration has been parsed.</p>
		<p>这是一个简单的法则，但能让你准确理解所有的声明。这个法则运用如下：从最内部的括号开始阅读声明，向右看，然后向左看。当你碰到一个括号时就调转阅读的方向。括号内的所有内容都分析完毕就跳出括号的范围。这样继续，直到整个声明都被分析完毕。</p>
		<p>对上述“右左法则”做一个小小的修正：当你第一次开始阅读声明的时候，你必须从变量名开始，而不是从最内部的括号。</p>
		<p>下面结合例子来演示一下“右左法则”的使用。</p>
		<p>int * (* (*fp1) (int) ) [10];</p>
		<p>阅读步骤：<br />1. 从变量名开始 -------------------------------------------- fp1<br />2. 往右看，什么也没有，碰到了)，因此往左看，碰到一个* ------ 一个指针<br />3. 跳出括号，碰到了(int) ----------------------------------- 一个带一个int参数的函数<br />4. 向左看，发现一个* --------------------------------------- （函数）返回一个指针<br />5. 跳出括号，向右看，碰到[10] ------------------------------ 一个10元素的数组<br />6. 向左看，发现一个* --------------------------------------- 指针<br />7. 向左看，发现int ----------------------------------------- int类型</p>
		<p>总结：fp1被声明成为一个函数的指针的指针的数组，这个数组有10个元素，函数的原型为带一个int类型的参数，返回值为一个指针？</p>
		<p>再来看一个例子：</p>
		<p>int *( *( *arr[5])())();</p>
		<p>阅读步骤：<br />1. 从变量名开始 -------------------------------------------- arr<br />2. 往右看，发现是一个数组 ---------------------------------- 一个5元素的数组<br />3. 向左看，发现一个* --------------------------------------- 指针<br />4. 跳出括号，向右看，发现() -------------------------------- 不带参数的函数<br />5. 向左看，碰到* ------------------------------------------- （函数）返回一个指针<br />6. 跳出括号，向右发现() ------------------------------------ 不带参数的函数<br />7. 向左，发现* --------------------------------------------- （函数）返回一个指针<br />8. 继续向左，发现int --------------------------------------- int类型</p>
		<p>总结：？？</p>
		<p>
				<br />还有更多的例子：</p>
		<p>float ( * ( *b()) [] )();              // b is a function that returns a <br />                                       // pointer to an array of pointers<br />                                       // to functions returning floats.</p>
		<p>void * ( *c) ( char, int (*)());       // c is a pointer to a function that takes<br />                                       // two parameters:<br />                                       //     a char and a pointer to a<br />                                       //     function that takes no<br />                                       //     parameters and returns<br />                                       //     an int<br />                                       // and returns a pointer to void.</p>
		<p>void ** (*d) (int &amp;, <br />  char **(*)(char *, char **));        // d is a pointer to a function that takes<br />                                       // two parameters:<br />                                       //     a reference to an int and a pointer<br />                                       //     to a function that takes two parameters:<br />                                       //        a pointer to a char and a pointer<br />                                       //        to a pointer to a char<br />                                       //     and returns a pointer to a pointer <br />                                       //     to a char<br />                                       // and returns a pointer to a pointer to void</p>
		<p>float ( * ( * e[10]) <br />    (int &amp;) ) [5];                    // e is an array of 10 pointers to <br />                                       // functions that take a single<br />                                       // reference to an int as an argument <br />                                       // and return pointers to<br />                                       // an array of 5 floats.</p>
		<p>正文完</p>
		<p> </p>
<img src ="http://www.cppblog.com/apollo/aggbug/5390.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-04-12 14:52 <a href="http://www.cppblog.com/apollo/articles/5390.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个模板巧妙技术，语法技巧</title><link>http://www.cppblog.com/apollo/articles/5054.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Wed, 05 Apr 2006 16:17:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/5054.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/5054.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/5054.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/5054.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/5054.html</trackback:ping><description><![CDATA[
		<span style="color: rgb(0, 0, 0);">#include </span>
		<span style="color: rgb(0, 0, 0);">&lt;</span>
		<span style="color: rgb(0, 0, 0);">iostream</span>
		<span style="color: rgb(0, 0, 0);">&gt;</span>
		<span style="color: rgb(0, 0, 0);">
				<br />
				<img src="../../Images/OutliningIndicators/None.gif" align="top" />
				<br />
				<img src="../../Images/OutliningIndicators/None.gif" align="top" />
		</span>
		<span style="color: rgb(0, 128, 0);">//</span>
		<span style="color: rgb(0, 128, 0);"> 返回类型,大小分别为1、2</span>
		<span style="color: rgb(0, 128, 0);">
				<br />
				<img src="../../Images/OutliningIndicators/None.gif" align="top" />
		</span>
		<span style="color: rgb(0, 0, 0);">typedef </span>
		<span style="color: rgb(0, 0, 255);">char</span>
		<span style="color: rgb(0, 0, 0);"> RT1;<br /><img src="../../Images/OutliningIndicators/None.gif" align="top" />typedef </span>
		<span style="color: rgb(0, 0, 255);">struct</span>
		<span style="color: rgb(0, 0, 0);">
				<br />
				<img id="Codehighlighter1_71_85_Open_Image" onclick="this.style.display='none'; Codehighlighter1_71_85_Open_Text.style.display='none'; Codehighlighter1_71_85_Closed_Image.style.display='inline'; Codehighlighter1_71_85_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" />
				<img id="Codehighlighter1_71_85_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_71_85_Closed_Text.style.display='none'; Codehighlighter1_71_85_Open_Image.style.display='inline'; Codehighlighter1_71_85_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top" />
		</span>
		<span id="Codehighlighter1_71_85_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);">
				<img src="../../Images/dot.gif" />
		</span>
		<span id="Codehighlighter1_71_85_Open_Text">
				<span style="color: rgb(0, 0, 0);">{<br /><img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />    </span>
				<span style="color: rgb(0, 0, 255);">char</span>
				<span style="color: rgb(0, 0, 0);"> a[</span>
				<span style="color: rgb(0, 0, 0);">2</span>
				<span style="color: rgb(0, 0, 0);">];<br /><img src="../../Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
		</span>
		<span style="color: rgb(0, 0, 0);"> RT2;<br /><img src="../../Images/OutliningIndicators/None.gif" align="top" /><br /><img src="../../Images/OutliningIndicators/None.gif" align="top" /></span>
		<span style="color: rgb(0, 128, 0);">//</span>
		<span style="color: rgb(0, 128, 0);"> 选择这个版本将返回char,大小为1</span>
		<span style="color: rgb(0, 128, 0);">
				<br />
				<img src="../../Images/OutliningIndicators/None.gif" align="top" />
		</span>
		<span style="color: rgb(0, 0, 0);">template</span>
		<span style="color: rgb(0, 0, 0);">&lt;</span>
		<span style="color: rgb(0, 0, 0);">typename T</span>
		<span style="color: rgb(0, 0, 0);">&gt;</span>
		<span style="color: rgb(0, 0, 0);"> RT1 test(typename T::X </span>
		<span style="color: rgb(0, 0, 255);">const</span>
		<span style="color: rgb(0, 0, 0);">*</span>
		<span style="color: rgb(0, 0, 0);">)<br /><img id="Codehighlighter1_167_193_Open_Image" onclick="this.style.display='none'; Codehighlighter1_167_193_Open_Text.style.display='none'; Codehighlighter1_167_193_Closed_Image.style.display='inline'; Codehighlighter1_167_193_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_167_193_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_167_193_Closed_Text.style.display='none'; Codehighlighter1_167_193_Open_Image.style.display='inline'; Codehighlighter1_167_193_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top" /></span>
		<span id="Codehighlighter1_167_193_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);">
				<img src="../../Images/dot.gif" />
		</span>
		<span id="Codehighlighter1_167_193_Open_Text">
				<span style="color: rgb(0, 0, 0);">{<br /><img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />    </span>
				<span style="color: rgb(0, 0, 255);">int</span>
				<span style="color: rgb(0, 0, 0);">    dumy    </span>
				<span style="color: rgb(0, 0, 0);">=</span>
				<span style="color: rgb(0, 0, 0);"> </span>
				<span style="color: rgb(0, 0, 0);">0</span>
				<span style="color: rgb(0, 0, 0);">;<br /><img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />    dumy</span>
				<span style="color: rgb(0, 0, 0);">++</span>
				<span style="color: rgb(0, 0, 0);">;<br /><img src="../../Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
		</span>
		<span style="color: rgb(0, 0, 0);">
				<br />
				<img src="../../Images/OutliningIndicators/None.gif" align="top" />
				<br />
				<img src="../../Images/OutliningIndicators/None.gif" align="top" />
		</span>
		<span style="color: rgb(0, 128, 0);">//</span>
		<span style="color: rgb(0, 128, 0);"> 选择这个版本将返回char,大小为2</span>
		<span style="color: rgb(0, 128, 0);">
				<br />
				<img src="../../Images/OutliningIndicators/None.gif" align="top" />
		</span>
		<span style="color: rgb(0, 0, 0);">template</span>
		<span style="color: rgb(0, 0, 0);">&lt;</span>
		<span style="color: rgb(0, 0, 0);">typename T</span>
		<span style="color: rgb(0, 0, 0);">&gt;</span>
		<span style="color: rgb(0, 0, 0);"> RT2 test(<img src="../../Images/dot.gif" />)<br /><img id="Codehighlighter1_253_279_Open_Image" onclick="this.style.display='none'; Codehighlighter1_253_279_Open_Text.style.display='none'; Codehighlighter1_253_279_Closed_Image.style.display='inline'; Codehighlighter1_253_279_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_253_279_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_253_279_Closed_Text.style.display='none'; Codehighlighter1_253_279_Open_Image.style.display='inline'; Codehighlighter1_253_279_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top" /></span>
		<span id="Codehighlighter1_253_279_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);">
				<img src="../../Images/dot.gif" />
		</span>
		<span id="Codehighlighter1_253_279_Open_Text">
				<span style="color: rgb(0, 0, 0);">{<br /><img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />    </span>
				<span style="color: rgb(0, 0, 255);">int</span>
				<span style="color: rgb(0, 0, 0);">    dumy    </span>
				<span style="color: rgb(0, 0, 0);">=</span>
				<span style="color: rgb(0, 0, 0);"> </span>
				<span style="color: rgb(0, 0, 0);">0</span>
				<span style="color: rgb(0, 0, 0);">;<br /><img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />    dumy</span>
				<span style="color: rgb(0, 0, 0);">++</span>
				<span style="color: rgb(0, 0, 0);">;<br /><img src="../../Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
		</span>
		<span style="color: rgb(0, 0, 0);">
				<br />
				<img src="../../Images/OutliningIndicators/None.gif" align="top" />
				<br />
				<img src="../../Images/OutliningIndicators/None.gif" align="top" />
		</span>
		<span style="color: rgb(0, 128, 0);">//</span>
		<span style="color: rgb(0, 128, 0);"> 依靠编译器自动选择test函数,然后依据返回类型判断是否含有X</span>
		<span style="color: rgb(0, 128, 0);">
				<br />
				<img src="../../Images/OutliningIndicators/None.gif" align="top" />
		</span>
		<span style="color: rgb(0, 0, 0);">template</span>
		<span style="color: rgb(0, 0, 0);">&lt;</span>
		<span style="color: rgb(0, 0, 0);">typename T</span>
		<span style="color: rgb(0, 0, 0);">&gt;</span>
		<span style="color: rgb(0, 0, 0);">
				<br />
				<img src="../../Images/OutliningIndicators/None.gif" align="top" />
		</span>
		<span style="color: rgb(0, 0, 255);">bool</span>
		<span style="color: rgb(0, 0, 0);"> type_has_member_type_X()<br /><img id="Codehighlighter1_369_441_Open_Image" onclick="this.style.display='none'; Codehighlighter1_369_441_Open_Text.style.display='none'; Codehighlighter1_369_441_Closed_Image.style.display='inline'; Codehighlighter1_369_441_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_369_441_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_369_441_Closed_Text.style.display='none'; Codehighlighter1_369_441_Open_Image.style.display='inline'; Codehighlighter1_369_441_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top" /></span>
		<span id="Codehighlighter1_369_441_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);">
				<img src="../../Images/dot.gif" />
		</span>
		<span id="Codehighlighter1_369_441_Open_Text">
				<span style="color: rgb(0, 0, 0);">{<br /><img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />    </span>
				<span style="color: rgb(0, 0, 255);">return</span>
				<span style="color: rgb(0, 0, 0);"> (</span>
				<span style="color: rgb(0, 0, 255);">sizeof</span>
				<span style="color: rgb(0, 0, 0);">(test</span>
				<span style="color: rgb(0, 0, 0);">&lt;</span>
				<span style="color: rgb(0, 0, 0);">T</span>
				<span style="color: rgb(0, 0, 0);">&gt;</span>
				<span style="color: rgb(0, 0, 0);">(</span>
				<span style="color: rgb(0, 0, 0);">0</span>
				<span style="color: rgb(0, 0, 0);">)) </span>
				<span style="color: rgb(0, 0, 0);">==</span>
				<span style="color: rgb(0, 0, 0);"> </span>
				<span style="color: rgb(0, 0, 0);">1</span>
				<span style="color: rgb(0, 0, 0);">);<br /><img src="../../Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
		</span>
		<span style="color: rgb(0, 0, 0);">
				<br />
				<img src="../../Images/OutliningIndicators/None.gif" align="top" />
				<br />
				<img src="../../Images/OutliningIndicators/None.gif" align="top" />
		</span>
		<span style="color: rgb(0, 128, 0);">//</span>
		<span style="color: rgb(0, 128, 0);"> 有X类型的类</span>
		<span style="color: rgb(0, 128, 0);">
				<br />
				<img src="../../Images/OutliningIndicators/None.gif" align="top" />
		</span>
		<span style="color: rgb(0, 0, 255);">class</span>
		<span style="color: rgb(0, 0, 0);"> HasX<br /><img id="Codehighlighter1_465_491_Open_Image" onclick="this.style.display='none'; Codehighlighter1_465_491_Open_Text.style.display='none'; Codehighlighter1_465_491_Closed_Image.style.display='inline'; Codehighlighter1_465_491_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_465_491_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_465_491_Closed_Text.style.display='none'; Codehighlighter1_465_491_Open_Image.style.display='inline'; Codehighlighter1_465_491_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top" /></span>
		<span id="Codehighlighter1_465_491_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);">
				<img src="../../Images/dot.gif" />
		</span>
		<span id="Codehighlighter1_465_491_Open_Text">
				<span style="color: rgb(0, 0, 0);">{<br /><img src="../../Images/OutliningIndicators/InBlock.gif" align="top" /></span>
				<span style="color: rgb(0, 0, 255);">public</span>
				<span style="color: rgb(0, 0, 0);">:<br /><img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />    </span>
				<span style="color: rgb(0, 0, 255);">class</span>
				<span style="color: rgb(0, 0, 0);"> X<br /><img id="Codehighlighter1_485_488_Open_Image" onclick="this.style.display='none'; Codehighlighter1_485_488_Open_Text.style.display='none'; Codehighlighter1_485_488_Closed_Image.style.display='inline'; Codehighlighter1_485_488_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_485_488_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_485_488_Closed_Text.style.display='none'; Codehighlighter1_485_488_Open_Image.style.display='inline'; Codehighlighter1_485_488_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span>
				<span id="Codehighlighter1_485_488_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);">
						<img src="../../Images/dot.gif" />
				</span>
				<span id="Codehighlighter1_485_488_Open_Text">
						<span style="color: rgb(0, 0, 0);">{<br /><img src="../../Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span>
				</span>
				<span style="color: rgb(0, 0, 0);">;<br /><img src="../../Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
		</span>
		<span style="color: rgb(0, 0, 0);">;<br /><img src="../../Images/OutliningIndicators/None.gif" align="top" /><br /><img src="../../Images/OutliningIndicators/None.gif" align="top" /></span>
		<span style="color: rgb(0, 128, 0);">//</span>
		<span style="color: rgb(0, 128, 0);"> 无X类型的类</span>
		<span style="color: rgb(0, 128, 0);">
				<br />
				<img src="../../Images/OutliningIndicators/None.gif" align="top" />
		</span>
		<span style="color: rgb(0, 0, 255);">class</span>
		<span style="color: rgb(0, 0, 0);"> NonX<br /><img id="Codehighlighter1_516_542_Open_Image" onclick="this.style.display='none'; Codehighlighter1_516_542_Open_Text.style.display='none'; Codehighlighter1_516_542_Closed_Image.style.display='inline'; Codehighlighter1_516_542_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_516_542_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_516_542_Closed_Text.style.display='none'; Codehighlighter1_516_542_Open_Image.style.display='inline'; Codehighlighter1_516_542_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top" /></span>
		<span id="Codehighlighter1_516_542_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);">
				<img src="../../Images/dot.gif" />
		</span>
		<span id="Codehighlighter1_516_542_Open_Text">
				<span style="color: rgb(0, 0, 0);">{<br /><img src="../../Images/OutliningIndicators/InBlock.gif" align="top" /></span>
				<span style="color: rgb(0, 0, 255);">public</span>
				<span style="color: rgb(0, 0, 0);">:<br /><img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />    </span>
				<span style="color: rgb(0, 0, 255);">class</span>
				<span style="color: rgb(0, 0, 0);"> Y<br /><img id="Codehighlighter1_536_539_Open_Image" onclick="this.style.display='none'; Codehighlighter1_536_539_Open_Text.style.display='none'; Codehighlighter1_536_539_Closed_Image.style.display='inline'; Codehighlighter1_536_539_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_536_539_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_536_539_Closed_Text.style.display='none'; Codehighlighter1_536_539_Open_Image.style.display='inline'; Codehighlighter1_536_539_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span>
				<span id="Codehighlighter1_536_539_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);">
						<img src="../../Images/dot.gif" />
				</span>
				<span id="Codehighlighter1_536_539_Open_Text">
						<span style="color: rgb(0, 0, 0);">{<br /><img src="../../Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span>
				</span>
				<span style="color: rgb(0, 0, 0);">;<br /><img src="../../Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
		</span>
		<span style="color: rgb(0, 0, 0);">;<br /><img src="../../Images/OutliningIndicators/None.gif" align="top" /><br /><img src="../../Images/OutliningIndicators/None.gif" align="top" /></span>
		<span style="color: rgb(0, 0, 255);">int</span>
		<span style="color: rgb(0, 0, 0);"> _tmain(</span>
		<span style="color: rgb(0, 0, 255);">int</span>
		<span style="color: rgb(0, 0, 0);"> argc, _TCHAR</span>
		<span style="color: rgb(0, 0, 0);">*</span>
		<span style="color: rgb(0, 0, 0);"> argv[])<br /><img id="Codehighlighter1_583_934_Open_Image" onclick="this.style.display='none'; Codehighlighter1_583_934_Open_Text.style.display='none'; Codehighlighter1_583_934_Closed_Image.style.display='inline'; Codehighlighter1_583_934_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_583_934_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_583_934_Closed_Text.style.display='none'; Codehighlighter1_583_934_Open_Image.style.display='inline'; Codehighlighter1_583_934_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top" /></span>
		<span id="Codehighlighter1_583_934_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);">
				<img src="../../Images/dot.gif" />
		</span>
		<span id="Codehighlighter1_583_934_Open_Text">
				<span style="color: rgb(0, 0, 0);">{<br /><img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />    </span>
				<span style="color: rgb(0, 128, 0);">//</span>
				<span style="color: rgb(0, 128, 0);"> 编译器选择重载函数策略:选择类型最匹配版本<br /><img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />    </span>
				<span style="color: rgb(0, 128, 0);">//</span>
				<span style="color: rgb(0, 128, 0);"> 倾向于把0转化为常量空指针,所以选择返回为RT1版本</span>
				<span style="color: rgb(0, 128, 0);">
						<br />
						<img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />
				</span>
				<span style="color: rgb(0, 0, 0);">    </span>
				<span style="color: rgb(0, 0, 255);">if</span>
				<span style="color: rgb(0, 0, 0);">(type_has_member_type_X</span>
				<span style="color: rgb(0, 0, 0);">&lt;</span>
				<span style="color: rgb(0, 0, 0);">HasX</span>
				<span style="color: rgb(0, 0, 0);">&gt;</span>
				<span style="color: rgb(0, 0, 0);">())<br /><img id="Codehighlighter1_679_719_Open_Image" onclick="this.style.display='none'; Codehighlighter1_679_719_Open_Text.style.display='none'; Codehighlighter1_679_719_Closed_Image.style.display='inline'; Codehighlighter1_679_719_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_679_719_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_679_719_Closed_Text.style.display='none'; Codehighlighter1_679_719_Open_Image.style.display='inline'; Codehighlighter1_679_719_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span>
				<span id="Codehighlighter1_679_719_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);">
						<img src="../../Images/dot.gif" />
				</span>
				<span id="Codehighlighter1_679_719_Open_Text">
						<span style="color: rgb(0, 0, 0);">{<br /><img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />        std::cout </span>
						<span style="color: rgb(0, 0, 0);">&lt;&lt;</span>
						<span style="color: rgb(0, 0, 0);"> </span>
						<span style="color: rgb(0, 0, 0);">"</span>
						<span style="color: rgb(0, 0, 0);">Has X</span>
						<span style="color: rgb(0, 0, 0);">"</span>
						<span style="color: rgb(0, 0, 0);"> </span>
						<span style="color: rgb(0, 0, 0);">&lt;&lt;</span>
						<span style="color: rgb(0, 0, 0);"> std::endl;<br /><img src="../../Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span>
				</span>
				<span style="color: rgb(0, 0, 0);">
						<br />
						<img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />    </span>
				<span style="color: rgb(0, 0, 255);">else</span>
				<span style="color: rgb(0, 0, 0);">
						<br />
						<img id="Codehighlighter1_728_768_Open_Image" onclick="this.style.display='none'; Codehighlighter1_728_768_Open_Text.style.display='none'; Codehighlighter1_728_768_Closed_Image.style.display='inline'; Codehighlighter1_728_768_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" />
						<img id="Codehighlighter1_728_768_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_728_768_Closed_Text.style.display='none'; Codehighlighter1_728_768_Open_Image.style.display='inline'; Codehighlighter1_728_768_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span>
				<span id="Codehighlighter1_728_768_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);">
						<img src="../../Images/dot.gif" />
				</span>
				<span id="Codehighlighter1_728_768_Open_Text">
						<span style="color: rgb(0, 0, 0);">{<br /><img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />        std::cout </span>
						<span style="color: rgb(0, 0, 0);">&lt;&lt;</span>
						<span style="color: rgb(0, 0, 0);"> </span>
						<span style="color: rgb(0, 0, 0);">"</span>
						<span style="color: rgb(0, 0, 0);">Non X</span>
						<span style="color: rgb(0, 0, 0);">"</span>
						<span style="color: rgb(0, 0, 0);"> </span>
						<span style="color: rgb(0, 0, 0);">&lt;&lt;</span>
						<span style="color: rgb(0, 0, 0);"> std::endl;<br /><img src="../../Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span>
				</span>
				<span style="color: rgb(0, 0, 0);">
						<br />
						<img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />
						<br />
						<img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />    </span>
				<span style="color: rgb(0, 128, 0);">//</span>
				<span style="color: rgb(0, 128, 0);"> 没有T::X,所以选择返回为RT2版本</span>
				<span style="color: rgb(0, 128, 0);">
						<br />
						<img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />
				</span>
				<span style="color: rgb(0, 0, 0);">    </span>
				<span style="color: rgb(0, 0, 255);">if</span>
				<span style="color: rgb(0, 0, 0);">(type_has_member_type_X</span>
				<span style="color: rgb(0, 0, 0);">&lt;</span>
				<span style="color: rgb(0, 0, 0);">NonX</span>
				<span style="color: rgb(0, 0, 0);">&gt;</span>
				<span style="color: rgb(0, 0, 0);">())<br /><img id="Codehighlighter1_832_872_Open_Image" onclick="this.style.display='none'; Codehighlighter1_832_872_Open_Text.style.display='none'; Codehighlighter1_832_872_Closed_Image.style.display='inline'; Codehighlighter1_832_872_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_832_872_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_832_872_Closed_Text.style.display='none'; Codehighlighter1_832_872_Open_Image.style.display='inline'; Codehighlighter1_832_872_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span>
				<span id="Codehighlighter1_832_872_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);">
						<img src="../../Images/dot.gif" />
				</span>
				<span id="Codehighlighter1_832_872_Open_Text">
						<span style="color: rgb(0, 0, 0);">{<br /><img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />        std::cout </span>
						<span style="color: rgb(0, 0, 0);">&lt;&lt;</span>
						<span style="color: rgb(0, 0, 0);"> </span>
						<span style="color: rgb(0, 0, 0);">"</span>
						<span style="color: rgb(0, 0, 0);">Has X</span>
						<span style="color: rgb(0, 0, 0);">"</span>
						<span style="color: rgb(0, 0, 0);"> </span>
						<span style="color: rgb(0, 0, 0);">&lt;&lt;</span>
						<span style="color: rgb(0, 0, 0);"> std::endl;<br /><img src="../../Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span>
				</span>
				<span style="color: rgb(0, 0, 0);">
						<br />
						<img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />    </span>
				<span style="color: rgb(0, 0, 255);">else</span>
				<span style="color: rgb(0, 0, 0);">
						<br />
						<img id="Codehighlighter1_881_921_Open_Image" onclick="this.style.display='none'; Codehighlighter1_881_921_Open_Text.style.display='none'; Codehighlighter1_881_921_Closed_Image.style.display='inline'; Codehighlighter1_881_921_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" />
						<img id="Codehighlighter1_881_921_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_881_921_Closed_Text.style.display='none'; Codehighlighter1_881_921_Open_Image.style.display='inline'; Codehighlighter1_881_921_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span>
				<span id="Codehighlighter1_881_921_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);">
						<img src="../../Images/dot.gif" />
				</span>
				<span id="Codehighlighter1_881_921_Open_Text">
						<span style="color: rgb(0, 0, 0);">{<br /><img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />        std::cout </span>
						<span style="color: rgb(0, 0, 0);">&lt;&lt;</span>
						<span style="color: rgb(0, 0, 0);"> </span>
						<span style="color: rgb(0, 0, 0);">"</span>
						<span style="color: rgb(0, 0, 0);">Non X</span>
						<span style="color: rgb(0, 0, 0);">"</span>
						<span style="color: rgb(0, 0, 0);"> </span>
						<span style="color: rgb(0, 0, 0);">&lt;&lt;</span>
						<span style="color: rgb(0, 0, 0);"> std::endl;<br /><img src="../../Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span>
				</span>
				<span style="color: rgb(0, 0, 0);">
						<br />
						<img src="../../Images/OutliningIndicators/InBlock.gif" align="top" />    </span>
				<span style="color: rgb(0, 0, 255);">return</span>
				<span style="color: rgb(0, 0, 0);"> </span>
				<span style="color: rgb(0, 0, 0);">0</span>
				<span style="color: rgb(0, 0, 0);">;<br /><img src="../../Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
		</span>
		输出结果:<br />
Has X<br />
Non X<img src ="http://www.cppblog.com/apollo/aggbug/5054.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-04-06 00:17 <a href="http://www.cppblog.com/apollo/articles/5054.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个复杂的boost.lambda表达式的例子</title><link>http://www.cppblog.com/apollo/articles/lambda.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Tue, 28 Mar 2006 15:03:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/lambda.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/4699.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/lambda.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/4699.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/4699.html</trackback:ping><description><![CDATA[
		<font size="4">    对于lambda库的介绍，大家还是去看boost文档。我对lambda的原理也是一知半解，有兴趣的可以去学习一些函数式编程语言的相关理论。<br />lambda的使用方式确实颠覆了传统的过程式语言的一些方面。<br />   
在C++中，可以这样理解：lambda的功能就是把一段代码当作参数，传给一个函数。在被调用函数中，会用这段参数代码作一个处理。而且这段参数代码并
不是只能写一些静态的过程，它可以有参数。在C++中，这段参数代码实际上是一个functor.<br /><br />我们看一个最简单的例子：<br />vector&lt;int&gt; v(10)<br />for_each(v.begin(), v.end(), <span style="color: rgb(255, 0, 0);">cout &lt;&lt; _1 &lt;&lt; '\n'</span>);<br /><br />这个<span style="color: rgb(255, 0, 0);">cout &lt;&lt; _1 &lt;&lt; '\n'</span>，就是一个lambda函数。<br />lambda并不是只能处理这样简单的例子，还可以有分支、循环等控制语句。正好工作中用到，顺便贴出来。<br />例子说明：这是一个收集windows信息的代码的一部分，下面这段代码是收集磁盘类型和磁盘空间的。<br /><br />using namespace boost::lambda;<br /><span style="color: rgb(128, 128, 128);">//下面三行，是因为windows API是__stdcall修饰的，因此，用function来包装一下。</span><br />boost::function&lt;UINT (LPCTSTR)&gt; drtype = ::GetDriveType;<br />boost::function&lt;BOOL (LPCTSTR, LPDWORD, LPDWORD, LPDWORD, LPDWORD)&gt; <br />drfree = ::GetDiskFreeSpace;<br /><br /><br />DWORD dwSectorsPerCluster, dwBytesPerSector, <br />NumberOfFreeClusters, dwTotalNumberOfClusters;<br /><span style="color: rgb(128, 128, 128);">//log 是预定义的，ostream类型</span><br />log &lt;&lt; "DriveType=";<br /><span style="color: rgb(128, 128, 128);">//dl是盘符列表</span><br />for_each(dl.begin(), dl.end(), <br />(       <span style="color: rgb(128, 128, 128);">//这个“(“不能少，你就当它是{看待</span><br />log &lt;&lt; _1 &lt;&lt; " " <span style="color: rgb(128, 128, 128);">// 这个很简单</span><br />&lt;&lt; bind(drtype, bind(&amp;string::c_str, _1)),    <span style="color: rgb(128, 128, 128);">//这个，相当于导致drtype(_1.c_str())</span><br /><span style="color: rgb(128, 128, 128);">        //上面的"<span style="color: rgb(255, 0, 0);">,</span>"是被lambda重载的，你当它是“<span style="color: rgb(255, 0, 0);">;</span>”</span><br />if_  <span style="color: rgb(128, 128, 128);">//这个相当于if</span><br />(<br />bind(drfree, bind(&amp;string::c_str, _1)<br />, &amp;dwSectorsPerCluster, &amp;dwBytesPerSector<br />, &amp;NumberOfFreeClusters, &amp;dwTotalNumberOfClusters<br />) &gt; 0    <span style="color: rgb(128, 128, 128);">//这个好长，其实很简单：drfree(1.c_str(), ...) &gt; 0;</span><br />)<br />[    <span style="color: rgb(128, 128, 128);">//这个也是重载的，当它是“{“</span><br />log &lt;&lt; constant(" ")    <span style="color: rgb(128, 128, 128);">//这个constant是一定要的，这样这一行才能成为一个lambda表达式</span><br />&lt;&lt; var(dwSectorsPerCluster) &lt;&lt; constant(" ")<br />&lt;&lt; var(dwSectorsPerCluster) &lt;&lt; constant(" ")<br />&lt;&lt; var(dwBytesPerSector) &lt;&lt; constant(" ")<br />&lt;&lt; var(NumberOfFreeClusters) &lt;&lt; constant(" ")<br />&lt;&lt; var(dwTotalNumberOfClusters)<br />],<br />log &lt;&lt; constant(", ")<br />)<br />);<br />log &lt;&lt; END_LINE;<br /><br />    在写比较长的lambda的时候，掌握一个原则，就很简单了。<br />    
我把一个lambda表达式叫做一个lambda算子，lambda表达式只能由lambda算子构成。lambda算子之间的运算组合，仍然是
lambda算子。一个普通的C++对象，必须首先转型成lambda算子才能参与lambda运算。一个复杂的lambda表达式必须注意检查每一个环
节，确保都是lambda算子（或者可以隐式转换的）。这样，结合运算符重载的知识，就不难写出复杂的lambda表达式了。<br />ps:在vc7.1中，lambda表达式有错误时，编译出错信息可是非常壮观的，不是一般的壮观哦</font>
<img src ="http://www.cppblog.com/apollo/aggbug/4699.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-03-28 23:03 <a href="http://www.cppblog.com/apollo/articles/lambda.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++   编程思想学习笔记－命名控制   </title><link>http://www.cppblog.com/apollo/articles/4593.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Sat, 25 Mar 2006 15:04:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/4593.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/4593.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/4593.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/4593.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/4593.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一、           																												static																				的使用																																																																								1、										  ...&nbsp;&nbsp;<a href='http://www.cppblog.com/apollo/articles/4593.html'>阅读全文</a><img src ="http://www.cppblog.com/apollo/aggbug/4593.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-03-25 23:04 <a href="http://www.cppblog.com/apollo/articles/4593.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>2005年华为招聘--C语言笔试试题</title><link>http://www.cppblog.com/apollo/articles/huawei.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Thu, 23 Mar 2006 15:29:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/huawei.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/4511.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/huawei.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/4511.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/4511.html</trackback:ping><description><![CDATA[
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: center;" align="center">
				<strong style="">
						<span style="font-size: 12pt;" lang="EN-US">
								<font face="Times New Roman">2005</font>
						</span>
				</strong>
				<strong style="">
						<span style="font-size: 12pt; font-family: 宋体;">年华为招聘</span>
				</strong>
				<font face="Times New Roman">
						<strong style="">
								<span style="font-size: 12pt;" lang="EN-US">--</span>
						</strong>
						<strong style="">
								<span style="font-size: 12pt;" lang="EN-US">C</span>
						</strong>
				</font>
				<strong style="">
						<span style="font-size: 12pt; font-family: 宋体;">语言笔试试题</span>
				</strong>
				<strong style="">
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</strong>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: center;" align="center">
				<strong style="">
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p> </o:p>
						</span>
				</strong>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt 21pt; text-indent: -21pt; text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: 宋体;">一、</span>
				<span style="font-size: 12pt; font-family: 宋体;">判断题（对的写</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">T</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">，错的写</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">F</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">并说明原因，每小题</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">4</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">分，共</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">20</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">分）</span>
				<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">1</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">、有数组定义</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">int a[2][2]={{1},{2,3}};</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">则</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">a[0][1]</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">的值为</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">0</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">。（</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<span style="">
								<font face="Times New Roman">     </font>
						</span>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">）</span>
				<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">2</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">、</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">int (*ptr) (),</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">则</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">ptr</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">是一维数组的名字。（</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<span style="">
								<font face="Times New Roman">     </font>
						</span>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">）</span>
				<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">3</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">、指针在任何情况下都可进行</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">&gt;,&lt;,&gt;=,&lt;=,==</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">运算。（</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<span style="">
								<font face="Times New Roman">     </font>
						</span>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">）</span>
				<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">4</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">、</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">switch(c) </font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">语句中</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">c</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">可以是</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">int ,long,char ,float ,unsigned int </font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">类型。（</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<span style="">
								<font face="Times New Roman">   </font>
						</span>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">）</span>
				<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">5</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">、</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">#define print(x)<span style="">  </span>printf(</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">＂</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">the no, </font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">＂</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">#x</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">＂</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">,is </font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">＂</span>
				<font face="Times New Roman">
						<span style="font-size: 12pt;" lang="EN-US">)</span>
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"> <o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: 宋体;">二、填空题（共</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">30</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">分）</span>
				<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">1</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">、在</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">windows</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">下，写出运行结果，每空</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">2</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">分，共</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">10</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">分。</span>
				<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">char str[ ]= </font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">＂</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">Hello</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">＂</span>
				<font face="Times New Roman">
						<span style="font-size: 12pt;" lang="EN-US">;</span>
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<font face="Times New Roman">
						<span style="font-size: 12pt;" lang="EN-US">char *p=str;</span>
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<font face="Times New Roman">
						<span style="font-size: 12pt;" lang="EN-US">int n=10;</span>
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<font face="Times New Roman">
						<span style="font-size: 12pt;" lang="EN-US">sizeof(str)=(<span style="">      </span>)</span>
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<font face="Times New Roman">
						<span style="font-size: 12pt;" lang="EN-US">sizeof(p)=(<span style="">       </span>)</span>
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<font face="Times New Roman">
						<span style="font-size: 12pt;" lang="EN-US">sizeof(n)=(<span style="">       </span>)</span>
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
						<o:p> </o:p>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<font face="Times New Roman">
						<span style="font-size: 12pt;" lang="EN-US">void func(char str[100])</span>
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<font face="Times New Roman">
						<span style="font-size: 12pt;" lang="EN-US">{<span style="">    </span>}</span>
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<font face="Times New Roman">
						<span style="font-size: 12pt;" lang="EN-US">sizeof(str)=(<span style="">     </span>)</span>
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"> <o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">2</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">、</span>
				<font face="Times New Roman">
						<span style="font-size: 12pt;" lang="EN-US">void setmemory(char **p, int num)</span>
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<font face="Times New Roman">
						<span style="font-size: 12pt;" lang="EN-US">{ *p=(char *) malloc(num);}</span>
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<font face="Times New Roman">
						<span style="font-size: 12pt;" lang="EN-US">void test(void)</span>
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<font face="Times New Roman">
						<span style="font-size: 12pt;" lang="EN-US">{<span style="">  </span>char *str=NULL;</span>
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<font face="Times New Roman">
						<span style="font-size: 12pt;" lang="EN-US">
								<span style="">   </span>getmemory(&amp;str,100);</span>
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">
								<span style="">   </span>strcpy(str,</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">＂</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">hello</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">＂</span>
				<font face="Times New Roman">
						<span style="font-size: 12pt;" lang="EN-US">);</span>
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<font face="Times New Roman">
						<span style="font-size: 12pt;" lang="EN-US">
								<span style="">   </span>printf(str);</span>
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<font face="Times New Roman">
						<span style="font-size: 12pt;" lang="EN-US">}</span>
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: 宋体;">运行</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">test</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">函数有什么结果？（</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<span style="">
								<font face="Times New Roman">                               
</font>
						</span>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">）</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">10</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">分</span>
				<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"> <o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">3</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">、设</span>
				<font face="Times New Roman">
						<span style="font-size: 12pt;" lang="EN-US">int arr[]={6,7,8,9,10};</span>
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<font face="Times New Roman">
						<span style="font-size: 12pt;" lang="EN-US">
								<span style="">     </span>int *ptr=arr;</span>
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<font face="Times New Roman">
						<span style="font-size: 12pt;" lang="EN-US">
								<span style="">   </span>*(ptr++)+=123;</span>
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">
								<span style=""> </span>printf(</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">＂</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">%d,%d</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">＂</span>
				<font face="Times New Roman">
						<span style="font-size: 12pt;" lang="EN-US">,*ptr,*(++ptr));</span>
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">(<span style="">                                  
</span>) 10</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">分</span>
				<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt 21pt; text-indent: -21pt; text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"> <o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt 21pt; text-indent: -21pt; text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: 宋体;">二、</span>
				<span style="font-size: 12pt; font-family: 宋体;">编程题（第一小题</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">20</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">，第二小题</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">30</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">分）</span>
				<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt 18pt; text-indent: -18pt; text-align: left;" align="left">
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">1</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">、</span>
				<span style="font-size: 7pt;" lang="EN-US">
						<font face="Times New Roman">  </font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">不使用库函数，编写函数</span>
				<font face="Times New Roman">
						<span style="font-size: 12pt;" lang="EN-US">int strcmp(char<span style="">  </span>*source, char *dest)</span>
						<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<span style="font-size: 12pt;" lang="EN-US">
						<span style="">
								<font face="Times New Roman"> </font>
						</span>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">相等返回</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">0</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">，不等返回</span>
				<span style="font-size: 12pt;" lang="EN-US">
						<font face="Times New Roman">-1</font>
				</span>
				<span style="font-size: 12pt; font-family: 宋体;">；</span>
				<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">
				<span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">
						<o:p> </o:p>
				</span>
		</p>
		<span style="font-size: 12pt;" lang="EN-US">
				<font face="Times New Roman">2</font>
		</span>
		<span style="font-size: 12pt; font-family: 宋体;">、</span>
		<span style="font-size: 7pt;" lang="EN-US">
				<font face="Times New Roman">  </font>
		</span>
		<span style="font-size: 12pt; font-family: 宋体;">写一函数</span>
		<span style="font-size: 12pt;" lang="EN-US">
				<font face="Times New Roman">int fun(char *p)</font>
		</span>
		<span style="font-size: 12pt; font-family: 宋体;">判断一字符串是否为回文，是返回</span>
		<span style="font-size: 12pt;" lang="EN-US">
				<font face="Times New Roman">1</font>
		</span>
		<span style="font-size: 12pt; font-family: 宋体;">，不是返回</span>
		<span style="font-size: 12pt;" lang="EN-US">
				<font face="Times New Roman">0</font>
		</span>
		<span style="font-size: 12pt; font-family: 宋体;">，出错返回</span>
		<font face="Times New Roman">
				<span style="font-size: 12pt;" lang="EN-US">-1</span>
		</font>
<img src ="http://www.cppblog.com/apollo/aggbug/4511.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-03-23 23:29 <a href="http://www.cppblog.com/apollo/articles/huawei.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>dynamic_cast详解</title><link>http://www.cppblog.com/apollo/articles/dynamic_cast.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Wed, 22 Mar 2006 15:37:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/dynamic_cast.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/4475.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/dynamic_cast.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/4475.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/4475.html</trackback:ping><description><![CDATA[作为四个内部类型转换操作符之一的dynamic_cast和传统的C风格的强制类型转换有着巨大的差别。除了dynamic_cast以外的转换，其行
为的都是在编译期就得以确定的，转换是否成功，并不依赖被转换的对象。而dynamic_cast则不然。在这里，不再讨论其他三种转换和C风格的转换。<br />
首先，dynamic_cast依赖于RTTI信息，其次，在转换时，dynamic_cast会检查转换的source对象是否真的可以转换成target类型，这种检查不是语法上的，而是真实情况的检查。<br />
先
看RTTI相关部分，通常，许多编译器都是通过vtable找到对象的RTTI信息的，这也就意味着，如果基类没有虚方法，也就无法判断一个基类指针变量
所指对象的真实类型,
这时候，dynamic_cast只能用来做安全的转换,例如从派生类指针转换成基类指针.而这种转换其实并不需要dynamic_cast参与.<br />
也就是说,dynamic_cast是根据RTTI记载的信息来判断类型转换是否合法的.<br /><br />
下面看一个例子:<br />
struct B1{<br />
    virtual ~B1(){}<br />
};<br />
struct B2{<br />
    virtual ~B2(){}<br />
};<br />
struct D1 : B1, B2{};<br />
int main()<br />
{<br />
    D1 d;<br />
    B1* pb1 = &amp;d;<br />
    B2* pb2 = dynamic_cast&lt;B2*&gt;(pb1);//L1<br />
    B2* pb22 = static_cast&lt;B2*&gt;(pb1);  //L2<br />
    return 0;<br />
}<br />
上述定义中可以看到,B1和B2是不相关的类,从L1可以看到,dynamic_cast允许这种转换:只要B1存在多态方法.<br />
L2将编译失败,static_cast并不允许两个完全不相干的类互相转换.<br /><br />
dynamic_cast的这种特性，在提取一个对象的某个接口的时候，非常有用，它很类似于实现了COM的QueryInterface的功能。<img src ="http://www.cppblog.com/apollo/aggbug/4475.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-03-22 23:37 <a href="http://www.cppblog.com/apollo/articles/dynamic_cast.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>vc++7.1转移到vc++2005 需要的一些变动</title><link>http://www.cppblog.com/apollo/articles/UpGrade.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Thu, 16 Mar 2006 14:21:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/UpGrade.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/4249.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/UpGrade.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/4249.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/4249.html</trackback:ping><description><![CDATA[<span style="color: rgb(0, 0, 255);"><strong>1.&nbsp;变量作用域 <br></strong></span>在vc7.1中, 如果一个变量定义在for语句的条件从句中，那么这个变量可以在for之后使用。但Vc8禁止这样，会报告一个C2065错误. 
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);">&nbsp;(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;i&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;&nbsp;i&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">10</span><span style="color: rgb(0, 0, 0);">;&nbsp;</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">i)&nbsp;&nbsp;<br><img id="Codehighlighter1_31_81_Open_Image" onclick="this.style.display='none'; Codehighlighter1_31_81_Open_Text.style.display='none'; Codehighlighter1_31_81_Closed_Image.style.display='inline'; Codehighlighter1_31_81_Closed_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_31_81_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_31_81_Closed_Text.style.display='none'; Codehighlighter1_31_81_Open_Image.style.display='inline'; Codehighlighter1_31_81_Open_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_31_81_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_31_81_Open_Text"><span style="color: rgb(0, 0, 0);">{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;<img src="http://www.cnblogs.com/Images/dot.gif"></span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">codes&nbsp;here</span><span style="color: rgb(0, 128, 0);"><br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"></span><span style="color: rgb(0, 0, 0);">}</span></span><span style="color: rgb(0, 0, 0);"><br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;(i&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">10</span><span style="color: rgb(0, 0, 0);">)..&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">error&nbsp;in&nbsp;Vc8</span><span style="color: rgb(0, 128, 0);"><br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);">&nbsp;(i&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;&nbsp;i&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">5</span><span style="color: rgb(0, 0, 0);">;&nbsp;</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">i)&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">error&nbsp;in&nbsp;Vc8</span></div>

<p>解决方法：<br>在for语句之前声明变量（可保证代码在vc7.1和vc8下同时编译通过）</p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;i&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);">&nbsp;(i&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;&nbsp;i&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">10</span><span style="color: rgb(0, 0, 0);">;&nbsp;</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">i)<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);">&nbsp;(i&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;&nbsp;i&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">5</span><span style="color: rgb(0, 0, 0);">;&nbsp;</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">i)</span></div>

<p><span style="color: rgb(0, 0, 255);"><strong>2.&nbsp;指针和引用的声明 <br></strong></span>在Vc7.1中, 下面的代码可以编译, 但是vc8会报C4430 错误。（很难想象有些美国程序员竟然这样声明）</p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 255);">const</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;a;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">error&nbsp;in&nbsp;VC8</span><span style="color: rgb(0, 128, 0);"><br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">const</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;b;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">error&nbsp;in&nbsp;VC8</span><span style="color: rgb(0, 128, 0);"><br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;myfun&nbsp;(</span><span style="color: rgb(0, 0, 255);">const</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">&nbsp;B);&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">error&nbsp;in&nbsp;VC8</span></div>

<p>解决方法：<br>把* 或&amp;放到类型的后面.</p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 255);">const</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">&nbsp;a;&nbsp;<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">const</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">&nbsp;b;<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;myfun&nbsp;(</span><span style="color: rgb(0, 0, 255);">const</span><span style="color: rgb(0, 0, 0);">&nbsp;B</span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">);</span></div>

<p><span style="color: rgb(0, 0, 255);"><strong>3.&nbsp;默认int类型 </strong></span><br>在vc7.1中，如果定义一个变量但不声明类型，那么默认为int。VC8不支持。<br></p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);">&nbsp;i&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;C4430&nbsp;error&nbsp;in&nbsp;Vc8&nbsp;</span><span style="color: rgb(0, 128, 0);"><br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">const</span><span style="color: rgb(0, 0, 0);">&nbsp;i&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">C4430&nbsp;error</span></div>

<p>解决方法：<br>加上int.<br></p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;i&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;&nbsp;<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">const</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;i&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;</span></div>

<p><span style="color: rgb(0, 0, 255);"><strong>4.&nbsp;函数的默认返回值类型 </strong></span><br>同上，VC8不支持把 int 作为默认返回值类</p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 0);">Func()<br><img id="Codehighlighter1_7_17_Open_Image" onclick="this.style.display='none'; Codehighlighter1_7_17_Open_Text.style.display='none'; Codehighlighter1_7_17_Closed_Image.style.display='inline'; Codehighlighter1_7_17_Closed_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_7_17_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_7_17_Closed_Text.style.display='none'; Codehighlighter1_7_17_Open_Image.style.display='inline'; Codehighlighter1_7_17_Open_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_7_17_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_7_17_Open_Text"><span style="color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;}</span></span><span style="color: rgb(0, 0, 0);">;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">error&nbsp;in&nbsp;VC8</span></div>

<p>解决方法：<br>明确声明函数返回值类型为 int.</p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;Func()<br><img id="Codehighlighter1_11_21_Open_Image" onclick="this.style.display='none'; Codehighlighter1_11_21_Open_Text.style.display='none'; Codehighlighter1_11_21_Closed_Image.style.display='inline'; Codehighlighter1_11_21_Closed_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_11_21_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_11_21_Closed_Text.style.display='none'; Codehighlighter1_11_21_Open_Image.style.display='inline'; Codehighlighter1_11_21_Open_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_11_21_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_11_21_Open_Text"><span style="color: rgb(0, 0, 0);">{</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;}</span></span><span style="color: rgb(0, 0, 0);">;</span></div>

<p><span style="color: rgb(0, 0, 255);"><strong>5.&nbsp;函数地址</strong></span><br>Vc7中函数名就是地址。在vc8中，必须要使用&amp;操作符同时写出这个方法的全名(fully qualified name). </p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;A<br><img id="Codehighlighter1_8_39_Open_Image" onclick="this.style.display='none'; Codehighlighter1_8_39_Open_Text.style.display='none'; Codehighlighter1_8_39_Closed_Image.style.display='inline'; Codehighlighter1_8_39_Closed_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_8_39_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_8_39_Closed_Text.style.display='none'; Codehighlighter1_8_39_Open_Image.style.display='inline'; Codehighlighter1_8_39_Open_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_8_39_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_8_39_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">:<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;Test(</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">);<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: rgb(0, 0, 0);">;<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;fun(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;(A::</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">test)&nbsp;(</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">));<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;main()&nbsp;<br><img id="Codehighlighter1_87_142_Open_Image" onclick="this.style.display='none'; Codehighlighter1_87_142_Open_Text.style.display='none'; Codehighlighter1_87_142_Closed_Image.style.display='inline'; Codehighlighter1_87_142_Closed_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_87_142_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_87_142_Closed_Text.style.display='none'; Codehighlighter1_87_142_Open_Image.style.display='inline'; Codehighlighter1_87_142_Open_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_87_142_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_87_142_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fun(A::Test);</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">C3867&nbsp;error&nbsp;in&nbsp;VC</span><span style="color: rgb(0, 128, 0);"><br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span></div>

<p>解决方法：<br>加上 &amp;.</p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 0);">fun(</span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">A::Test);</span></div>

<p><span style="color: rgb(0, 0, 255);"><strong>6.&nbsp;<span style="font-size: 12pt; font-family: 宋体;">隐式类型转换</span> <br></strong></span>VC8不允许B* 到const B*&amp;的隐式转换.</p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img id="Codehighlighter1_7_8_Open_Image" onclick="this.style.display='none'; Codehighlighter1_7_8_Open_Text.style.display='none'; Codehighlighter1_7_8_Closed_Image.style.display='inline'; Codehighlighter1_7_8_Closed_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_7_8_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_7_8_Closed_Text.style.display='none'; Codehighlighter1_7_8_Open_Image.style.display='inline'; Codehighlighter1_7_8_Open_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;B</span><span id="Codehighlighter1_7_8_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_7_8_Open_Text"><span style="color: rgb(0, 0, 0);">{}</span></span><span style="color: rgb(0, 0, 0);">;<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;fun&nbsp;(&nbsp;</span><span style="color: rgb(0, 0, 255);">const</span><span style="color: rgb(0, 0, 0);">&nbsp;B</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">&nbsp;);</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">if&nbsp;possible&nbsp;use&nbsp;const&nbsp;B*&nbsp;instead</span><span style="color: rgb(0, 128, 0);"><br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;main()&nbsp;<br><img id="Codehighlighter1_82_140_Open_Image" onclick="this.style.display='none'; Codehighlighter1_82_140_Open_Text.style.display='none'; Codehighlighter1_82_140_Closed_Image.style.display='inline'; Codehighlighter1_82_140_Closed_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_82_140_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_82_140_Closed_Text.style.display='none'; Codehighlighter1_82_140_Open_Image.style.display='inline'; Codehighlighter1_82_140_Open_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_82_140_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_82_140_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">B&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">test&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;B();<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">fun&nbsp;(test);&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">error&nbsp;in&nbsp;VC8</span><span style="color: rgb(0, 128, 0);"><br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span></div>

<p>解决方法：<br>强制转换或函数参数变成const B*。</p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;fun&nbsp;(&nbsp;</span><span style="color: rgb(0, 0, 255);">const</span><span style="color: rgb(0, 0, 0);">&nbsp;B</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;);</span></div>

<p><span style="color: rgb(0, 0, 255);"><strong>7.&nbsp;友元方法(Friend function) </strong></span><br>VC8不允许声明一个private或protected函数为友元.</p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;A<br><img id="Codehighlighter1_8_32_Open_Image" onclick="this.style.display='none'; Codehighlighter1_8_32_Open_Text.style.display='none'; Codehighlighter1_8_32_Closed_Image.style.display='inline'; Codehighlighter1_8_32_Closed_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_8_32_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_8_32_Closed_Text.style.display='none'; Codehighlighter1_8_32_Open_Image.style.display='inline'; Codehighlighter1_8_32_Open_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_8_32_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_8_32_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">:<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;c();&nbsp;&nbsp;<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: rgb(0, 0, 0);">;<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;B<br><img id="Codehighlighter1_43_111_Open_Image" onclick="this.style.display='none'; Codehighlighter1_43_111_Open_Text.style.display='none'; Codehighlighter1_43_111_Closed_Image.style.display='inline'; Codehighlighter1_43_111_Closed_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_43_111_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_43_111_Closed_Text.style.display='none'; Codehighlighter1_43_111_Open_Image.style.display='inline'; Codehighlighter1_43_111_Open_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_43_111_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_43_111_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;friend&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;A::c();&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">C2248&nbsp;error,&nbsp;c()&nbsp;is&nbsp;invisible&nbsp;to&nbsp;class&nbsp;B.</span><span style="color: rgb(0, 128, 0);"><br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"></span><span style="color: rgb(0, 0, 0);">}</span></span><span style="color: rgb(0, 0, 0);">;</span></div>

<p>解决方法 1:<br>声明友元类.</p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;A<br><img id="Codehighlighter1_8_32_Open_Image" onclick="this.style.display='none'; Codehighlighter1_8_32_Open_Text.style.display='none'; Codehighlighter1_8_32_Closed_Image.style.display='inline'; Codehighlighter1_8_32_Closed_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_8_32_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_8_32_Closed_Text.style.display='none'; Codehighlighter1_8_32_Open_Image.style.display='inline'; Codehighlighter1_8_32_Open_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_8_32_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_8_32_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);">:<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;c();&nbsp;&nbsp;<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: rgb(0, 0, 0);">;<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;B<br><img id="Codehighlighter1_43_63_Open_Image" onclick="this.style.display='none'; Codehighlighter1_43_63_Open_Text.style.display='none'; Codehighlighter1_43_63_Closed_Image.style.display='inline'; Codehighlighter1_43_63_Closed_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_43_63_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_43_63_Closed_Text.style.display='none'; Codehighlighter1_43_63_Open_Image.style.display='inline'; Codehighlighter1_43_63_Open_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_43_63_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_43_63_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;friend&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;A;<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: rgb(0, 0, 0);">;</span></div>

<p>解决方法 2:<br>把函数声明为public</p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;A<br><img id="Codehighlighter1_8_31_Open_Image" onclick="this.style.display='none'; Codehighlighter1_8_31_Open_Text.style.display='none'; Codehighlighter1_8_31_Closed_Image.style.display='inline'; Codehighlighter1_8_31_Closed_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_8_31_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_8_31_Closed_Text.style.display='none'; Codehighlighter1_8_31_Open_Image.style.display='inline'; Codehighlighter1_8_31_Open_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_8_31_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_8_31_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">:<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;c();&nbsp;&nbsp;<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: rgb(0, 0, 0);">;<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;B<br><img id="Codehighlighter1_42_66_Open_Image" onclick="this.style.display='none'; Codehighlighter1_42_66_Open_Text.style.display='none'; Codehighlighter1_42_66_Closed_Image.style.display='inline'; Codehighlighter1_42_66_Closed_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_42_66_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_42_66_Closed_Text.style.display='none'; Codehighlighter1_42_66_Open_Image.style.display='inline'; Codehighlighter1_42_66_Open_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_42_66_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_42_66_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;friend&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;A::c();<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: rgb(0, 0, 0);">;</span></div>

<p><span style="color: rgb(0, 0, 255);"><strong>8.&nbsp;STL的stdext 命名空间</strong></span><br>在vc8中，hash_map 和hash_set 被移进了stdext命名空间中.</p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 0);">#include&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">hash_map</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">std::hash_map&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">error&nbsp;in&nbsp;VC8</span></div>

<p>解决方法：<br>使用stdext 命名空间.</p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 0);">#include&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">hash_map</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">stdext::hash_map</span></div>

<p><span style="color: rgb(0, 0, 255);"><strong>9.&nbsp;头文件 </strong></span><br>许多头文件如fstream.h 和iostream.h在VC8中已经不存在了.</p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 0);">#include&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">fstream.h</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">error&nbsp;in&nbsp;VC8</span></div>

<p>解决方法：<br>使用STL.</p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 0);">#include&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">fstream</span><span style="color: rgb(0, 0, 0);">&gt;</span></div>

<p><span style="color: rgb(0, 0, 255);"><strong>10.&nbsp;Iterator </strong></span><br>一些 STL 类, iterators 不再用指针实现</p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 0);">std::vector</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">DMDetailRow</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;m_data;<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">std::vector</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">DMDetailRow</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">::iterator&nbsp;iter&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">m_data[rowNum];</span></div>

<p>解决方法：</p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 0);">std::vector</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">DMDetailRow</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">::iterator&nbsp;Iter&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;m_data.begin()&nbsp;</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">&nbsp;rowNum;</span></div>

<p><span style="color: rgb(0, 0, 255);"><strong>11.&nbsp;Enum </strong></span><br>使用一个Enum的成员时，不要使用enum的名字</p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 255);">enum</span><span style="color: rgb(0, 0, 0);">&nbsp;E<br><img id="Codehighlighter1_7_17_Open_Image" onclick="this.style.display='none'; Codehighlighter1_7_17_Open_Text.style.display='none'; Codehighlighter1_7_17_Closed_Image.style.display='inline'; Codehighlighter1_7_17_Closed_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_7_17_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_7_17_Closed_Text.style.display='none'; Codehighlighter1_7_17_Open_Image.style.display='inline'; Codehighlighter1_7_17_Open_Text.style.display='inline';" src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_7_17_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_7_17_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;a,b,c<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: rgb(0, 0, 0);">;<br><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">E&nbsp;e1&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;E::a;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">warning&nbsp;in&nbsp;VC8</span></div>

<p>解决方法：<br>去掉Enum 的名字.</p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://vinceyuan.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 0);">E&nbsp;e1&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;a;</span></div>
<img src ="http://www.cppblog.com/apollo/aggbug/4249.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-03-16 22:21 <a href="http://www.cppblog.com/apollo/articles/UpGrade.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C模拟C++中的继承</title><link>http://www.cppblog.com/apollo/articles/CsimulateCPP.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Thu, 16 Mar 2006 07:04:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/CsimulateCPP.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/4239.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/CsimulateCPP.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/4239.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/4239.html</trackback:ping><description><![CDATA[<P>比如在一个项目中，有大量的数据结构，他们都是双向链表，但又想共用一套对链表的操作算法，这怎么做到呢，C中又没有C++中的继承，不然我可以继承一父（类中只有两个指针，一个向前一个向后），而其算法可以写在你类中的虚函数中，供子类使用。如：</P>
<P><FONT face="Courier New">class Links<BR>{<BR>public:<BR>&nbsp;&nbsp;&nbsp; Links* back;<BR>&nbsp;&nbsp;&nbsp; Links* forword;</FONT></P>
<P><FONT face="Courier New">&nbsp;&nbsp;&nbsp; virtual Add(){ ... };<BR>&nbsp;&nbsp;&nbsp; virtual Del(){ ... };<BR>&nbsp;&nbsp;&nbsp; virtual Ins(){ ... };<BR>&nbsp;&nbsp;&nbsp; virtual Print() =0;<BR>&nbsp;&nbsp;&nbsp; ....</FONT></P>
<P><FONT face="Courier New">};</FONT></P>
<P>于是对于特定的数据结构我们可以：<BR><FONT face="Courier New">class mylinks : public Links <BR>{ <BR>public:<BR>&nbsp;&nbsp;&nbsp; char* myname;<BR>&nbsp;&nbsp;&nbsp; char sex;<BR>&nbsp;&nbsp;&nbsp; int&nbsp; age;<BR>&nbsp;&nbsp;&nbsp; ... <BR>&nbsp;&nbsp;&nbsp; virtual Print(){ .... }</FONT></P>
<P><FONT face="Courier New">};<BR></FONT>对其操作时都可以使用你类的泛型算法。</P>
<P><BR>在C中，该如何做呢？我们用C中的指针和强制类型转可以做到。</P>
<P>下面是我总结出来的一个小的程序，体现了用指针的弹性来实现这一继承的效果：<BR>（我在Liniux下的GCC调试通过）</P>
<P><FONT face="Courier New">=======================================</FONT><BR>
<DIV style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #008080">&nbsp;1</SPAN><IMG src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">#include&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">stdio.h</SPAN><SPAN style="COLOR: #000000">&gt;</SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;2</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;3</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_20_36_Open_Image onclick="this.style.display='none'; Codehighlighter1_20_36_Open_Text.style.display='none'; Codehighlighter1_20_36_Closed_Image.style.display='inline'; Codehighlighter1_20_36_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_20_36_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_20_36_Closed_Text.style.display='none'; Codehighlighter1_20_36_Open_Image.style.display='inline'; Codehighlighter1_20_36_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN id=Codehighlighter1_20_36_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</SPAN><SPAN id=Codehighlighter1_20_36_Open_Text><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">&nbsp;双向链表&nbsp;（类似于父类）</SPAN><SPAN style="COLOR: #008000">*/</SPAN></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;4</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_59_113_Open_Image onclick="this.style.display='none'; Codehighlighter1_59_113_Open_Text.style.display='none'; Codehighlighter1_59_113_Closed_Image.style.display='inline'; Codehighlighter1_59_113_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_59_113_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_59_113_Closed_Text.style.display='none'; Codehighlighter1_59_113_Open_Image.style.display='inline'; Codehighlighter1_59_113_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align=top>typedef&nbsp;</SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;hLinks</SPAN><SPAN id=Codehighlighter1_59_113_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cppblog.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_59_113_Open_Text><SPAN style="COLOR: #000000">{<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;5</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;hLinks&nbsp;</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">bwLink;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;6</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;hLinks&nbsp;</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">fwLink;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;7</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN><SPAN style="COLOR: #000000">&nbsp;hLinks;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;8</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;9</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">10</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_125_160_Open_Image onclick="this.style.display='none'; Codehighlighter1_125_160_Open_Text.style.display='none'; Codehighlighter1_125_160_Closed_Image.style.display='inline'; Codehighlighter1_125_160_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_125_160_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_125_160_Closed_Text.style.display='none'; Codehighlighter1_125_160_Open_Image.style.display='inline'; Codehighlighter1_125_160_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN id=Codehighlighter1_125_160_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</SPAN><SPAN id=Codehighlighter1_125_160_Open_Text><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #008080">11</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;*&nbsp;一个使用双向链表的结构<BR></SPAN><SPAN style="COLOR: #008080">12</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;（类似于子类）<BR></SPAN><SPAN style="COLOR: #008080">13</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">14</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_181_231_Open_Image onclick="this.style.display='none'; Codehighlighter1_181_231_Open_Text.style.display='none'; Codehighlighter1_181_231_Closed_Image.style.display='inline'; Codehighlighter1_181_231_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_181_231_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_181_231_Closed_Text.style.display='none'; Codehighlighter1_181_231_Open_Image.style.display='inline'; Codehighlighter1_181_231_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align=top>typedef&nbsp;</SPAN><SPAN style="COLOR: #0000ff">struct</SPAN><SPAN style="COLOR: #000000">&nbsp;hEnt</SPAN><SPAN id=Codehighlighter1_181_231_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cppblog.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_181_231_Open_Text><SPAN style="COLOR: #000000">{<BR></SPAN><SPAN style="COLOR: #008080">15</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;hLinks&nbsp;links;<BR></SPAN><SPAN style="COLOR: #008080">16</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;hData;<BR></SPAN><SPAN style="COLOR: #008080">17</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">char</SPAN><SPAN style="COLOR: #000000">&nbsp;key[</SPAN><SPAN style="COLOR: #000000">10</SPAN><SPAN style="COLOR: #000000">];<BR></SPAN><SPAN style="COLOR: #008080">18</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN><SPAN style="COLOR: #000000">&nbsp;hEnt;<BR></SPAN><SPAN style="COLOR: #008080">19</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">20</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">21</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_241_274_Open_Image onclick="this.style.display='none'; Codehighlighter1_241_274_Open_Text.style.display='none'; Codehighlighter1_241_274_Closed_Image.style.display='inline'; Codehighlighter1_241_274_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_241_274_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_241_274_Closed_Text.style.display='none'; Codehighlighter1_241_274_Open_Image.style.display='inline'; Codehighlighter1_241_274_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN id=Codehighlighter1_241_274_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</SPAN><SPAN id=Codehighlighter1_241_274_Open_Text><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #008080">22</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;*&nbsp;&nbsp;双向链插入泛型算法&nbsp;（类似于父数中的成员函数）<BR></SPAN><SPAN style="COLOR: #008080">23</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">24</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align=top>Insert(&nbsp;hLinks</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">&nbsp;elem,&nbsp;hLinks&nbsp;</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">dest&nbsp;)<BR></SPAN><SPAN style="COLOR: #008080">25</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_313_461_Open_Image onclick="this.style.display='none'; Codehighlighter1_313_461_Open_Text.style.display='none'; Codehighlighter1_313_461_Closed_Image.style.display='inline'; Codehighlighter1_313_461_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_313_461_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_313_461_Closed_Text.style.display='none'; Codehighlighter1_313_461_Open_Image.style.display='inline'; Codehighlighter1_313_461_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN id=Codehighlighter1_313_461_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cppblog.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_313_461_Open_Text><SPAN style="COLOR: #000000">{<BR></SPAN><SPAN style="COLOR: #008080">26</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(&nbsp;</SPAN><SPAN style="COLOR: #000000">!</SPAN><SPAN style="COLOR: #000000">elem&nbsp;</SPAN><SPAN style="COLOR: #000000">||</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">!</SPAN><SPAN style="COLOR: #000000">dest&nbsp;)&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">;<BR></SPAN><SPAN style="COLOR: #008080">27</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">28</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;elem</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">bwLink&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;dest</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">bwLink;<BR></SPAN><SPAN style="COLOR: #008080">29</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;elem</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">fwLink&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;dest;<BR></SPAN><SPAN style="COLOR: #008080">30</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;dest</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">bwLink</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">fwLink&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;elem;<BR></SPAN><SPAN style="COLOR: #008080">31</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;dest</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">bwLink&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;elem;<BR></SPAN><SPAN style="COLOR: #008080">32</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">33</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">34</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">35</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_465_494_Open_Image onclick="this.style.display='none'; Codehighlighter1_465_494_Open_Text.style.display='none'; Codehighlighter1_465_494_Closed_Image.style.display='inline'; Codehighlighter1_465_494_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_465_494_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_465_494_Closed_Text.style.display='none'; Codehighlighter1_465_494_Open_Image.style.display='inline'; Codehighlighter1_465_494_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN id=Codehighlighter1_465_494_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</SPAN><SPAN id=Codehighlighter1_465_494_Open_Text><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #008080">36</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;*&nbsp;&nbsp;打印&nbsp;（类似于子类重载父类的成员函数）<BR></SPAN><SPAN style="COLOR: #008080">37</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">38</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align=top>PrintLink(&nbsp;hLinks&nbsp;</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">h&nbsp;)<BR></SPAN><SPAN style="COLOR: #008080">39</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_519_751_Open_Image onclick="this.style.display='none'; Codehighlighter1_519_751_Open_Text.style.display='none'; Codehighlighter1_519_751_Closed_Image.style.display='inline'; Codehighlighter1_519_751_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_519_751_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_519_751_Closed_Text.style.display='none'; Codehighlighter1_519_751_Open_Image.style.display='inline'; Codehighlighter1_519_751_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN id=Codehighlighter1_519_751_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cppblog.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_519_751_Open_Text><SPAN style="COLOR: #000000">{<BR></SPAN><SPAN style="COLOR: #008080">40</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;hEnt&nbsp;</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">p&nbsp;;<BR></SPAN><SPAN style="COLOR: #008080">41</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">42</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_574_603_Open_Image onclick="this.style.display='none'; Codehighlighter1_574_603_Open_Text.style.display='none'; Codehighlighter1_574_603_Closed_Image.style.display='inline'; Codehighlighter1_574_603_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_574_603_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_574_603_Closed_Text.style.display='none'; Codehighlighter1_574_603_Open_Image.style.display='inline'; Codehighlighter1_574_603_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">(&nbsp;p&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;(&nbsp;hEnt</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">&nbsp;)&nbsp;h</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">fwLink;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN id=Codehighlighter1_574_603_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</SPAN><SPAN id=Codehighlighter1_574_603_Open_Text><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">&nbsp;&nbsp;&lt;-----------把hLink再转回来&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">43</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;</SPAN><SPAN style="COLOR: #000000">!=</SPAN><SPAN style="COLOR: #000000">&nbsp;(&nbsp;hEnt</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">&nbsp;)&nbsp;h;<BR></SPAN><SPAN style="COLOR: #008080">44</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;(&nbsp;hEnt</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">&nbsp;)(&nbsp;(hLinks</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">)p&nbsp;)</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">fwLink&nbsp;)<BR></SPAN><SPAN style="COLOR: #008080">45</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_683_749_Open_Image onclick="this.style.display='none'; Codehighlighter1_683_749_Open_Text.style.display='none'; Codehighlighter1_683_749_Closed_Image.style.display='inline'; Codehighlighter1_683_749_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_683_749_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_683_749_Closed_Text.style.display='none'; Codehighlighter1_683_749_Open_Image.style.display='inline'; Codehighlighter1_683_749_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN id=Codehighlighter1_683_749_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cppblog.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_683_749_Open_Text><SPAN style="COLOR: #000000">{<BR></SPAN><SPAN style="COLOR: #008080">46</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">hData=[%d],&nbsp;key=[%s]\n</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;p</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">hData,&nbsp;p</SPAN><SPAN style="COLOR: #000000">-&gt;</SPAN><SPAN style="COLOR: #000000">key);<BR></SPAN><SPAN style="COLOR: #008080">47</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">48</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">49</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">50</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align=top>&nbsp;<BR></SPAN><SPAN style="COLOR: #008080">51</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">52</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align=top>main()<BR></SPAN><SPAN style="COLOR: #008080">53</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_764_1113_Open_Image onclick="this.style.display='none'; Codehighlighter1_764_1113_Open_Text.style.display='none'; Codehighlighter1_764_1113_Closed_Image.style.display='inline'; Codehighlighter1_764_1113_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_764_1113_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_764_1113_Closed_Text.style.display='none'; Codehighlighter1_764_1113_Open_Image.style.display='inline'; Codehighlighter1_764_1113_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN id=Codehighlighter1_764_1113_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cppblog.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_764_1113_Open_Text><SPAN style="COLOR: #000000">{<BR></SPAN><SPAN style="COLOR: #008080">54</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;hLinks&nbsp;head;<BR></SPAN><SPAN style="COLOR: #008080">55</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;hEnt&nbsp;a[</SPAN><SPAN style="COLOR: #000000">4</SPAN><SPAN style="COLOR: #000000">];<BR></SPAN><SPAN style="COLOR: #008080">56</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;i;<BR></SPAN><SPAN style="COLOR: #008080">57</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">58</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;head.bwLink&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #000000">head;<BR></SPAN><SPAN style="COLOR: #008080">59</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;head.fwLink&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #000000">head;<BR></SPAN><SPAN style="COLOR: #008080">60</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">61</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">(i</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;i</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">4</SPAN><SPAN style="COLOR: #000000">;i</SPAN><SPAN style="COLOR: #000000">++</SPAN><SPAN style="COLOR: #000000">)<BR></SPAN><SPAN style="COLOR: #008080">62</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_879_1049_Open_Image onclick="this.style.display='none'; Codehighlighter1_879_1049_Open_Text.style.display='none'; Codehighlighter1_879_1049_Closed_Image.style.display='inline'; Codehighlighter1_879_1049_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_879_1049_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_879_1049_Closed_Text.style.display='none'; Codehighlighter1_879_1049_Open_Image.style.display='inline'; Codehighlighter1_879_1049_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;</SPAN><SPAN id=Codehighlighter1_879_1049_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.cppblog.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_879_1049_Open_Text><SPAN style="COLOR: #000000">{<BR></SPAN><SPAN style="COLOR: #008080">63</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a[i].hData&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;i</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">10</SPAN><SPAN style="COLOR: #000000">;<BR></SPAN><SPAN style="COLOR: #008080">64</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sprintf(a[i].key,</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">id=%d</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;i);<BR></SPAN><SPAN style="COLOR: #008080">65</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">66</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_949_967_Open_Image onclick="this.style.display='none'; Codehighlighter1_949_967_Open_Text.style.display='none'; Codehighlighter1_949_967_Closed_Image.style.display='inline'; Codehighlighter1_949_967_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_949_967_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_949_967_Closed_Text.style.display='none'; Codehighlighter1_949_967_Open_Image.style.display='inline'; Codehighlighter1_949_967_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN id=Codehighlighter1_949_967_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</SPAN><SPAN id=Codehighlighter1_949_967_Open_Text><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">&nbsp;&nbsp;使用泛型算法构造双向链&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN></SPAN><SPAN style="COLOR: #000000">&nbsp;<BR></SPAN><SPAN style="COLOR: #008080">67</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_1022_1044_Open_Image onclick="this.style.display='none'; Codehighlighter1_1022_1044_Open_Text.style.display='none'; Codehighlighter1_1022_1044_Closed_Image.style.display='inline'; Codehighlighter1_1022_1044_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_1022_1044_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1022_1044_Closed_Text.style.display='none'; Codehighlighter1_1022_1044_Open_Image.style.display='inline'; Codehighlighter1_1022_1044_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Insert(&nbsp;(hLinks&nbsp;</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">)&nbsp;</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #000000">a[i],&nbsp;(hLinks&nbsp;</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">)&nbsp;</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #000000">head&nbsp;);&nbsp;</SPAN><SPAN id=Codehighlighter1_1022_1044_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</SPAN><SPAN id=Codehighlighter1_1022_1044_Open_Text><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">&nbsp;&nbsp;&nbsp;&lt;-----注意这个强制转换&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">68</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">69</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/InBlock.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">70</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_1086_1111_Open_Image onclick="this.style.display='none'; Codehighlighter1_1086_1111_Open_Text.style.display='none'; Codehighlighter1_1086_1111_Closed_Image.style.display='inline'; Codehighlighter1_1086_1111_Closed_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_1086_1111_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1086_1111_Closed_Text.style.display='none'; Codehighlighter1_1086_1111_Open_Image.style.display='inline'; Codehighlighter1_1086_1111_Open_Text.style.display='inline';" src="http://www.cppblog.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;PrintLink(&nbsp;(hLinks&nbsp;</SPAN><SPAN style="COLOR: #000000">*</SPAN><SPAN style="COLOR: #000000">)&nbsp;</SPAN><SPAN style="COLOR: #000000">&amp;</SPAN><SPAN style="COLOR: #000000">head&nbsp;);&nbsp;</SPAN><SPAN id=Codehighlighter1_1086_1111_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**/</SPAN><SPAN id=Codehighlighter1_1086_1111_Open_Text><SPAN style="COLOR: #008000">/*</SPAN><SPAN style="COLOR: #008000">&nbsp;&nbsp;&nbsp;&lt;-------也注意这个强制转换&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">*/</SPAN></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">71</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">72</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">73</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.cppblog.com/images/OutliningIndicators/None.gif" align=top></SPAN></DIV></P><img src ="http://www.cppblog.com/apollo/aggbug/4239.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-03-16 15:04 <a href="http://www.cppblog.com/apollo/articles/CsimulateCPP.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>文件操作</title><link>http://www.cppblog.com/apollo/articles/4155.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Tue, 14 Mar 2006 14:33:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/4155.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/4155.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/4155.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/4155.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/4155.html</trackback:ping><description><![CDATA[<STRONG>一、ASCII 输出<BR><BR></STRONG>　　为了使用下面的方法, 你必须包含头文件&lt;fstream.h&gt;(译者注：在标准C++中，已经使用&lt;fstream&gt;取代&lt;fstream.h&gt;，所有的C++标准头文件都是无后缀的。)。这是 &lt;iostream.h&gt;的一个扩展集, 提供有缓冲的文件输入输出操作. 事实上, &lt;iostream.h&gt; 已经被&lt;fstream.h&gt;包含了, 所以你不必包含所有这两个文件, 如果你想显式包含他们，那随便你。我们从文件操作类的设计开始, 我会讲解如何进行ASCII I/O操作。 如果你猜是"fstream," 恭喜你答对了！ 但这篇文章介绍的方法,我们分别使用"ifstream"?和 "ofstream" 来作输入输出。<BR><BR>　　如果你用过标准控制台流"cin"?和 "cout," 那现在的事情对你来说很简单。 我们现在开始讲输出部分，首先声明一个类对象。ofstream fout; <BR><BR>　　这就可以了，不过你要打开一个文件的话, 必须像这样调用ofstream::open()。<BR><BR>
<TABLE borderColor=#ffcc66 cellPadding=1 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>fout.open("output.txt"); </TD></TR></TBODY></TABLE><BR>　　你也可以把文件名作为构造参数来打开一个文件.<BR><BR>
<TABLE borderColor=#ffcc66 cellPadding=1 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>ofstream fout("output.txt");</TD></TR></TBODY></TABLE><BR>　　这是我们使用的方法, 因为这样创建和打开一个文件看起来更简单. 顺便说一句, 如果你要打开的文件不存在，它会为你创建一个, 所以不用担心文件创建的问题. 现在就输出到文件，看起来和"cout"的操作很像。 对不了解控制台输出"cout"的人, 这里有个例子。<BR><BR>
<TABLE borderColor=#ffcc66 cellPadding=1 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>int num = 150;<BR>char name[] = "John Doe";<BR>fout &lt;&lt; "Here is a number: " &lt;&lt; num &lt;&lt; "\n";<BR>fout &lt;&lt; "Now here is a string: " &lt;&lt; name &lt;&lt; "\n";</TD></TR></TBODY></TABLE><BR>　　现在保存文件，你必须关闭文件，或者回写文件缓冲. 文件关闭之后就不能再操作了, 所以只有在你不再操作这个文件的时候才调用它，它会自动保存文件。 回写缓冲区会在保持文件打开的情况下保存文件, 所以只要有必要就使用它。 回写看起来像另一次输出, 然后调用方法关闭。像这样：<BR><BR>
<TABLE borderColor=#ffcc66 cellPadding=1 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>fout &lt;&lt; flush; fout.close(); </TD></TR></TBODY></TABLE><BR>　　 现在你用文本编辑器打开文件，内容看起来是这样：<BR><BR>　　Here is a number: 150 Now here is a string: John Doe <BR><BR>　　很简单吧! 现在继续文件输入, 需要一点技巧, 所以先确认你已经明白了流操作，对 "&lt;&lt;" 和"&gt;&gt;" 比较熟悉了, 因为你接下来还要用到他们。继续…<BR><BR>　　<B>二、ASCII 输入</B><BR><BR>　　输入和"cin" 流很像. 和刚刚讨论的输出流很像, 但你要考虑几件事情。在我们开始复杂的内容之前, 先看一个文本：<BR><BR>　　12 GameDev 15.45 L This is really awesome! <BR><BR>　　为了打开这个文件，你必须创建一个in-stream对象,?像这样。<BR><BR>
<TABLE borderColor=#ffcc66 cellPadding=1 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>ifstream fin("input.txt"); </TD></TR></TBODY></TABLE><BR>　　现在读入前四行. 你还记得怎么用"&lt;&lt;" 操作符往流里插入变量和符号吧？好,?在 "&lt;&lt;" (插入)?操作符之后，是"&gt;&gt;" (提取) 操作符. 使用方法是一样的. 看这个代码片段.<BR><BR>
<TABLE borderColor=#ffcc66 cellPadding=1 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>int number; <BR>float real; <BR>char letter, word[8]; <BR>fin &gt;&gt; number; fin &gt;&gt; word; fin &gt;&gt; real; fin &gt;&gt; letter; </TD></TR></TBODY></TABLE><BR>　　也可以把这四行读取文件的代码写为更简单的一行。<BR><BR>
<TABLE borderColor=#ffcc66 cellPadding=1 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>fin &gt;&gt; number &gt;&gt; word &gt;&gt; real &gt;&gt; letter; </TD></TR></TBODY></TABLE><BR>　　它是如何运作的呢? 文件的每个空白之后, "&gt;&gt;" 操作符会停止读取内容, 直到遇到另一个&gt;&gt;操作符. 因为我们读取的每一行都被换行符分割开(是空白字符), "&gt;&gt;" 操作符只把这一行的内容读入变量。这就是这个代码也能正常工作的原因。但是，可别忘了文件的最后一行。<BR><BR>　　This is really awesome! <BR><BR>　　如果你想把整行读入一个char数组, 我们没办法用"&gt;&gt;"?操作符，因为每个单词之间的空格（空白字符）会中止文件的读取。为了验证：<BR><BR>
<TABLE borderColor=#ffcc66 cellPadding=1 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>char sentence[101]; fin &gt;&gt; sentence; </TD></TR></TBODY></TABLE><BR>　　我们想包含整个句子, "This is really awesome!" 但是因为空白, 现在它只包含了"This". 很明显, 肯定有读取整行的方法, 它就是getline()。这就是我们要做的。<BR><BR>
<TABLE borderColor=#ffcc66 cellPadding=1 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>fin.getline(sentence, 100);</TD></TR></TBODY></TABLE><BR>　　这是函数参数. 第一个参数显然是用来接受的char数组. 第二个参数是在遇到换行符之前，数组允许接受的最大元素数量. 现在我们得到了想要的结果：“This is really awesome!”。<BR><BR>　　你应该已经知道如何读取和写入ASCII文件了。但我们还不能罢休，因为二进制文件还在等着我们。<BR><BR><SPAN class=f14><FONT size=3>　　<B>三、二进制 输入输出</B><BR><BR>　　二进制文件会复杂一点, 但还是很简单的。 首先你要注意我们不再使用插入和提取操作符(译者注：&lt;&lt; 和 &gt;&gt; 操作符). 你可以这么做，但它不会用二进制方式读写。你必须使用read() 和write() 方法读取和写入二进制文件. 创建一个二进制文件, 看下一行。<BR><BR></FONT>
<TABLE borderColor=#ffcc66 cellPadding=1 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>ofstream fout("file.dat", ios::binary); </TD></TR></TBODY></TABLE><BR>　　这会以二进制方式打开文件, 而不是默认的ASCII模式。首先从写入文件开始。函数write() 有两个参数。 第一个是指向对象的char类型的指针, 第二个是对象的大小（译者注：字节数）。 为了说明，看例子。<BR><BR>
<TABLE borderColor=#ffcc66 cellPadding=1 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>int number = 30; fout.write((char *)(&amp;number), sizeof(number)); </TD></TR></TBODY></TABLE><BR>　　第一个参数写做"(char *)(&amp;number)". 这是把一个整型变量转为char *指针。如果你不理解，可以立刻翻阅C++的书籍，如果有必要的话。第二个参数写作"sizeof(number)". sizeof() 返回对象大小的字节数. 就是这样!<BR><BR>　　二进制文件最好的地方是可以在一行把一个结构写入文件。 如果说，你的结构有12个不同的成员。 用ASCII?文件，你不得不每次一条的写入所有成员。 但二进制文件替你做好了。 看这个。<BR><BR>
<TABLE borderColor=#ffcc66 cellPadding=1 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>struct OBJECT { int number; char letter; } obj; <BR>obj.number = 15;<BR>obj.letter = ‘M’; <BR>fout.write((char *)(&amp;obj), sizeof(obj)); </TD></TR></TBODY></TABLE><BR>　　这样就写入了整个结构! 接下来是输入. 输入也很简单，因为read()?函数的参数和 write()是完全一样的, 使用方法也相同。<BR><BR>
<TABLE borderColor=#ffcc66 cellPadding=1 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>ifstream fin("file.dat", ios::binary); fin.read((char *)(&amp;obj), sizeof(obj)); </TD></TR></TBODY></TABLE><BR>　　我不多解释用法, 因为它和write()是完全相同的。二进制文件比ASCII文件简单, 但有个缺点是无法用文本编辑器编辑。 接着, 我解释一下ifstream 和ofstream 对象的其他一些方法作为结束.<BR><BR>　　<B>四、更多方法</B><BR><BR>　　我已经解释了ASCII文件和二进制文件, 这里是一些没有提及的底层方法。<BR><BR>　　检查文件<BR><BR>　　你已经学会了open() 和close() 方法, 不过这里还有其它你可能用到的方法。<BR><BR>　　方法good() 返回一个布尔值，表示文件打开是否正确。<BR><BR>　　类似的，bad() 返回一个布尔值表示文件打开是否错误。 如果出错，就不要继续进一步的操作了。 <BR><BR>　　最后一个检查的方法是fail(), 和bad()有点相似, 但没那么严重。<BR><BR>　　读文件<BR><BR>　　方法get() 每次返回一个字符。<BR><BR>　　方法ignore(int,char) 跳过一定数量的某个字符, 但你必须传给它两个参数。第一个是需要跳过的字符数。 第二个是一个字符, 当遇到的时候就会停止。 例子,<BR><BR>
<TABLE borderColor=#ffcc66 cellPadding=1 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>fin.ignore(100, ‘\n’);</TD></TR></TBODY></TABLE><BR>　　会跳过100个字符，或者不足100的时候，跳过所有之前的字符，包括 ‘\n’。<BR><BR>　　方法peek() 返回文件中的下一个字符, 但并不实际读取它。所以如果你用peek() 查看下一个字符, 用get() 在peek()之后读取，会得到同一个字符, 然后移动文件计数器。<BR><BR>　　方法putback(char) 输入字符, 一次一个, 到流中。我没有见到过它的使用，但这个函数确实存在。<BR><BR>　　写文件<BR><BR>　　只有一个你可能会关注的方法.?那就是 put(char), 它每次向输出流中写入一个字符。<BR><BR>　　打开文件<BR><BR>　　当我们用这样的语法打开二进制文件:<BR><BR>
<TABLE borderColor=#ffcc66 cellPadding=1 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>ofstream fout("file.dat", ios::binary); </TD></TR></TBODY></TABLE><BR>　　"ios::binary"是你提供的打开选项的额外标志. 默认的, 文件以ASCII方式打开, 不存在则创建, 存在就覆盖. 这里有些额外的标志用来改变选项。<BR><BR>　　ios::app 添加到文件尾 <BR>　　ios::ate 把文件标志放在末尾而非起始。 <BR>　　ios::trunc 默认. 截断并覆写文件。 <BR>　　ios::nocreate 文件不存在也不创建。 <BR>　　ios::noreplace 文件存在则失败。 <BR><BR>　　文件状态<BR><BR>　　我用过的唯一一个状态函数是eof(), 它返回是否标志已经到了文件末尾。 我主要用在循环中。 例如, 这个代码断统计小写‘e’ 在文件中出现的次数。<BR><BR>
<TABLE borderColor=#ffcc66 cellPadding=1 width="90%" align=center bgColor=#dadacf border=1>
<TBODY>
<TR>
<TD>ifstream fin("file.txt"); <BR>char ch; int counter; <BR>while (!fin.eof()) {<BR>ch = fin.get(); <BR>if (ch == ‘e’) counter++; <BR>}<BR>fin.close(); </TD></TR></TBODY></TABLE><BR>　　我从未用过这里没有提到的其他方法。 还有很多方法，但是他们很少被使用。参考C++书籍或者文件流的帮助文档来了解其他的方法。<BR></SPAN><img src ="http://www.cppblog.com/apollo/aggbug/4155.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-03-14 22:33 <a href="http://www.cppblog.com/apollo/articles/4155.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>函数对象替代函数指针作回调函数 </title><link>http://www.cppblog.com/apollo/articles/4153.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Tue, 14 Mar 2006 13:34:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/4153.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/4153.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/4153.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/4153.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/4153.html</trackback:ping><description><![CDATA[<P>函数指针实在是个讨厌的东西，说实话，我很讨厌他的语法，非常丑陋，而且有很多局限性，起码不能保有数据，函数对象是一个替换函数指针的好东东，通过重载operator()操作符，可以实现与函数指针几乎完全一致的功能。最近在看《C++必知必会》，里面讲到用函数对象替代函数指针，还有例子，觉得很好，贴出来，供兄弟们一起参考研究。</P>
<P>下面的代码并不复杂，先定义了一个基类函数对象Action，Button类带有一个Action的指针，作为其回调函数，在setAction中设置回调。由于Action是一个基类，所有继承了Action的继承类如PlayMusic都可以被Button调用，而且不需要改变接口，这个比起函数指针作回调来说，简单了很多，也清晰很多。</P>
<P>&nbsp;</P>
<P><SPAN class=Code>下面是代码：</SPAN></P>
<P><SPAN class=Code>#include &lt;iostream&gt;<BR>#include &lt;string&gt;<BR>#include &lt;stdlib.h&gt;</SPAN></P>
<P><SPAN class=Code>using namespace std;</SPAN></P>
<P><SPAN class=Code>class Action<BR>{<BR>public:<BR>&nbsp;&nbsp;&nbsp; virtual ~Action() = 0;<BR>&nbsp;&nbsp;&nbsp; virtual void operator()() = 0;<BR>&nbsp;&nbsp;&nbsp; virtual Action *clone() const = 0;<BR>};</SPAN></P>
<P><SPAN class=Code>Action::~Action()<BR>{ cout &lt;&lt; "::~Action()" &lt;&lt; endl; }</SPAN></P>
<P><SPAN class=Code>void Action::operator()()<BR>{<BR>&nbsp;&nbsp;&nbsp; cout &lt;&lt; "1111111111" &lt;&lt; endl;<BR>}</SPAN></P>
<P><SPAN class=Code>class Button<BR>{<BR>public:<BR>&nbsp;&nbsp;&nbsp; Button( const string &amp;label )<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : m_label( label ), m_action( 0 ) {}<BR>&nbsp;&nbsp;&nbsp; ~Button()<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if( m_action )<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete m_action;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_action = NULL;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; void setAction( const Action *newAction )<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Action *tmp = newAction-&gt;clone();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete m_action;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_action = tmp;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; void onClick() const<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if( m_action )<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( *m_action )();<BR>&nbsp;&nbsp;&nbsp; }</SPAN></P>
<P><SPAN class=Code>private:<BR>&nbsp;&nbsp;&nbsp; string m_label;<BR>&nbsp;&nbsp;&nbsp; Action *m_action;<BR>};</SPAN></P>
<P><SPAN class=Code>class PlayMusic : public Action<BR>{<BR>public:<BR>&nbsp;&nbsp;&nbsp; PlayMusic( const string &amp;songFile )<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :m_song( songFile ) {}<BR>&nbsp;&nbsp;&nbsp; virtual ~PlayMusic() { cout &lt;&lt; "~PlayMusic()" &lt;&lt; endl; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; void operator()()<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "PlayMusic " &lt;&lt; m_song &lt;&lt; endl;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; virtual Action *clone() const<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (Action *)this;<BR>&nbsp;&nbsp;&nbsp; }<BR>private:<BR>&nbsp;&nbsp;&nbsp; string m_song;<BR>};</SPAN></P>
<P><SPAN class=Code>int main(int argc, char *argv[])<BR>{<BR>&nbsp;&nbsp;&nbsp; Button *b = new Button( "Anoko no namaewa" );<BR>&nbsp;&nbsp;&nbsp; PlayMusic *song = new PlayMusic( "AnokoNonamaewa.mp3" );<BR>&nbsp;&nbsp;&nbsp; b-&gt;setAction( song );<BR>&nbsp;&nbsp;&nbsp; b-&gt;onClick();<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; delete b;<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp; system("PAUSE");&nbsp;<BR>&nbsp; return 0;<BR>}</SPAN></P><img src ="http://www.cppblog.com/apollo/aggbug/4153.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-03-14 21:34 <a href="http://www.cppblog.com/apollo/articles/4153.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++指针探讨---成员函数指针</title><link>http://www.cppblog.com/apollo/articles/MemBerPoint.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Mon, 13 Mar 2006 14:37:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/MemBerPoint.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/4110.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/MemBerPoint.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/4110.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/4110.html</trackback:ping><description><![CDATA[C语言的指针相当的灵活方便，但也相当容易出错。许多C语言初学者，甚至C语言老鸟都很容易栽倒在C语言的指针下。但不可否认的是，指针在C语言中的位置极其重要，也许可以偏激一点的来说：没有指针的C程序不是真正的C程序。<br>
　
　然而C++的指针却常常给我一种束手束脚的感觉。C++比C语言更加强调强类型，强调类型安全，强调编译时检查。因此，对于C语言中最容易错用的指针，
更是不能放过：C++的指针被分成数据指针，数据成员指针，函数指针，成员函数指针，而且不能随便相互转换。而且这些指针的声明格式都不一样：
<p>
<table style="width: 320px; border-collapse: collapse;" border="1" cellpadding="3" cellspacing="0">
<tbody>
<tr>
<td>数据指针</td>
<td>T&nbsp;*</td></tr>
<tr>
<td>成员数据指针</td>
<td>T::*</td></tr>
<tr>
<td>函数指针</td>
<td>R&nbsp;(*)(...)</td></tr>
<tr>
<td>成员函数指针</td>
<td>R (T::*)(...)</td></tr></tbody></table><br>　　尽管C++中仍然有万能指针void*，但它却属于被批斗的对象，而且再也不能“万能”了。它不能转换成成员指针。</p>

<p>　　这样一来，C++的指针就变得很尴尬：我们需要一种指针能够指向同一类型的数据，不管这个数据是普通数据，还是成员数据；我们更需要一种指针能够指向同一类型的函数，不管这个函数是静态函数，还是成员函数。但是没有，至少从现在的C++标准中，还没有看到。<br>　<br><a id="BlogTitleLink" href="http://ly4cn.cnblogs.com/"><font color="#6b86b3">沐枫网志</font></a>&nbsp;<a title="C++指针探讨(三)成员函数指针" href="http://ly4cn.cnblogs.com/archive/2006/03/13/349180.html">C++指针探讨(三)成员函数指针</a><br><br>　　自从有了类，我们开始按照　数据＋操作　的方式来组织数据结构；自从有了模板，我们又开始把 数据 和 算法 分离，以便重用，实在够折腾人的。但不管怎么折腾，现在大多数函数都不再单身，都嫁给了类，进了围城。可是我们仍然需要能够自由调用这些成员函数。<br>　　考虑一下windows下的定时调用。SetTimer函数的原型是这样的：</p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 0);">UINT_PTR&nbsp;SetTimer(<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;HWND&nbsp;hWnd,<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;UINT_PTR&nbsp;nIDEvent,<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;UINT&nbsp;uElapse,<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;TIMERPROC&nbsp;lpTimerFunc<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">);<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span></div>
　
　其中，参数就不解释了，这个函数估计大多数windows开发人员都知道。lpTimerFunc是个会被定时调用的函数指针。假如我们不通过
WM_TIMER消息来触发定时器，而是通过lpTimerFunc来定时工作，那么我们就只能使用普通函数或静态函数，而无论如何都不能使用成员函数，
哪怕通过静态函数转调也不行。<br>
<br>
　　再考虑一下线程的创建：<br>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 0);">uintptr_t&nbsp;_beginthread(&nbsp;<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">(&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">start_address&nbsp;)(&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">&nbsp;),<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">&nbsp;&nbsp;&nbsp;unsigned&nbsp;stack_size,<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">arglist&nbsp;<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">);<img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span></div>
　
　start_address仍然只支持普通函数。不过这回好了，它允许回调函数一个void*参数，它将会arglist作为参数来调用
start_address。于是，聪明的C++程序员，就利用arglist传递this指针，从而利用静态函数成功的调用到了成员函数了：<br>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;mythread<br><img id="Codehighlighter1_15_113_Open_Image" onclick="this.style.display='none'; Codehighlighter1_15_113_Open_Text.style.display='none'; Codehighlighter1_15_113_Closed_Image.style.display='inline'; Codehighlighter1_15_113_Closed_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_15_113_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_15_113_Closed_Text.style.display='none'; Codehighlighter1_15_113_Open_Image.style.display='inline'; Codehighlighter1_15_113_Open_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_15_113_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_15_113_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">:<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;doit(</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">&nbsp;pThis)<br><img id="Codehighlighter1_65_90_Open_Image" onclick="this.style.display='none'; Codehighlighter1_65_90_Open_Text.style.display='none'; Codehighlighter1_65_90_Closed_Image.style.display='inline'; Codehighlighter1_65_90_Closed_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_65_90_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_65_90_Closed_Text.style.display='none'; Codehighlighter1_65_90_Open_Image.style.display='inline'; Codehighlighter1_65_90_Open_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_65_90_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_65_90_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">　　　　((mythread*)pThis)</span><span style="color: rgb(0, 0, 0);">-&gt;</span><span style="color: rgb(0, 0, 0);">doit();<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: rgb(0, 0, 0);"><br><img id="Codehighlighter1_107_111_Open_Image" onclick="this.style.display='none'; Codehighlighter1_107_111_Open_Text.style.display='none'; Codehighlighter1_107_111_Closed_Image.style.display='inline'; Codehighlighter1_107_111_Closed_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_107_111_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_107_111_Closed_Text.style.display='none'; Codehighlighter1_107_111_Open_Image.style.display='inline'; Codehighlighter1_107_111_Open_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;doit()</span><span id="Codehighlighter1_107_111_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_107_111_Open_Text"><span style="color: rgb(0, 0, 0);">{<img src="http://www.cnblogs.com/Images/dot.gif">}</span></span><span style="color: rgb(0, 0, 0);"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: rgb(0, 0, 0);">;<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">main()<br><img id="Codehighlighter1_124_211_Open_Image" onclick="this.style.display='none'; Codehighlighter1_124_211_Open_Text.style.display='none'; Codehighlighter1_124_211_Closed_Image.style.display='inline'; Codehighlighter1_124_211_Closed_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_124_211_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_124_211_Closed_Text.style.display='none'; Codehighlighter1_124_211_Open_Image.style.display='inline'; Codehighlighter1_124_211_Open_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_124_211_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_124_211_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;<img src="http://www.cnblogs.com/Images/dot.gif"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;mythread</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">&nbsp;pmt&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;mythread;<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;_beginthread(</span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">mythread::doit,&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">,&nbsp;(void*)pmt);<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;<img src="http://www.cnblogs.com/Images/dot.gif"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span></div>

<p>　　但是显然，C++程序员肯定不会因此而满足。这里头有许多被C++批判的不安定因素。它使用了C++中被认为不安全的类型转换，不安全的
void*指针，等等等等。但这是系统为C语言留下的调用接口，这也就认了。那么假如，我们就在C++程序中如何来调用成员函数指针呢？<br>　　如下例，我们打算对vector中的所有类调用其指定的成员函数：</p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 0);">#include&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">vector</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">#include&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">algorithm</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">#include&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">functional</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top">#include&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">iostream</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">using</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">namespace</span><span style="color: rgb(0, 0, 0);">&nbsp;std;<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;A<br><img id="Codehighlighter1_111_249_Open_Image" onclick="this.style.display='none'; Codehighlighter1_111_249_Open_Text.style.display='none'; Codehighlighter1_111_249_Closed_Image.style.display='inline'; Codehighlighter1_111_249_Closed_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_111_249_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_111_249_Closed_Text.style.display='none'; Codehighlighter1_111_249_Open_Image.style.display='inline'; Codehighlighter1_111_249_Open_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_111_249_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_111_249_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;value;<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">:<br><img id="Codehighlighter1_142_153_Open_Image" onclick="this.style.display='none'; Codehighlighter1_142_153_Open_Text.style.display='none'; Codehighlighter1_142_153_Closed_Image.style.display='inline'; Codehighlighter1_142_153_Closed_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_142_153_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_142_153_Closed_Text.style.display='none'; Codehighlighter1_142_153_Open_Image.style.display='inline'; Codehighlighter1_142_153_Open_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;A(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;v)</span><span id="Codehighlighter1_142_153_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_142_153_Open_Text"><span style="color: rgb(0, 0, 0);">{value&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;v;}</span></span><span style="color: rgb(0, 0, 0);"><br><img id="Codehighlighter1_167_191_Open_Image" onclick="this.style.display='none'; Codehighlighter1_167_191_Open_Text.style.display='none'; Codehighlighter1_167_191_Closed_Image.style.display='inline'; Codehighlighter1_167_191_Closed_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_167_191_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_167_191_Closed_Text.style.display='none'; Codehighlighter1_167_191_Open_Image.style.display='inline'; Codehighlighter1_167_191_Open_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;doit()</span><span id="Codehighlighter1_167_191_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_167_191_Open_Text"><span style="color: rgb(0, 0, 0);">{&nbsp;cout&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);">&nbsp;value&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);">&nbsp;endl;}</span></span><span style="color: rgb(0, 0, 0);">;<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;call_doit(A</span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">&nbsp;rThis)<br><img id="Codehighlighter1_228_247_Open_Image" onclick="this.style.display='none'; Codehighlighter1_228_247_Open_Text.style.display='none'; Codehighlighter1_228_247_Closed_Image.style.display='inline'; Codehighlighter1_228_247_Closed_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_228_247_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_228_247_Closed_Text.style.display='none'; Codehighlighter1_228_247_Open_Image.style.display='inline'; Codehighlighter1_228_247_Open_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_228_247_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_228_247_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rThis.doit();<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: rgb(0, 0, 0);"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: rgb(0, 0, 0);">;<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;main()<br><img id="Codehighlighter1_265_587_Open_Image" onclick="this.style.display='none'; Codehighlighter1_265_587_Open_Text.style.display='none'; Codehighlighter1_265_587_Closed_Image.style.display='inline'; Codehighlighter1_265_587_Closed_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_265_587_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_265_587_Closed_Text.style.display='none'; Codehighlighter1_265_587_Open_Image.style.display='inline'; Codehighlighter1_265_587_Open_Text.style.display='inline';" src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_265_587_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="http://www.cnblogs.com/Images/dot.gif"></span><span id="Codehighlighter1_265_587_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;vector</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">A</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;va;<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;va.push_back(A(</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">));<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;va.push_back(A(</span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);">));<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;va.push_back(A(</span><span style="color: rgb(0, 0, 0);">3</span><span style="color: rgb(0, 0, 0);">));<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;va.push_back(A(</span><span style="color: rgb(0, 0, 0);">4</span><span style="color: rgb(0, 0, 0);">));<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">方法1:<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">for_each(va.begin(),&nbsp;va.end(),&nbsp;&amp;A::doit);&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">error<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">方法2:</span><span style="color: rgb(0, 128, 0);"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;for_each(va.begin(),&nbsp;va.end(),&nbsp;</span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">A::call_doit);<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">方法3:</span><span style="color: rgb(0, 128, 0);"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;for_each(va.begin(),&nbsp;va.end(),&nbsp;mem_fun_ref</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">,&nbsp;A</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">A::doit));<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;system(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Pause</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: rgb(0, 0, 0);"><br><img src="http://ly4cn.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"></span></div>

<p>　　方法1，编译不能通过。for_each只允许具有一个参数的函数指针或函数对象，哪怕A::doit默认有一个this指针参数也不行。不是for_each没考虑到这一点，而是根本做不到！<br>　　方法2，显然是受到了beginthread的启发，使用一个静态函数来转调用，哈哈成功了。但是不爽！这不是C++。<br>　　方法3，呼，好不容易啊，终于用mem_fun_ref包装成功了成员函数指针。<br>　
　似乎方法3不错，又是类型安全的，又可以通用－－慢着，首先，它很丑，哪有调用普通C函数指针那么漂亮啊（见方法2），用了一大串包装，又是尖括号又是
圆括号，还少不了&amp;号！其次，它只能包装不超过一个参数的函数！尽管它在for_each中够用了，但是你要是想用在超过一个参数的场合，那只有
一句话：不可能的任务。<br></p>

　　是的，在标准C++中，这是不可能的任务。但事情并不总是悲观的，至少有许多第三方库提供了超越mem_fun的包装。如boost::
function等等。但是它也有限制：它所支持的参数仍然是有限的，只有十多个，尽管够你用的了；同样，它也是丑陋的，永远不要想它能够简单的用
&amp;来搞定。<br>
<br>
　　也许，以失去美丽的代价，来换取质量上的保证，这也是C++对于函数指针的一种无奈吧……<br>
<br>
　　期待C++0x版本。它通过可变模板参数，能够让mem_fun的参数达到无限个……<img src ="http://www.cppblog.com/apollo/aggbug/4110.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-03-13 22:37 <a href="http://www.cppblog.com/apollo/articles/MemBerPoint.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> C++ 备忘录</title><link>http://www.cppblog.com/apollo/articles/remeber.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Sun, 12 Mar 2006 15:14:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/remeber.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/4058.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/remeber.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/4058.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/4058.html</trackback:ping><description><![CDATA[<p>本文主要是记录一些初级的但是有时候我自己容易忽略或者忘记东西，仅作备忘录之用&nbsp;&nbsp;&nbsp;<br>1）、衔接符 \ </p>

<p>\ 在c++中可以作为衔接符（忘了规范的术语是不是这么叫了， 汗自己一个~），例如：</p>

<p>&nbsp;&nbsp;//this is memo\</p>

<p>this is memo too</p>

<p>上面两行在c++中，编译器会认为是一行。</p>

<p>不过\一般只在宏定义中使用，因为如果是字符串，那么别写分号就行，如：<br>char *s = "How "<br>&nbsp;&nbsp;&nbsp; "are "<br>&nbsp;&nbsp;&nbsp; "you?";<br>如果是一般的语句，那么就直接换，比如：<br>int sum = i + <br>&nbsp;&nbsp;&nbsp; j;<br></p>

<p>2）##</p>

<p>## 叫做指令粘贴符，它的英文术语叫做token-pasting operator，主要在宏定义中使用。使用例子如下：</p>
<pre><code>#define paster( n ) printf( "token" #n " = %d", token##n )</code></pre>

<p>int token9 = 9;</p>

<p>用如下方式调用宏,</p>

<p>paster( 9 ); //输出: taken9 = 9</p>

<p>上面的宏此时等价于</p>

<p>printf( "token" "9" " = %d", token9 );</p>

<p>结果就是：</p>

<p>printf( "token9 = %d", token9 );<br>
</p>
<p>3) C++函数参数入栈顺序--从右到左</p>

<p>下面的例子用来验证C++函数参数入栈顺序：</p>

<p>&nbsp;&nbsp;&nbsp;void test（int i1, int i2, int i3）</p>

<p>{</p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;printf(“i1=%d, i2=%d, i3=%d\n“,i1,i2,i3);</p>

<p>}</p>

<p>int i=0;</p>

<p>test(++i,++i,++i);</p>

<p>则输出结果为：i1=3, i2=2, i3=1</p>

<p>4)一个有趣的小问题--表达式与算符结合顺序</p>

<p>在VC论坛里看到有人对下面的表达式计算结果有点迷惑，</p>

<p>int i&nbsp;= 1;</p>

<p>int k = (++i) + (++i)+ (++i);</p>

<p>int i2&nbsp;= 1;</p>

<p>int k2 = (++i2) + (++i2);</p>

<p>我也测试了一下，很多人一开始会以为 k = 2 + 3 + 4&nbsp; =9;</p>

<p>但是事实上在VC, DevC++4.9(GCC)里面编译， 执行结果k=10;</p>

<p>综合其他人的一些看法和我自己的测试，得出结论:</p>

<p>k= (++i)+(++i)+(++i);//等价于++i，++i，k = i+i + （++i）；也就是 k = 3 + 3 + 4 = 10。</p>

<p>因此，k2的结果为6。</p>

当然，这个没有进行语法上的深层次分析，有兴趣的朋友可以自己分析一下C++的相关语法。<br>
<br>
<p>4)下面先看问题：</p>

<p>////bowex ()///////////////////////////////////////////////////////</p>

<p>char uu[3][2];<br>CString s;<br>for(int i=0;i&lt;3;i++)<br>{<br>&nbsp; s="我";<br>&nbsp; strcpy(uu[i],s);<br>} </p>

<p>运行完以上程序后为何数组uu中的内容是</p>

<p>uu[0] --- &gt; 我我我<br>uu[1] --- &gt; 我我<br>uu[2] --- &gt; 我</p>

<p>而不是<br>uu[0] --- &gt; 我<br>uu[1] --- &gt; 我<br>uu[2] --- &gt; 我&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为何？ 奇怪! 多谢</p>

<p>////////////////////////////////////////////////////////////////////</p>

<p>网友“QunKangLi(维护成本与程序员的创造力的平方成正比)”给出解释：</p>

<p>“<strong>char uu[3][3];//这样就行了，字符串结束符占一个字符宽度</strong>。”</p>

<p>这个解释是很对，不过我还是要强调一下这种情况可能产生的严重后果：</p>

<p>像这种情况让我想起了strcpy函数可能引起非法内存访问，也就是说，<strong>如果</strong></p>

<p><strong>strcpy拷贝的目的地址分配的空间不够，那么strcpy会把空间后面的地址也占用，</strong></p>

<p><strong>这样就可能使某些数据被意外修改，从而导致程序崩溃或者数据异常</strong>。之所以有</p>

<p>这种感受，是因为以前碰到有个程序，就发生这样的错误，就是因为strcpy拷贝的内容</p>

<p>过长从而把数据结构中紧接其后的成员的数据变为0了，结果程序当然出现意外。</p>

<p>假设把上面的for循环用下面的语句代替 那么结果就更加荒唐， 因为会出现乱码。</p>

<p>char uu[3][2];<br>CString s;</p>

<p>s="我";<br>strcpy(uu[2],s);<br>&nbsp;strcpy(uu[1],s);<br>strcpy(uu[0],s);</p>

<p>&nbsp;大家可以编译一下上面的代码，运行程序 你可以看到uu数组中有乱码。</p>

<p>如果输出的话，应该是这样的，</p>

<p>uu[0] --- &gt; 我<br>uu[1] --- &gt; （空串）<br>uu[2] --- &gt; （空串）</p>

是什么原因大家应该一目了然了吧。<br>
<img src ="http://www.cppblog.com/apollo/aggbug/4058.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-03-12 23:14 <a href="http://www.cppblog.com/apollo/articles/remeber.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>预处理过程</title><link>http://www.cppblog.com/apollo/articles/precompiler.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Fri, 10 Mar 2006 15:40:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/precompiler.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/3990.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/precompiler.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/3990.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/3990.html</trackback:ping><description><![CDATA[<span style="font-size: 9pt; font-family: 宋体;">预处理过程扫描源代码，对其进行初步的转换，产生新的源代码提供给编译器。可见预处理过程先于编译器对源代码进行处理。<span lang="EN-US"><br></span>在<span lang="EN-US">C</span>语
言中，并没有任何内在的机制来完成如下一些功能：在编译时包含其他源文件、定义宏、根据条件决定编译时是否包含某些代码。要完成这些工作，就需要使用预处
理程序。尽管在目前绝大多数编译器都包含了预处理程序，但通常认为它们是独立于编译器的。预处理过程读入源代码，检查包含预处理指令的语句和宏定义，并对
源代码进行响应的转换。预处理过程还会删除程序中的注释和多余的空白字符。<span lang="EN-US"><br></span>预处理指令是以<span lang="EN-US">#</span>号开头的代码行。<span lang="EN-US">#</span>号必须是该行除了任何空白字符外的第一个字符。<span lang="EN-US">#</span>后是指令关键字，在关键字和<span lang="EN-US">#</span>号之间允许存在任意个数的空白字符。整行语句构成了一条预处理指令，该指令将在编译器进行编译之前对源代码做某些转换。下面是部分预处理指令：<span lang="EN-US"><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>指令<span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>用途<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>空指令，无任何效果<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#include&nbsp;&nbsp;&nbsp;&nbsp;</span>包含一个源代码文件<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#define&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>定义宏<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#undef&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>取消已定义的宏<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#if&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>如果给定条件为真，则编译下面代码<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#ifdef&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>如果宏已经定义，则编译下面代码<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#ifndef&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>如果宏没有定义，则编译下面代码<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#elif&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>如果前面的<span lang="EN-US">#if</span>给定条件不为真，当前条件为真，则编译下面代码<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#endif&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>结束一个<span lang="EN-US">#if</span>……<span lang="EN-US">#else</span>条件编译块<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#error&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>停止编译并显示错误信息<span lang="EN-US"><br><br></span>一、文件包含<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;#include</span>预处理指令的作用是在指令处展开被包含的文件。包含可以是多重的，也就是说一个被包含的文件中还可以包含其他文件。标准<span lang="EN-US">C</span>编译器至少支持八重嵌套包含。<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span>预处理过程不检查在转换单元中是否已经包含了某个文件并阻止对它的多次包含。这样就可以在多次包含同一个头文件时，通过给定编译时的条件来达到不同的效果。例如：<span lang="EN-US"><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#define&nbsp;AAA<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#include&nbsp;"t.c"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#undef&nbsp;AAA<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#include&nbsp;"t.c"<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span>为了避免那些只能包含一次的头文件被多次包含，可以在头文件中用编译时条件来进行控制。例如：<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*my.h*/<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#ifndef&nbsp;MY_H<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#define&nbsp;MY_H<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>……<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#endif<br><br>&nbsp;&nbsp;&nbsp;&nbsp;</span>在程序中包含头文件有两种格式：<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#include&nbsp;&lt;my.h&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#include&nbsp;"my.h"<br>&nbsp;&nbsp;&nbsp;&nbsp;</span>第
一种方法是用尖括号把头文件括起来。这种格式告诉预处理程序在编译器自带的或外部库的头文件中搜索被包含的头文件。第二种方法是用双引号把头文件括起来。
这种格式告诉预处理程序在当前被编译的应用程序的源代码文件中搜索被包含的头文件，如果找不到，再搜索编译器自带的头文件。<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span>采用两种不同包含格式的理由在于，编译器是安装在公共子目录下的，而被编译的应用程序是在它们自己的私有子目录下的。一个应用程序既包含编译器提供的公共头文件，也包含自定义的私有头文件。采用两种不同的包含格式使得编译器能够在很多头文件中区别出一组公共的头文件。<span lang="EN-US"><br><br></span>二、宏<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span>宏
定义了一个代表特定内容的标识符。预处理过程会把源代码中出现的宏标识符替换成宏定义时的值。宏最常见的用法是定义代表某个值的全局符号。宏的第二种用法
是定义带参数的宏，这样的宏可以象函数一样被调用，但它是在调用语句处展开宏，并用调用时的实际参数来代替定义中的形式参数。<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;1.#define</span>指令<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#define</span>预处理指令是用来定义宏的。该指令最简单的格式是：首先神明一个标识符，然后给出这个标识符代表的代码。在后面的源代码中，就用这些代码来替代该标识符。这种宏把程序中要用到的一些全局值提取出来，赋给一些记忆标识符。<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#define&nbsp;MAX_NUM&nbsp;10<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;array[MAX_NUM];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(i=0;i&lt;MAX_NUM;i++)&nbsp;&nbsp;/*</span>……<span lang="EN-US">*/<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>在这个例子中，对于阅读该程序的人来说，符号<span lang="EN-US">MAX_NUM</span>就有特定的含义，它代表的值给出了数组所能容纳的最大元素数目。程序中可以多次使用这个值。作为一种约定，习惯上总是全部用大写字母来定义宏，这样易于把程序红的宏标识符和一般变量标识符区别开来。如果想要改变数组的大小，只需要更改宏定义并重新编译程序即可。<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>宏表示的值可以是一个常量表达式，其中允许包括前面已经定义的宏标识符。例如：<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#define&nbsp;ONE&nbsp;1<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#define&nbsp;TWO&nbsp;2<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#define&nbsp;THREE&nbsp;(ONE+TWO)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>注意上面的宏定义使用了括号。尽管它们并不是必须的。但出于谨慎考虑，还是应该加上括号的。例如：<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;six=THREE*TWO;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>预处理过程把上面的一行代码转换成：<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;six=(ONE+TWO)*TWO;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>如果没有那个括号，就转换成<span lang="EN-US">six=ONE+TWO*TWO;</span>了。<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>宏还可以代表一个字符串常量，例如：<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#define&nbsp;VERSION&nbsp;"Version&nbsp;1.0&nbsp;Copyright(c)&nbsp;2003"<br>&nbsp;&nbsp;&nbsp;&nbsp;2.</span>带参数的<span lang="EN-US">#define</span>指令<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>带参数的宏和函数调用看起来有些相似。看一个例子：<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#define&nbsp;Cube(x)&nbsp;(x)*(x)*(x)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>可以时任何数字表达式甚至函数调用来代替参数<span lang="EN-US">x</span>。这里再次提醒大家注意括号的使用。宏展开后完全包含在一对括号中，而且参数也包含在括号中，这样就保证了宏和参数的完整性。看一个用法：<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;num=8+2;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;volume=Cube(num);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>展开后为<span lang="EN-US">(8+2)*(8+2)*(8+2);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>如果没有那些括号就变为<span lang="EN-US">8+2*8+2*8+2</span>了。<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>下面的用法是不安全的：<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;volume=Cube(num++);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>如果<span lang="EN-US">Cube</span>是一个函数，上面的写法是可以理解的。但是，因为<span lang="EN-US">Cube</span>是一个宏，所以会产生副作用。这里的擦书不是简单的表达式，它们将产生意想不到的结果。它们展开后是这样的：<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;volume=(num++)*(num++)*(num++);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>很显然，结果是<span lang="EN-US">10*11*12,</span>而不是<span lang="EN-US">10*10*10;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>那么怎样安全的使用<span lang="EN-US">Cube</span>宏呢？必须把可能产生副作用的操作移到宏调用的外面进行：<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;num=8+2;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;volume=Cube(num);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;num++;<br>&nbsp;&nbsp;&nbsp;&nbsp;3.#</span>运算符<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>出现在宏定义中的<span lang="EN-US">#</span>运算符把跟在其后的参数转换成一个字符串。有时把这种用法的<span lang="EN-US">#</span>称为字符串化运算符。例如：<span lang="EN-US"><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#define&nbsp;PASTE(n)&nbsp;"adhfkj"#n<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;main()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("%s\n",PASTE(15));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>宏定义中的<span lang="EN-US">#</span>运算符告诉预处理程序，把源代码中任何传递给该宏的参数转换成一个字符串。所以输出应该是<span lang="EN-US">adhfkj15</span>。<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;4.##</span>运算符<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;##</span>运算符用于把参数连接到一起。预处理程序把出现在<span lang="EN-US">##</span>两侧的参数合并成一个符号。看下面的例子：<span lang="EN-US"><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#define&nbsp;NUM(a,b,c)&nbsp;a##b##c<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#define&nbsp;STR(a,b,c)&nbsp;a##b##c<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;main()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("%d\n",NUM(1,2,3));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("%s\n",STR("aa","bb","cc"));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>最后程序的输出为<span lang="EN-US">:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;123<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;aabbcc<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>千万别担心，除非需要或者宏的用法恰好和手头的工作相关，否则很少有程序员会知道<span lang="EN-US">##</span>运算符。绝大多数程序员从来没用过它。<span lang="EN-US"><br><br></span>三、条件编译指令<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span>条件编译指令将决定那些代码被编译，而哪些是不被编译的。可以根据表达式的值或者某个特定的宏是否被定义来确定编译条件。<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;1.#if</span>指令<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#if</span>指令检测跟在制造另关键字后的常量表达式。如果表达式为真，则编译后面的代码，知道出现<span lang="EN-US">#else</span>、<span lang="EN-US">#elif</span>或<span lang="EN-US">#endif</span>为止；否则就不编译。<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;2.#endif</span>指令<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#endif</span>用于终止<span lang="EN-US">#if</span>预处理指令。<span lang="EN-US"><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#define&nbsp;DEBUG&nbsp;0<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;main()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#if&nbsp;DEBUG<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Debugging\n");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#endif<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Running\n");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>由于程序定义<span lang="EN-US">DEBUG</span>宏代表<span lang="EN-US">0</span>，所以<span lang="EN-US">#if</span>条件为假，不编译后面的代码直到<span lang="EN-US">#endif</span>，所以程序直接输出<span lang="EN-US">Running</span>。<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>如果去掉<span lang="EN-US">#define</span>语句，效果是一样的。<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;3.#ifdef</span>和<span lang="EN-US">#ifndef<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#define&nbsp;DEBUG<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;main()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#ifdef&nbsp;DEBUG<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("yes\n");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#endif<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#ifndef&nbsp;DEBUG<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("no\n");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#endif<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#if&nbsp;defined</span>等价于<span lang="EN-US">#ifdef;&nbsp;#if&nbsp;!defined</span>等价于<span lang="EN-US">#ifndef<br>&nbsp;&nbsp;&nbsp;&nbsp;4.#else</span>指令<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#else</span>指令用于某个<span lang="EN-US">#if</span>指令之后，当前面的<span lang="EN-US">#if</span>指令的条件不为真时，就编译<span lang="EN-US">#else</span>后面的代码。<span lang="EN-US">#endif</span>指令将中指上面的条件块。<span lang="EN-US"><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#define&nbsp;DEBUG<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;main()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#ifdef&nbsp;DEBUG<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Debugging\n");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Not&nbsp;debugging\n");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#endif<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("Running\n");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;5.#elif</span>指令<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#elif</span>预处理指令综合了<span lang="EN-US">#else</span>和<span lang="EN-US">#if</span>指令的作用。<span lang="EN-US"><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#define&nbsp;TWO<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;main()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#ifdef&nbsp;ONE<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("1\n");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#elif&nbsp;defined&nbsp;TWO<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("2\n");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("3\n");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#endif<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>程序很好理解，最后输出结果是<span lang="EN-US">2</span>。<span lang="EN-US"><br><br>&nbsp;&nbsp;&nbsp;&nbsp;6.</span>其他一些标准指令<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#error</span>指令将使编译器显示一条错误信息，然后停止编译。<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#line</span>指令可以改变编译器用来指出警告和错误信息的文件号和行号。<span lang="EN-US"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#pragma</span>指令没有正式的定义。编译器可以自定义其用途。典型的用法是禁止或允许某些烦人的警告信息。</span><img src ="http://www.cppblog.com/apollo/aggbug/3990.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-03-10 23:40 <a href="http://www.cppblog.com/apollo/articles/precompiler.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于主函数</title><link>http://www.cppblog.com/apollo/articles/Main.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Thu, 09 Mar 2006 14:22:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/Main.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/3947.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/Main.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/3947.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/3947.html</trackback:ping><description><![CDATA[&nbsp;
很多人甚至市面上的一些书籍，都使用了void&nbsp;main(&nbsp;)&nbsp;，其实这是错误的。C/C++&nbsp;中从来没有定
义过void&nbsp;main(&nbsp;)&nbsp;。C+
+&nbsp;之父&nbsp;Bjarne&nbsp;Stroustrup&nbsp;在他的主页上的&nbsp;FAQ&nbsp;中明确地写着
&nbsp;The&nbsp;definition&nbsp;void&nbsp;main(&nbsp;)&nbsp;
{&nbsp;/*&nbsp;...&nbsp;*/&nbsp;}&nbsp;is&nbsp;not&nbsp;and&nbsp;never&nbsp;has&nbsp;been&nbsp;C++,&nbsp;nor&nbsp;has&nbsp;it&nbsp;even&nbsp;been&nbsp;C.
（&nbsp;void&nbsp;main(&nbsp;)&nbsp;从来就不存在于&nbsp;C++&nbsp;或者&nbsp;
C&nbsp;）。下面我分别说一下&nbsp;C&nbsp;和&nbsp;C++&nbsp;标准中对&nbsp;main&nbsp;函数的定义。
&nbsp;<br>
<br>
&nbsp;&nbsp;<br>
<br>
1.&nbsp;C&nbsp;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
在&nbsp;C89&nbsp;中，main(&nbsp;)&nbsp;是可以接受的。Brian&nbsp;W.&nbsp;Kernighan&nbsp;和&nbsp;Dennis&nbsp;M.&nbsp;Ritchie&nbsp;的经典巨著
&nbsp;The&nbsp;C&nbsp;programming&nbsp;Language（《C&nbsp;程序设计语言》）用的就是&nbsp;main(&nbsp;)。不过在最新的&nbsp;C99&nbsp;标准中，只有以下两
种定义方式是正确的：&nbsp;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;main(&nbsp;void&nbsp;)&nbsp;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;main(&nbsp;int&nbsp;argc,&nbsp;char&nbsp;*argv[]&nbsp;)&nbsp;<br>
<br>
（参考资料：ISO/IEC&nbsp;9899:1999&nbsp;(E)&nbsp;Programming&nbsp;
languages&nbsp;—&nbsp;C&nbsp;5.1.2.2.1&nbsp;Program&nbsp;startup）&nbsp;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;当然，我们也可以做一点小小的改动。例如：
char&nbsp;*argv[]&nbsp;可以写成&nbsp;char&nbsp;**argv；argv&nbsp;和&nbsp;
argc&nbsp;可以改成别的变量名（如&nbsp;intval&nbsp;和&nbsp;charval），不过一定要符合变量的命名规则。
&nbsp;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果你不需要从命令行中获取参数，请用&nbsp;
int&nbsp;main(&nbsp;void&nbsp;)&nbsp;；否则请用&nbsp;int&nbsp;main(&nbsp;
int&nbsp;argc,&nbsp;char&nbsp;*argv[]&nbsp;)&nbsp;。&nbsp;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;main&nbsp;函数的返回值类型必须是&nbsp;int&nbsp;，这样返回值才能传递给程序的激活者（如操作系统）。&nbsp;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
如果&nbsp;main&nbsp;函数的最后没有写&nbsp;return&nbsp;语句的话，C99&nbsp;规定编译器要自动在生成的目标文件中（如&nbsp;exe&nbsp;文件）加入
&nbsp;return&nbsp;0&nbsp;，表示程序正常退出。不过，我还是建议你最好在&nbsp;main&nbsp;函数的最后加上&nbsp;return&nbsp;语句，虽然没有这个必要，但这是一个好的
习惯。注意，vc6&nbsp;不会在生成的目标文件中加入&nbsp;return&nbsp;0&nbsp;，大概是因为&nbsp;vc6&nbsp;是&nbsp;98&nbsp;年的产品，所以才不支持这个特性。现在明白我为什
么建议你最好加上&nbsp;return&nbsp;语句了吧！不过，gcc3.2（Linux&nbsp;下的&nbsp;C&nbsp;编译器）会在生成的目标文件中加入&nbsp;return&nbsp;0&nbsp;。&nbsp;<br>
<br>
&nbsp;&nbsp;<br>
<br>
2.&nbsp;C++&nbsp;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C++98&nbsp;中定义了如下两种&nbsp;main&nbsp;函数的定义方式：&nbsp;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;main(&nbsp;)&nbsp;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;main(&nbsp;int&nbsp;argc,&nbsp;char&nbsp;*argv[]&nbsp;)&nbsp;<br>
<br>
（参考资料：ISO/IEC&nbsp;14882(1998-9-01)Programming&nbsp;languages&nbsp;—
&nbsp;C++&nbsp;3.6&nbsp;Start&nbsp;and&nbsp;termination）&nbsp;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;main
(&nbsp;)&nbsp;等同于&nbsp;C99&nbsp;中的&nbsp;int&nbsp;main(&nbsp;void&nbsp;)
&nbsp;；int&nbsp;main(&nbsp;int&nbsp;argc,&nbsp;char&nbsp;*argv[]&nbsp;)
&nbsp;的用法也
和&nbsp;C99&nbsp;中定义的一样。同样，main&nbsp;函数的返回值类型也必须是&nbsp;int&nbsp;。如果&nbsp;
main&nbsp;函数的末尾没写&nbsp;return&nbsp;语句，C++98&nbsp;规
定编译器要自动在生成的目标文件中加入&nbsp;return&nbsp;0&nbsp;。同样，vc6&nbsp;也不支持这个特性，但是
&nbsp;g++3.2（Linux&nbsp;下的&nbsp;C++&nbsp;编译器）
支持。&nbsp;<br>
<br>
&nbsp;&nbsp;<br>
<br>
3.&nbsp;关于&nbsp;void&nbsp;main&nbsp;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在&nbsp;C&nbsp;和&nbsp;C++&nbsp;中，不接收任何参
数也不返回任何信息的函数原型为“void&nbsp;foo(void);”。可能正是因为这个，所以很多人都误认为如果不需要程序返回任何信息时可以把
&nbsp;main&nbsp;函数定义成&nbsp;void&nbsp;main(void)&nbsp;。然而这是错误的！main&nbsp;函数的返回值应该定义为&nbsp;int&nbsp;类型，C&nbsp;和&nbsp;C++&nbsp;标准中
都是这样规定的。虽然在一些编译器中，void&nbsp;main&nbsp;可以通过编译（如&nbsp;vc6），但并非所有编译器都支持&nbsp;void&nbsp;main&nbsp;，因为标准中从来
没有定义过&nbsp;void&nbsp;main&nbsp;。g++3.2&nbsp;中如果&nbsp;main&nbsp;函数的返回值不是&nbsp;int&nbsp;类型，就根本通不过编译。而&nbsp;gcc3.2&nbsp;则会发出警
告。所以，如果你想你的程序拥有很好的可移植性，请一定要用&nbsp;int&nbsp;main&nbsp;。&nbsp;<br>
<br>
&nbsp;&nbsp;<br>
<br>
4.&nbsp;返回值的作用&nbsp;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;main&nbsp;函数的返回值用于说明程序的退
出状态。如果返回&nbsp;0，则代表程序正常退出，否则代表程序异常退出。下面我们在&nbsp;winxp&nbsp;环境下做一个小实验。首先编
译下面的程序：&nbsp;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;main(&nbsp;void&nbsp;)&nbsp;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;0;&nbsp;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>
<br>
然
后打开附件里的“命令提示符”，在命令行里运行刚才编译好的可执行文件，然后输入“echo&nbsp;%ERRORLEVEL%”，回车，就可以看到程序的返回值
为&nbsp;0&nbsp;。假设刚才编译好的文件是&nbsp;a.exe&nbsp;，如果输入“a&nbsp;&amp;&amp;&nbsp;dir”，则会列出当前目录下的文件夹和文件。但是如果改成
“return&nbsp;-1”，或者别的非&nbsp;0&nbsp;值，重新编译后输入“a&nbsp;&amp;&amp;&nbsp;dir”，则&nbsp;dir&nbsp;不会执行。因为&nbsp;&amp;&amp;
&nbsp;的含义是：如果&nbsp;&amp;&amp;&nbsp;前面的程序正常退出，则继续执行&nbsp;&amp;&amp;&nbsp;后面的程序，否则不执行。也就是说，利用程序的返回
值，我们可以控制要不要执行下一个程序。这就是&nbsp;int&nbsp;main&nbsp;的好处。如果你有兴趣，也可以把&nbsp;main&nbsp;函数的返回值类型改成非&nbsp;int&nbsp;类型
（如&nbsp;float），重新编译后执行“a&nbsp;&amp;&amp;&nbsp;dir”，看看会出现什么情况，想想为什么会出现那样的情况。顺便提一下，如果输入
&nbsp;a&nbsp;||&nbsp;dir&nbsp;的话，则表示如果&nbsp;a&nbsp;异常退出，则执行&nbsp;dir&nbsp;。&nbsp;<br>
<br>
int&nbsp;main(&nbsp;int&nbsp;argc,&nbsp;char&nbsp;*argv[],&nbsp;char&nbsp;
*env[]&nbsp;)&nbsp;也不是标准C里面定义的东西~char&nbsp;*env[]是某些编译器提供的扩展功能~用于获取系统的环境
设定~因为不是标准~故而移植性差~不推荐使用 <br>
<img src ="http://www.cppblog.com/apollo/aggbug/3947.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-03-09 22:22 <a href="http://www.cppblog.com/apollo/articles/Main.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个关于指针的问题</title><link>http://www.cppblog.com/apollo/articles/AboutPoint.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Wed, 08 Mar 2006 15:16:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/AboutPoint.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/3913.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/AboutPoint.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/3913.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/3913.html</trackback:ping><description><![CDATA[<div class="postTitle">
		<a id="viewpost1_TitleUrl" class="postTitle2" href="../../geforcex/archive/2005/12/21/1936.html">一个关于指针的问题</a>
	</div>

	有些东西在你没有遇到之前还真是不知道自己没有弄清楚，也许是我平时细节的地方注意少了，看来以后要多加注意了。<br>
<br>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="../../Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">pStr;<br><img src="../../Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">&nbsp;ch;<br><img src="../../Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">&nbsp;str[]&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Hello</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">;<br><img src="../../Images/OutliningIndicators/None.gif" align="top"><br><img src="../../Images/OutliningIndicators/None.gif" align="top">ch&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;str[</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">];<br><img src="../../Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">pStr&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;str[</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">];<br><img src="../../Images/OutliningIndicators/None.gif" align="top"><br><img src="../../Images/OutliningIndicators/None.gif" align="top">printf(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">ch&nbsp;=&nbsp;%c\n</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,&nbsp;ch);<br><img src="../../Images/OutliningIndicators/None.gif" align="top">printf(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">*pStr&nbsp;=&nbsp;%c</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">pStr);</span></div>
<br>
此时打印ch值的时候能正确输出，但是打印pStr[0]的时候就出问题了，跟踪发现是pStr[0] = str[1];这句出现问题。<br>
<br>
原
来，char *pStr;
只定义了一个4字节的指针变量，而这个变量里面的内容是将要指向一个char类型变量的，但是此时pStr只是个“野指针”，并没有指向一个char类型
的内存单元，所以，当用*pStr来访问这个元素时，系统根本不知道该访问何处的空间，因此，在使用pStr前，必须让它指向一个具体的空间。<br>
<br>
由上面可以将相关语句改为 
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="../../Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">pStr;<br><img src="../../Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">&nbsp;ch;<br><img src="../../Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">&nbsp;str[]&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Hello</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">;<br><img src="../../Images/OutliningIndicators/None.gif" align="top"><br><img src="../../Images/OutliningIndicators/None.gif" align="top">pStr&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">ch;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">pStr指向ch、获得初始化</span><span style="color: rgb(0, 128, 0);"><br><img src="../../Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 0);">pStr&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">str[</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">];&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">pStr指向str[1]地址、获得初始化</span><span style="color: rgb(0, 128, 0);"><br><img src="../../Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 0);">ch&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;str[</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">];<br><img src="../../Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">pStr&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;str[</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">];<br><img src="../../Images/OutliningIndicators/None.gif" align="top"><br><img src="../../Images/OutliningIndicators/None.gif" align="top">printf(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">ch&nbsp;=&nbsp;%c\n</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,&nbsp;ch);<br><img src="../../Images/OutliningIndicators/None.gif" align="top">printf(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">*pStr&nbsp;=&nbsp;%c</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">pStr);</span></div>
也就是说，要先给指针一个地址值初始化它，然后才能用*访问它指向的内容。<br>
<br>
<br>
<br>
◎另外，<font color="#ff0000">在子函数中使用malloc()/new()分配的内存空间不会因子函数的返回而消失</font>，函数只会清理调子函数里定义的变量的空间，如： 
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="../../Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">&nbsp;func()<br><img id="Codehighlighter1_13_77_Open_Image" onclick="this.style.display='none'; Codehighlighter1_13_77_Open_Text.style.display='none'; Codehighlighter1_13_77_Closed_Image.style.display='inline'; Codehighlighter1_13_77_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_13_77_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_13_77_Closed_Text.style.display='none'; Codehighlighter1_13_77_Open_Image.style.display='inline'; Codehighlighter1_13_77_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_13_77_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_13_77_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">p;<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;p&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;(</span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">)malloc(</span><span style="color: rgb(0, 0, 255);">sizeof</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">));<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;p;<br><img src="../../Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">返回后，p所在空间被释放，但是p所指空间还存在</span></div>
所以，可以用p1=func();来获得在func()中分配的空间。<br>
<br>
此中方法可以用来解决“指针的指针”使用不方便的问题。步骤分2步：1、把传入的指针的指针参数去掉；2、把函数的返回值赋给要改变的对象的指针： 
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="../../Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;GetMemory2(</span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">**</span><span style="color: rgb(0, 0, 0);">p,&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;num)<br><img id="Codehighlighter1_35_80_Open_Image" onclick="this.style.display='none'; Codehighlighter1_35_80_Open_Text.style.display='none'; Codehighlighter1_35_80_Closed_Image.style.display='inline'; Codehighlighter1_35_80_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_35_80_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_35_80_Closed_Text.style.display='none'; Codehighlighter1_35_80_Open_Image.style.display='inline'; Codehighlighter1_35_80_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_35_80_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_35_80_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">p&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;(</span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">)malloc(</span><span style="color: rgb(0, 0, 255);">sizeof</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">)&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">&nbsp;num);<br><img src="../../Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: rgb(0, 0, 0);"><br><img src="../../Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;Test2(</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">)<br><img id="Codehighlighter1_99_230_Open_Image" onclick="this.style.display='none'; Codehighlighter1_99_230_Open_Text.style.display='none'; Codehighlighter1_99_230_Closed_Image.style.display='inline'; Codehighlighter1_99_230_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_99_230_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_99_230_Closed_Text.style.display='none'; Codehighlighter1_99_230_Open_Image.style.display='inline'; Codehighlighter1_99_230_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_99_230_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_99_230_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">str&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;NULL;<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;GetMemory2(</span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">str,&nbsp;</span><span style="color: rgb(0, 0, 0);">100</span><span style="color: rgb(0, 0, 0);">);&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;注意参数是&nbsp;&amp;str，而不是str</span><span style="color: rgb(0, 128, 0);"><br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;strcpy(str,&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">hello</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;cout</span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);">&nbsp;str&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);">&nbsp;endl;<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;free(str);&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="../../Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: rgb(0, 0, 0);"><br><img src="../../Images/OutliningIndicators/None.gif" align="top"><br><img id="Codehighlighter1_233_254_Open_Image" onclick="this.style.display='none'; Codehighlighter1_233_254_Open_Text.style.display='none'; Codehighlighter1_233_254_Closed_Image.style.display='inline'; Codehighlighter1_233_254_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_233_254_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_233_254_Closed_Text.style.display='none'; Codehighlighter1_233_254_Open_Image.style.display='inline'; Codehighlighter1_233_254_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_233_254_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);">/**/</span><span id="Codehighlighter1_233_254_Open_Text"><span style="color: rgb(128, 128, 128);">//////</span><span style="color: rgb(0, 128, 0);">下面是用传递动态内存的方法实现</span><span style="color: rgb(128, 128, 128);"></span></span><br><img src="../../Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">GetMemory3(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;num)<br><img id="Codehighlighter1_281_343_Open_Image" onclick="this.style.display='none'; Codehighlighter1_281_343_Open_Text.style.display='none'; Codehighlighter1_281_343_Closed_Image.style.display='inline'; Codehighlighter1_281_343_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_281_343_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_281_343_Closed_Text.style.display='none'; Codehighlighter1_281_343_Open_Image.style.display='inline'; Codehighlighter1_281_343_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_281_343_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_281_343_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">p&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;(</span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">)malloc(</span><span style="color: rgb(0, 0, 255);">sizeof</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">)&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">&nbsp;num);<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;p;<br><img src="../../Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: rgb(0, 0, 0);"><br><img src="../../Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;Test3(</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">)<br><img id="Codehighlighter1_362_470_Open_Image" onclick="this.style.display='none'; Codehighlighter1_362_470_Open_Text.style.display='none'; Codehighlighter1_362_470_Closed_Image.style.display='inline'; Codehighlighter1_362_470_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_362_470_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_362_470_Closed_Text.style.display='none'; Codehighlighter1_362_470_Open_Image.style.display='inline'; Codehighlighter1_362_470_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_362_470_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_362_470_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">str&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;NULL;<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;str&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;GetMemory3(</span><span style="color: rgb(0, 0, 0);">100</span><span style="color: rgb(0, 0, 0);">);&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;strcpy(str,&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">hello</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;cout</span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);">&nbsp;str&nbsp;</span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);">&nbsp;endl;<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;free(str);&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="../../Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: rgb(0, 0, 0);"><br><img src="../../Images/OutliningIndicators/None.gif" align="top"></span></div>
因
为此时用malloc/new分配的内存空间是堆里面的，函数返回时不会回收；而如果在子函数中用char
p[]="asdfgewq";则p是在栈中定义的（先分配p的空间，然后讲字符串拷贝进去，跟char
*p="asdfasdf"分配在全局静态内存中不一样），所以会被系统收回。<img src ="http://www.cppblog.com/apollo/aggbug/3913.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-03-08 23:16 <a href="http://www.cppblog.com/apollo/articles/AboutPoint.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Singleton模式的演化</title><link>http://www.cppblog.com/apollo/articles/Singleton.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Wed, 08 Mar 2006 15:14:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/Singleton.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/3912.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/Singleton.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/3912.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/3912.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Singleton模式是常用的设计模式之一，但是要实现一个真正实用的设计模式却也不是件容易的事情。1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 标准的实现class Singleton{public:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static Singleton * Instan...&nbsp;&nbsp;<a href='http://www.cppblog.com/apollo/articles/Singleton.html'>阅读全文</a><img src ="http://www.cppblog.com/apollo/aggbug/3912.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-03-08 23:14 <a href="http://www.cppblog.com/apollo/articles/Singleton.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>杂记(一些解决问题的惯用法)</title><link>http://www.cppblog.com/apollo/articles/3682.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Fri, 03 Mar 2006 07:30:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/3682.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/3682.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/3682.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/3682.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/3682.html</trackback:ping><description><![CDATA[<P><FONT size=1>1. c++中类的相互引用<BR>&nbsp; <BR>&nbsp; 原则是:相互引用的class要分别写.h和.cpp文件(分别合用一个.h,.cpp也可)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在.h文件中只需申明class类型即可，一定不要包含其他类的头文件<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在.cpp文件中必须要包含其他要引用的头件<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不要将函数申明跟寒暑提在同一文件中实现,否则会出意想不到的错误！！！<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a.h b.h 合成一个.h文件<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a.cpp b.cpp 合成一个.cpp文件也可<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp; a.h&nbsp; <BR>&nbsp;&nbsp;#ifndef _A_<BR>&nbsp;&nbsp;#define _A_<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;class b;<BR>&nbsp;&nbsp;class a;<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;class a {<BR>&nbsp;&nbsp;&nbsp;friend class&nbsp; b;<BR>&nbsp;&nbsp;private:<BR>&nbsp;&nbsp;&nbsp;int aa;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;void a1( b m );<BR>&nbsp;&nbsp;};<BR>&nbsp;&nbsp;#endif<BR>&nbsp;&nbsp; a.cpp<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #include "stdafx.h"<BR>&nbsp;&nbsp;#include "a.h"<BR>&nbsp;&nbsp;#include "b.h"<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;void a::a1(b m )<BR>&nbsp;&nbsp;{&nbsp;<BR>&nbsp;&nbsp;&nbsp;m.bb = 0 ;<BR>&nbsp;&nbsp;}<BR>&nbsp;&nbsp; b.h<BR>&nbsp;&nbsp;#ifndef _B_<BR>&nbsp;&nbsp;#define _B_<BR>&nbsp;&nbsp;class&nbsp; b;<BR>&nbsp;&nbsp;class a;<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;class&nbsp; b <BR>&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;friend class a;<BR>&nbsp;&nbsp;private:<BR>&nbsp;&nbsp;&nbsp;int bb;<BR>&nbsp;&nbsp;&nbsp;void zzz(a n);<BR>&nbsp;&nbsp;};&nbsp;<BR>&nbsp;&nbsp;#endif<BR>&nbsp;b.cpp<BR>&nbsp;&nbsp;&nbsp;&nbsp; #include "stdafx.h"<BR>&nbsp;&nbsp;#include "b.h"<BR>&nbsp;&nbsp;#include "a.h"<BR>&nbsp;&nbsp;void b::zzz(a m )<BR>&nbsp;&nbsp;{&nbsp;<BR>&nbsp;&nbsp;&nbsp;m.aa = 0 ;<BR>&nbsp;&nbsp;}&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp; main.cpp<BR>&nbsp;&nbsp;#include "stdafx.h"<BR>&nbsp;&nbsp;#include "a.h"<BR>&nbsp;&nbsp;#include "b.h"<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;int main(int argc, char* argv[])<BR>&nbsp;&nbsp;{ <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a aa;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b bb;<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<BR>&nbsp;&nbsp;}</FONT></P>
<P><FONT size=1>2. 链表的好用法<BR>&nbsp;&nbsp; struct a {<BR>&nbsp;&nbsp;&nbsp;&nbsp; static a *mLinkedList; // 申明为一个静态变量<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp; &nbsp;a *mNext;<BR>&nbsp;&nbsp;&nbsp;&nbsp; bool mCanRemoteCreate;</FONT></P>
<P><FONT size=1>&nbsp;&nbsp;&nbsp; a(bool canRemoteCreate)<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mNext = mLinkedList;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mLinkedList = this;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mCanRemoteCreate = canRemoteCreate;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; static int *create(const char *name);<BR>&nbsp; };<BR>&nbsp; <BR>&nbsp; a *a::mLinkedList = NULL; // 初始化<BR>&nbsp; <BR>3. 灵活的应用# ##<BR>Token-Pasting Operator (##)</FONT></P>
<P><FONT size=1>#define paster( n ) printf( "token" #n " = %d", token##n )<BR>int token9 = 9;<BR>If a macro is called with a numeric argument like<BR>paster( 9 );the macro yields<BR>printf( "token" "9" " = %d", token9 );which becomes<BR>printf( "token9 = %d", token9 );</FONT></P>
<P><FONT size=1>Stringizing Operator (#)<BR>#define stringer( x ) printf( #x "\n" )<BR>void main()<BR>{<BR>&nbsp;&nbsp;&nbsp; stringer( In quotes in the printf function call\n ); <BR>&nbsp;&nbsp;&nbsp; stringer( "In quotes when printed to the screen"\n );&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; stringer( "This: \"&nbsp; prints an escaped double quote" );<BR>}<BR>Such invocations would be expanded during preprocessing, producing the following code:<BR>void main()<BR>{<BR>&nbsp;&nbsp; printf( "In quotes in the printf function call\n" "\n" );<BR>&nbsp;&nbsp; printf( "\"In quotes when printed to the screen\"\n" "\n" );<BR>&nbsp;&nbsp; printf( "\"This: </FONT><A><FONT size=1>\\\</FONT></A><FONT size=1>" prints an escaped double quote\"" "\n" );<BR>}<BR>When the program is run, screen output for each line is as follows:In quotes in the printf function call<BR>"In quotes when printed to the screen"<BR>"This: \" prints an escaped double quotation mark"<BR>#define IMPLEMENT_NETCONNECTION(className, classGroup, canRemoteCreate) \<BR>&nbsp;&nbsp; NetClassRep* className::getClassRep() const { return &amp;className::dynClassRep; } \<BR>&nbsp;&nbsp; NetClassRepInstance&lt;className&gt; className::dynClassRep(#className, 0, NetClassTypeNone, 0); \<BR>&nbsp;&nbsp; NetClassGroup className::getNetClassGroup() const { return classGroup; } \<BR>&nbsp;&nbsp; static NetConnectionRep g##className##Rep(&amp;className::dynClassRep, canRemoteCreate)</FONT></P>
<P><FONT size=1>4. 枚举:初始化为0值开始,后者比前者大1,除非显式指定.<BR>&nbsp;&nbsp; By default, the first enumerator has a value of 0, and each successive enumerator is one larger <BR>&nbsp;&nbsp; than the value of the previous one, unless you explicitly specify a value for a particular <BR>&nbsp;&nbsp; enumerator. Enumerators needn’t have unique values. The name of each enumerator is treated <BR>&nbsp;&nbsp; as a constant and must be unique within the scope where the enum is defined. An enumerator <BR>&nbsp;&nbsp; can be promoted to an integer value. However, converting an integer to an enumerator requires <BR>&nbsp;&nbsp; an explicit cast, and the results are not defined.</FONT></P>
<P><FONT size=1>=========================<BR>一些优秀的数学算法<BR>5.1 /// Determines if number is a power of two.<BR>&nbsp;inline bool isPow2(const U32 number)<BR>&nbsp;{<BR>&nbsp;&nbsp;&nbsp; return (number &amp; (number - 1)) == 0;<BR>&nbsp;}<BR>5.2 浮点数的计算机中的储存方法</FONT></P>
<P><FONT size=1>&nbsp;&nbsp;&nbsp; 单精度&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1|&nbsp;&nbsp; 8&nbsp;&nbsp; |&nbsp;&nbsp; 23&nbsp;&nbsp;&nbsp; | <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 符号&nbsp; 指数&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 尾数 <BR>&nbsp;&nbsp;&nbsp; 双精度&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1|&nbsp;&nbsp; 11&nbsp; |&nbsp;&nbsp; 52&nbsp;&nbsp;&nbsp; | <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 符号&nbsp; 指数&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 尾数&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; 10110.100011 -&gt; 1.0110100011* 2(4) 2的4之方<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; 符号位 0 <BR>&nbsp;&nbsp;&nbsp; 尾数&nbsp;&nbsp; 0110100011<BR>&nbsp;&nbsp;&nbsp; 指数&nbsp;&nbsp; 4 以过剩127储存 +127= 131&nbsp; -&gt; 10000011<BR>&nbsp;&nbsp;&nbsp; 所以&nbsp; IEEE 754 : 0100000110110100011<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; -0.0010011&nbsp; -&gt; -1.0011 * 2(-3) 2的-3之方<BR>&nbsp;&nbsp;&nbsp; 符号位：-1<BR>&nbsp;&nbsp;&nbsp; 尾数&nbsp; : 0011<BR>&nbsp;&nbsp;&nbsp; 指数为：-3&nbsp; +127&nbsp; 的124 -〉01111100<BR>&nbsp;&nbsp;&nbsp; 所以： 1 01111100 0011000000000000000000<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; /// Determines the binary logarithm of the input value rounded down to the nearest power of 2.<BR>&nbsp;inline U32 getBinLog2(U32 value)<BR>&nbsp;{<BR>&nbsp;&nbsp;&nbsp; F32 floatValue = F32(value);<BR>&nbsp;&nbsp;&nbsp; return (*((U32 *) &amp;floatValue) &gt;&gt; 23) - 127;<BR>&nbsp;}</FONT></P><img src ="http://www.cppblog.com/apollo/aggbug/3682.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-03-03 15:30 <a href="http://www.cppblog.com/apollo/articles/3682.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C经典用法</title><link>http://www.cppblog.com/apollo/articles/CClassical.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Fri, 03 Mar 2006 07:23:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/CClassical.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/3681.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/CClassical.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/3681.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/3681.html</trackback:ping><description><![CDATA[<DIV class=postTitle><FONT size=1>&nbsp; /* The following macros process structure members:&nbsp; to determine the&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp; /* offset of a structure member from the beginning of the structure, and&nbsp;&nbsp; */<BR>&nbsp; /* to detemine the size of a member of a structure.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */</FONT></DIV>
<P><FONT size=1>&nbsp; #define DEFS_OFFSET(s,m)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (DEFS_UI16)&amp;(((s *)0)-&gt;m)<BR>&nbsp; #define DEFS_MEMBER_SIZE(s,m)&nbsp; sizeof(((s *)0)-&gt;m)</FONT></P>
<P><FONT size=1>&nbsp; /* The following macros make it easier to specify binary numbers. For&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp; /* example, to specify a byte in binary:&nbsp; DEFS_BINARY(01100001) or to&nbsp;&nbsp; */<BR>&nbsp; /* specify a word in binary:&nbsp; DEFS_BINARY_WORD(00111101,11001010)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */</FONT></P>
<P><FONT size=1>&nbsp; #define DEFS_BINARY_CONVERT(byte) (((byte &amp; 0x10000000L) / 0x200000L) +&nbsp; \<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ((byte &amp; 0x01000000L) / 0x040000L) +&nbsp; \<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ((byte &amp; 0x00100000L) / 0x008000L) +&nbsp; \<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ((byte &amp; 0x00010000L) / 0x001000L) +&nbsp; \<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ((byte &amp; 0x00001000L) / 0x000200L) +&nbsp; \<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ((byte &amp; 0x00000100L) / 0x000040L) +&nbsp; \<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ((byte &amp; 0x00000010L) / 0x000008L) +&nbsp; \<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ((byte &amp; 0x00000001L) / 0x000001L))</FONT></P>
<P><FONT size=1>&nbsp; #define DEFS_BINARY(byte) DEFS_BINARY_CONVERT(0x##byte)</FONT></P>
<P><FONT size=1>&nbsp; #define DEFS_BINARY_WORD(high,low) (DEFS_BINARY_CONVERT(0x##high) * 256) + \</FONT></P>
<P><FONT size=1><U>2006.1.7 字节交换顺序</U><BR><BR>/* This is a set of routines for demonstrating the effects of<BR>&nbsp;byte ordering between little endian and big endian machines</FONT></P>
<P><FONT size=1>&nbsp;Big Endian (B_ENDIAN == TRUE):</FONT></P>
<P><FONT size=1>&nbsp;&nbsp;MSB [ n | n+1 | n+2 | n+3 ] LSB</FONT></P>
<P><FONT size=1>&nbsp;Little Endian (B_ENDIAN == FALSE):</FONT></P>
<P><FONT size=1>&nbsp;&nbsp;MSB [ n+3 | n+2 | n+1 | n] LSB</FONT></P>
<P><FONT size=1>&nbsp;little/big-endian is bitness as well.&nbsp; For example,</FONT></P>
<P><FONT size=1>&nbsp;&nbsp;struct {<BR>&nbsp;&nbsp;&nbsp;short b:5,&nbsp;&nbsp; --- we _want_ signed for the example ---<BR>&nbsp;&nbsp;&nbsp;c:11;<BR>&nbsp;&nbsp;};</FONT></P>
<P><FONT size=1>&nbsp;is stored in little-endian (gint32el) ['+' denotes sign bit]:</FONT></P>
<P><FONT size=1>&nbsp;tf_Bitstream view --&gt;<BR>&nbsp;&nbsp; 0123456789A BCDEF<BR>&nbsp;&nbsp;|-----c----+|--b-+|</FONT></P>
<P><FONT size=1>&nbsp;Whereas bigendian (Motorola) stores it thus:</FONT></P>
<P><FONT size=1>&nbsp;tf_Bitstream view --&gt;<BR>&nbsp;&nbsp; FEDCB A9876543210<BR>&nbsp;&nbsp;|+-b--|+----c-----| </FONT></P>
<P><FONT size=1>&nbsp;So, you have to invert bits as well to convert endianness.</FONT></P>
<P><FONT size=1>&nbsp;#define Gettf_Bit(Val,Idx) ( ( (Val) &amp; (1&lt;&lt;(Idx)) ) )<BR>&nbsp;#define Settf_Bit(Val,Idx,tf_Bit) ( ( (Val) &amp; (~(1&lt;&lt;Idx)) ) | ((tf_Bit)&lt;&lt;(Idx)) )<BR>&nbsp;for ( i = 0; i &lt; sizeof(Val)*8; i++)<BR>&nbsp;&nbsp;&nbsp; NewVal = Settf_Bit(NewVal,sizeof(Val)*8-i-1, Gettf_Bit(Val,i));<BR>*/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></P>
<P><FONT size=1><U>DNP<BR></U>DnpMasterStart<BR>&nbsp; --&gt; taskSpawn ("tDnpMaster", priority, VX_FP_TASK, 0x8000,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (FUNCPTR) DnpMasterTask,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (int) ini_name, 0, 0, 0, 0, 0, 0, 0, 0, 0)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp; dnpMasterTask ---&gt; dnp_init()<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ---&gt; ca_task_initialize()<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ---&gt; ca_add_fd_registration()<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ---&gt; 从配置文件中得到dnp的配置信息<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ---&gt; pdpdvrs_initDNP()<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ---&gt; addr_init()<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ---&gt; dnp_loop()<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp; DnpMasterAddDevice<BR>&nbsp; DnpMasterAdd8550<BR>&nbsp; DnpMasterAddText<BR>&nbsp; <BR>&nbsp; DNP　PEER TO PEER<BR>&nbsp; <BR>&nbsp; 一些debug信息<BR>&nbsp; <BR>&nbsp; 物理层<BR>&nbsp; 　．利用查表法来确定链路层的长度<BR>&nbsp; ---&gt;． pdpphys_initPhysRecMgr 物理层初始化，分配内存<BR>&nbsp; 　&nbsp; ． valid_address() <BR>&nbsp; 　　． pdpphys_parseDNPframe()　<BR>&nbsp; <BR>&nbsp; <BR>&nbsp; DnpMasterTask<BR>&nbsp;&nbsp;<BR><BR>========================================================<BR><BR>&nbsp; <U>串口：从温旧梦<BR></U><BR>&nbsp; 　非重叠模式优点　．直接<BR>&nbsp; 　　　　　　　　　．易移植<BR>&nbsp; 　　　　　　缺点　．线程中读、写相互堵塞<BR>&nbsp; 　　　　　　　　　．线程间相互堵塞（包括读之间，写之间，读写之间）<BR>&nbsp; <BR>&nbsp; 　　　　　　单片机，嵌入式如vxworks，任务中相对简单的程序中常用<BR>&nbsp; <BR>&nbsp; 　重叠模式　优点　．灵活，效率高（后台执行操作）<BR>&nbsp; 　　　　　　　　　．多线程间，线程中，读写操作不会相互堵塞<BR>&nbsp; 　　　　　　缺点　．不那么直接<BR>&nbsp; 　　　　　　　　　．不易于移植<BR>&nbsp; 　<BR>&nbsp; EV_RXCHAR：事件通知模式用在非重叠模是一个比较好的方式，因为程序不用轮询串口，以节省CPU的thread quantum<BR>&nbsp; 　　　　　 方式如下：<BR>&nbsp; 　　　　　DWORD dwCommEvent;<BR>&nbsp;&nbsp;&nbsp;DWORD dwRead;<BR>&nbsp;&nbsp;&nbsp;char&nbsp; chRead;<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;if (!SetCommMask(hComm, EV_RXCHAR))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Error setting communications event mask.<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;for ( ; ; ) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (WaitCommEvent(hComm, &amp;dwCommEvent, NULL)) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ReadFile(hComm, &amp;chRead, 1, &amp;dwRead, NULL))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // A byte has been read; process it.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // An error occurred in the ReadFile call.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Error in WaitCommEvent.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;问题出现在：当多个字节连续的发送，第１个byte到，引起EV_RXCHAR 事件发生，<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WaitCommEvent指示可读．第２个byte紧接着到，EV_RXCHAR只是在内部置位，<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当第１个byte读完，调用WaitCommEvent时，系统再次指示EV_RXCHAR 事件发生，<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 可读第２个byte,问题出现在当第２个字符到达，而没有被读出时，第３个字符到<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 达了，此时系统也期望将对应于第３个字符的EV_RXCHAR置位，但是系统中的<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EV_RXCHAR标志位已经被第２个已经置位了，于是就被忽略，当第２个自负读出<BR>&nbsp;&nbsp;　　　　　　后，只能在系统缓冲区，等待第４个字符到，而读出第３个字符，这样代码和系统<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 就失去同步。<BR>&nbsp;&nbsp;&nbsp;　　　　　　（我觉得这种情况在一般情况下不会出现,在单片机、<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 嵌入式应该是一个一个字符往外蹦，）<BR>&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;　　　　　　而且WaitCommEvent会导致很多其它事件丢失，在高速情况下。<BR>&nbsp;&nbsp;　　　　　　　　<BR>&nbsp;&nbsp;　　解决办法是：利用ClearCommError判断缓冲中的字符个数，一次性读完所有到达字符 </FONT></P><img src ="http://www.cppblog.com/apollo/aggbug/3681.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-03-03 15:23 <a href="http://www.cppblog.com/apollo/articles/CClassical.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用一个问题探讨程序优化</title><link>http://www.cppblog.com/apollo/articles/problemSolve.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Thu, 02 Mar 2006 14:37:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/problemSolve.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/3658.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/problemSolve.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/3658.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/3658.html</trackback:ping><description><![CDATA[题目是:找出01字符串中0和1出现的最大次数.<br>
<br>
代码：
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="../../Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 0);">#include</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">iostream</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br><img src="../../Images/OutliningIndicators/None.gif" align="top">#include</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 255);">string</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"><br><img src="../../Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">using</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">namespace</span><span style="color: rgb(0, 0, 0);">&nbsp;std;<br><img src="../../Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;main()<br><img id="Codehighlighter1_69_565_Open_Image" onclick="this.style.display='none'; Codehighlighter1_69_565_Open_Text.style.display='none'; Codehighlighter1_69_565_Closed_Image.style.display='inline'; Codehighlighter1_69_565_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_69_565_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_69_565_Closed_Text.style.display='none'; Codehighlighter1_69_565_Open_Image.style.display='inline'; Codehighlighter1_69_565_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_69_565_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_69_565_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">char</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">a</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">010000010111101101000000000</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">;<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&nbsp;i,temp0</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">,temp1</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">,max0</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">,max1</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">对变量初始化，如果不初始化，变量值是随机的</span><span style="color: rgb(0, 128, 0);"><br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);">(i</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;i</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">strlen(a);i</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">)<br><img id="Codehighlighter1_199_507_Open_Image" onclick="this.style.display='none'; Codehighlighter1_199_507_Open_Text.style.display='none'; Codehighlighter1_199_507_Closed_Image.style.display='inline'; Codehighlighter1_199_507_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_199_507_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_199_507_Closed_Text.style.display='none'; Codehighlighter1_199_507_Open_Image.style.display='inline'; Codehighlighter1_199_507_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_199_507_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_199_507_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">switch</span><span style="color: rgb(0, 0, 0);">(a[i])<br><img id="Codehighlighter1_218_504_Open_Image" onclick="this.style.display='none'; Codehighlighter1_218_504_Open_Text.style.display='none'; Codehighlighter1_218_504_Closed_Image.style.display='inline'; Codehighlighter1_218_504_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_218_504_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_218_504_Closed_Text.style.display='none'; Codehighlighter1_218_504_Open_Image.style.display='inline'; Codehighlighter1_218_504_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_218_504_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_218_504_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">case</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">:<br><img id="Codehighlighter1_236_359_Open_Image" onclick="this.style.display='none'; Codehighlighter1_236_359_Open_Text.style.display='none'; Codehighlighter1_236_359_Closed_Image.style.display='inline'; Codehighlighter1_236_359_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_236_359_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_236_359_Closed_Text.style.display='none'; Codehighlighter1_236_359_Open_Image.style.display='inline'; Codehighlighter1_236_359_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_236_359_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_236_359_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp0</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">;<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(a[i</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">]</span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">||</span><span style="color: rgb(0, 0, 0);">i</span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);">strlen(a)</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">)<br><img id="Codehighlighter1_291_343_Open_Image" onclick="this.style.display='none'; Codehighlighter1_291_343_Open_Text.style.display='none'; Codehighlighter1_291_343_Closed_Image.style.display='inline'; Codehighlighter1_291_343_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_291_343_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_291_343_Closed_Text.style.display='none'; Codehighlighter1_291_343_Open_Image.style.display='inline'; Codehighlighter1_291_343_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_291_343_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_291_343_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(max0</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">temp0)&nbsp;max0</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">temp0;<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp0</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br><img src="../../Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: rgb(0, 0, 0);"><br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">break</span><span style="color: rgb(0, 0, 0);">;<br><img src="../../Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: rgb(0, 0, 0);"><br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">case</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">:<br><img id="Codehighlighter1_377_500_Open_Image" onclick="this.style.display='none'; Codehighlighter1_377_500_Open_Text.style.display='none'; Codehighlighter1_377_500_Closed_Image.style.display='inline'; Codehighlighter1_377_500_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_377_500_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_377_500_Closed_Text.style.display='none'; Codehighlighter1_377_500_Open_Image.style.display='inline'; Codehighlighter1_377_500_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_377_500_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_377_500_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp1</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">;<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(a[i</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">]</span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">||</span><span style="color: rgb(0, 0, 0);">i</span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);">strlen(a)</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">)<br><img id="Codehighlighter1_432_484_Open_Image" onclick="this.style.display='none'; Codehighlighter1_432_484_Open_Text.style.display='none'; Codehighlighter1_432_484_Closed_Image.style.display='inline'; Codehighlighter1_432_484_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_432_484_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_432_484_Closed_Text.style.display='none'; Codehighlighter1_432_484_Open_Image.style.display='inline'; Codehighlighter1_432_484_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_432_484_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_432_484_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(max1</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">temp1)&nbsp;max1</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">temp1;<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp1</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br><img src="../../Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: rgb(0, 0, 0);"><br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">break</span><span style="color: rgb(0, 0, 0);">;<br><img src="../../Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: rgb(0, 0, 0);"><br><img src="../../Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: rgb(0, 0, 0);"><br><img src="../../Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: rgb(0, 0, 0);"><br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">max0=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);">max0</span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);">endl;<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">max1=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);">max1</span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);">endl;<br><img src="../../Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span></div>
<br>
<br>
那为什么不对i初始化呢？因为尽管i没被初始化，它的初始值是随机的，但在循环参数表里面已经对他进行赋值，所以i的随机值已经被0覆盖。<br>
<br>
#include &lt;iostream&gt;
<br>
void main()
<br>
{
<br>
  char *a="010000010111101101000000000";
<br>
  int max[2] = {0, 0};
<br>
  int count[2] = {0, 0};
<br>

<br>
  while(*a)
<br>
  {
<br>
    int index = *a - '0';
<br>
    count[index] ++;
<br>
	count[index^1] = 0; // count[index?0:1] = 0; // count[index==0?1:0] = 0;
<br>
    if(count[index] &gt; max[index])
<br>
      max[index] = count[index];
<br>
    a++;
<br>
  }
<br>
  std::cout &lt;&lt; "max 0: " &lt;&lt; max[0] &lt;&lt; std::endl;
<br>
  std::cout &lt;&lt; "max 1: " &lt;&lt; max[1] &lt;&lt; std::endl;
<br>
}
<br>

<br>
// output
<br>
// max 0: 9
<br>
// max 1: 4
<br>

<br>
点评：
<br>
1. 就C字串来说，从头到尾的遍历不需要for，用while是最佳选择。
<br>
2. strlen是很浪费的操作，如果非要用，对同一个不变长度的字串来说，用一个变量来存储，然后重复使用，比重复计算strlen要好得多。
<br>
3. 对数字串来说，可以直接将字符减去'0'得到相应的数字。
<br>
4. 比较判断其实并不比赋值省时，有时候直接赋值，比起比较后再赋值可能更有效率。更何况你的判断条件达三条之多才决定是否需要赋值。
<br>
  所以if(a[i+1]=='0'/*或'1'*/||i==strlen(a)-1)可以省掉。
<br>
5. 利用数组的下标，会给你带来意想不到的简洁。
<br>

<br>
6. 最后，变量没有初始化，是算法设计的问题。如果初始条件都没有确定，只能说明你的算法没有想清楚。<br>
<img src ="http://www.cppblog.com/apollo/aggbug/3658.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-03-02 22:37 <a href="http://www.cppblog.com/apollo/articles/problemSolve.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>qsort函数应用大全</title><link>http://www.cppblog.com/apollo/articles/Qsort.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Thu, 02 Mar 2006 14:30:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/Qsort.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/3657.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/Qsort.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/3657.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/3657.html</trackback:ping><description><![CDATA[
	七种qsort排序方法 <br>
<br>
&lt;本文中排序都是采用的从小到大排序&gt; <br>
<br>
一、对int类型数组排序 <br>
<br>
int num[100]; <br>
<br>
Sample: <br>
<br>
int cmp ( const void *a , const void *b ) <br>
{ <br>
return *(int *)a - *(int *)b; <br>
} <br>
<br>
qsort(num,100,sizeof(num[0]),cmp); <br>
<br>
二、对char类型数组排序（同int类型） <br>
<br>
char word[100]; <br>
<br>
Sample: <br>
<br>
int cmp( const void *a , const void *b ) <br>
{ <br>
return *(char *)a - *(int *)b; <br>
} <br>
<br>
qsort(word,100,sizeof(word[0]),cmp); <br>
<br>
三、对double类型数组排序（特别要注意） <br>
<br>
double in[100]; <br>
<br>
int cmp( const void *a , const void *b ) <br>
{ <br>
return *(double *)a &gt; *(double *)b ? 1 : -1; <br>
} <br>
<br>
qsort(in,100,sizeof(in[0]),cmp)； <br>
<br>
四、对结构体一级排序 <br>
<br>
struct In <br>
{ <br>
double data; <br>
int other; <br>
}s[100] <br>
<br>
//按照data的值从小到大将结构体排序,关于结构体内的排序关键数据data的类型可以很多种，参考上面的例子写 <br>
<br>
int cmp( const void *a ,const void *b) <br>
{ <br>
return (*(In *)a)-&gt;data &gt; (*(In *)b)-&gt;data ? 1 : -1; <br>
} <br>
<br>
qsort(s,100,sizeof(s[0]),cmp); <br>
<br>
五、对结构体二级排序 <br>
<br>
struct In <br>
{ <br>
int x; <br>
int y; <br>
}s[100]; <br>
<br>
//按照x从小到大排序，当x相等时按照y从大到小排序 <br>
<br>
int cmp( const void *a , const void *b ) <br>
{ <br>
struct In *c = (In *)a; <br>
struct In *d = (In *)b; <br>
if(c-&gt;x != d-&gt;x) return c-&gt;x - d-&gt;x; <br>
else return d-&gt;y - c-&gt;y; <br>
} <br>
<br>
qsort(s,100,sizeof(s[0]),cmp); <br>
<br>
六、对字符串进行排序 <br>
<br>
struct In <br>
{ <br>
int data; <br>
char str[100]; <br>
}s[100]; <br>
<br>
//按照结构体中字符串str的字典顺序排序 <br>
<br>
int cmp ( const void *a , const void *b ) <br>
{ <br>
return strcmp( (*(In *)a)-&gt;str , (*(In *)b)-&gt;str ); <br>
} <br>
<br>
qsort(s,100,sizeof(s[0]),cmp); <br>
<br>
七、计算几何中求凸包的cmp <br>
<br>
int cmp(const void *a,const void *b) //重点cmp函数，把除了1点外的所有点，旋转角度排序 <br>
{ <br>
struct point *c=(point *)a; <br>
struct point *d=(point *)b; <br>
if( calc(*c,*d,p[1]) &lt; 0) return 1; <br>
else
if( !calc(*c,*d,p[1]) &amp;&amp; dis(c-&gt;x,c-&gt;y,p[1].x,p[1].y)
&lt; dis(d-&gt;x,d-&gt;y,p[1].x,p[1].y)) //如果在一条直线上，则把远的放在前面 <br>
return 1; <br>
else return -1; <br>
} <br>
<br>
PS: <br>
<br>
其中的qsort函数包含在&lt;stdlib.h&gt;的头文件里，strcmp包含在&lt;string.h&gt;的头文件里<img src ="http://www.cppblog.com/apollo/aggbug/3657.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-03-02 22:30 <a href="http://www.cppblog.com/apollo/articles/Qsort.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++指针探讨 </title><link>http://www.cppblog.com/apollo/articles/CPPPoint.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Thu, 02 Mar 2006 14:27:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/CPPPoint.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/3656.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/CPPPoint.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/3656.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/3656.html</trackback:ping><description><![CDATA[&nbsp;
<h2 class="diaryTitle">C++指针探讨 (-) 数据指针&nbsp;
<br>
</h2>
<br>
&nbsp;&nbsp;&nbsp; 指针，在C/C++语言中一直是很受宠的；几乎找不到一个不使用指针的C/C++应用。用于存储数据和程序的地址，这是指针的基本功能。用于指向整型数，
用整数指针(int*)；指向浮点数用浮点数指针(float*)；指向结构，用对应的结构指针(struct xxx
*)；指向任意地址，用无类型指针(void*)。<br>
&nbsp;&nbsp;&nbsp; 有时候，我们需要一些通用的指针。在C语言当中，(void*)
可以代表一切；但是在C++中，我们还有一些比较特殊的指针，无法用(void*)来表示。事实上，在C++中，想找到一个通用的指针，特别是通用的函数
指针可是一个“不可能任务”。<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;
C++是一种强类型的语言，C++的编译器的功能是强大的，它的其中一个设计目标，是尽力为程序找出程序中可能存在的问题；因此，C++对类型的匹配是非
常严格的。在C语言中，你可以用void*来指向一切；但在C++中，void*并不能指向一切，就算能，也没有意义，因为它不能帮你发现问题，比如，用
函数指针赋值给一个数据指针。<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; 下面我们来探讨一下，C++中如何存储各种类型的指针。<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; 1.&nbsp; 数据指针<br>
&nbsp;&nbsp;&nbsp; &nbsp;数据指针分为两种：常规数据指针和成员数据指针<br>
&nbsp;&nbsp;&nbsp; &nbsp;<br>
&nbsp;&nbsp;&nbsp; 1.1 常规数据指针 (难度: 1)<br>
&nbsp;&nbsp;&nbsp; &nbsp;这个不用说明了，和C语言一样，很简单，直接定义、赋值就够了。常见的有：int*, double* 等等。<br>
&nbsp;&nbsp;&nbsp; &nbsp;如：<br>
&nbsp;&nbsp;&nbsp; &nbsp;int value = 123;<br>
&nbsp;&nbsp;&nbsp; &nbsp;int * pn = &amp;value;<br>
&nbsp;&nbsp;&nbsp; &nbsp;<br>
&nbsp;&nbsp;&nbsp; &nbsp;<br>
&nbsp;&nbsp;&nbsp; 1.2 成员数据指针 (难度: 4)<br>
&nbsp;&nbsp;&nbsp; &nbsp;有如下的结构：<br>
&nbsp;&nbsp;&nbsp; &nbsp;struct MyStruct<br>
&nbsp;&nbsp;&nbsp; &nbsp;{<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; int key;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; int value;<br>
&nbsp;&nbsp;&nbsp; &nbsp;};<br>
&nbsp;&nbsp;&nbsp; &nbsp;<br>
&nbsp;&nbsp;&nbsp; &nbsp;现在有一个结构对象:<br>
&nbsp;&nbsp;&nbsp; &nbsp;MyStruct me;<br>
&nbsp;&nbsp;&nbsp; &nbsp;<br>
&nbsp;&nbsp;&nbsp; &nbsp;我们需要 value 成员的地址，我们可以：<br>
&nbsp;&nbsp;&nbsp; &nbsp;int * pValue = &amp;me.value;<br>
&nbsp;&nbsp;&nbsp; &nbsp;<br>
&nbsp;&nbsp;&nbsp; &nbsp;:) 没什么难的对吧？<br>
&nbsp;&nbsp;&nbsp; &nbsp;<br>
&nbsp;&nbsp;&nbsp; &nbsp;我们假设一下，现在有一个结构的指针：<br>
&nbsp;&nbsp;&nbsp; &nbsp;<br>
&nbsp;&nbsp;&nbsp; &nbsp;MyStruct* pMe = new MyStruct;<br>
&nbsp;&nbsp;&nbsp; &nbsp;现在，我们要取得 pMe中 value 的指针，要怎么做呢？<br>
&nbsp;&nbsp;&nbsp; &nbsp;int * ppValue = &amp;pMe-&gt;value;<br>
&nbsp;&nbsp;&nbsp; &nbsp;<br>
&nbsp;&nbsp;&nbsp; &nbsp;:) 这仍然很容易。<br>
&nbsp;&nbsp;&nbsp; &nbsp;<br>
&nbsp;&nbsp;&nbsp; &nbsp;当然了，上面讨论的仍然是属于第一种范筹----常规数据指针。<br>
&nbsp;&nbsp;&nbsp; &nbsp;<br>
&nbsp;&nbsp;&nbsp; &nbsp;好了，我们现在需要一种指针，它指向MyStruct中的任一数据成员，那么它应该是这样的子：<br>
&nbsp;&nbsp;&nbsp; &nbsp;int MyStruct::* pMV = &amp;MyStruct::value;<br>
&nbsp;&nbsp;&nbsp; &nbsp;或<br>
&nbsp;&nbsp;&nbsp; &nbsp;int MyStruct::* pMK = &amp;MyStruct::key;<br>
&nbsp;&nbsp;&nbsp; &nbsp;<br>
&nbsp;&nbsp;&nbsp; &nbsp;这种指针的用途是用于取得结构成员在结构内的地址。我们可以通过该指针来访问成员数据：<br>
&nbsp;&nbsp;&nbsp; &nbsp;int value = pMe-&gt;*pMV; // 取得pMe的value成员数据。<br>
&nbsp;&nbsp;&nbsp; &nbsp;int value = me.*pMK; // 取得me的key成员数据。<br>
&nbsp;&nbsp;&nbsp; &nbsp;<br>
&nbsp;&nbsp;&nbsp; &nbsp;也许有人会问了，这种指针有什么用？<br>
&nbsp;&nbsp;&nbsp; &nbsp;确实，成员指针本来就不是一种很常用的指针。不过，在某些时候还是很有用处的。我们先来看看下面的一个函数：<br>
&nbsp;&nbsp;&nbsp; &nbsp;<br>
&nbsp;&nbsp;int sum(MyStruct* objs, int MyStruct::* pm, int count)<br>
&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int result = 0;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i = 0; i &lt; count; ++i)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result += objs[i].*pm;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return result;<br>
&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp; &nbsp;<br>
&nbsp;&nbsp;&nbsp; &nbsp;这个函数的功能是什么，你能看明白吗？它的功能就是，给定count个MyStruct结构的指针，计算出给定成员数据的总和。有点拗口对吧？看看下面的程序，你也许就明白了：<br>
&nbsp;&nbsp;&nbsp; &nbsp;<br>
&nbsp;&nbsp;&nbsp; &nbsp;MyStruct me[10] =<br>
&nbsp;&nbsp;&nbsp; &nbsp;{<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;{1,2},{3,4},{5,6},{7,8},{9,10},{11,12},{13,14},{15,16},{17,18},{19,20}<br>
&nbsp;&nbsp;&nbsp; &nbsp;};<br>
&nbsp;&nbsp;&nbsp; &nbsp;<br>
&nbsp;&nbsp;&nbsp; &nbsp;int sum_value = sum(me, &amp;MyStruct::value, 10);<br>
&nbsp;&nbsp;&nbsp; &nbsp;//计算10个MyStruct结构的value成员的总和： sum_value 值 为 110&nbsp;&nbsp;&nbsp;&nbsp; (2+4+6+8+...+20)<br>
&nbsp;&nbsp;&nbsp; &nbsp;<br>
&nbsp;&nbsp;&nbsp; &nbsp;int sum_key = sum(me, &amp;MyStruct::key, 10);<br>
&nbsp;&nbsp;&nbsp; &nbsp;//计算10个MyStruct结构的key成员的总和：&nbsp;&nbsp;
sum_key 值 为 100&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (1+3+5+7+...+19)<br>
&nbsp;&nbsp;&nbsp; &nbsp;<br>
&nbsp;&nbsp;&nbsp; &nbsp;<br>
&nbsp;&nbsp;&nbsp; &nbsp;也许，你觉得用常规指针也可以做到，而且更易懂。Ok，没问题：<br>
&nbsp;&nbsp;&nbsp; &nbsp;int sum_value(MyStruct* objs, int count)<br>
&nbsp;&nbsp;&nbsp; &nbsp;{<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;int result = 0;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;for(int i = 0; i &lt; count; ++i)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;result += objs[i].value;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;return result;<br>
&nbsp;&nbsp;&nbsp; &nbsp;}<br>
&nbsp;&nbsp;&nbsp; &nbsp;你是想这么做吗？但这么做，你只能计算value，如果要算key的话，你要多写一个函数。有多少个成员需要计算的话，你就要写多少个函数，多麻烦啊。<br>
<br>
<h2 class="diaryTitle">C++指针探讨 (二) 函数指针 - -</h2>

<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</p>
<p>
</p>

<p>&nbsp;&nbsp;&nbsp; 在C/C++中，数据指针是最直接，也最常用的，因此，理解起来也比较容易。而函数指针，作为运行时动态调用（比如回调函数 CallBack Function）是一种常见的，而且是很好用的手段，不能不好好认识一番。</p>

<p>&nbsp;&nbsp;&nbsp; 接下来，我们就讨论一下函数指针。<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 2 常规函数指针(难度: 3)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font style="background-color: rgb(204, 204, 255);">void(*fp)();</font><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fp 是一个典型的函数指针，用于指向无参数，无返回值的函数。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void(*fp2)(int);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fp2 也是一个函数指针，用于指向有一个整型参数，无返回值的函数。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当然，有经验人士一般都会建议使用typedef来定义函数指针的类型，如：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typedef void(* FP)();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FP fp3; // 和上面的fp一样的定义。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
函数指针之所以让初学者畏惧，最主要的原因是它的括号太多了；某些用途的函数指针，往往会让人陷在括号堆中出不来，这里就不举例了，因为不是本文讨论的范
围；typedef 方法可以有效的减少括号的数量，以及理清层次，所以受到推荐。本文暂时只考虑简单的函数指针，因此暂不用到typedef。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 假如有如下两个函数：<br>&nbsp; void f1()<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "call f " &lt;&lt; std::endl;<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;void f2(int a)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "call f2( " &lt;&lt; a &lt;&lt; " )" &lt;&lt; std::endl;<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;现在需要通过函数指针来调用，我们需要给指针指定函数：<br>&nbsp;&nbsp;fp = &amp;f1;&nbsp;// 也可以用：fp = f1;<br>&nbsp;&nbsp;fp2= &amp;f2;&nbsp;// 也可以用：fp2= f2;<br>&nbsp;&nbsp;void (*fp3)() = &amp;f1;&nbsp;// 也可以用：void (*fp3)() = f1;&nbsp;&nbsp;<br>&nbsp;&nbsp;调用时如下：<br>&nbsp;&nbsp;fp();&nbsp;// 或 (*fp)();<br>&nbsp;&nbsp;fp2(1); // 或 (*fp2)(1);<br>&nbsp;&nbsp;fp3();&nbsp; // 或 (*fp3)();<br>&nbsp;&nbsp;对于此两种调用方法，效果完全一样，我推荐用前一种。后一种不仅仅是多打了键盘，而且也损失了一些灵活性。这里暂且不说它。<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;C
++强调类型安全。也就是说，不同类型的变量是不能直接赋值的，否则轻则警告，重则报错。这是一个很有用的特性，常常能帮我们找到问题。因此，有识之士认
为，C++中的任何一外警告都不能忽视。甚至有人提出，编译的时候不能出现任何警告信息，也就是说，警告应该当作错误一样处理。<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;比如，我们把f1赋值给fp2，那么C++编译器(vc7.1)就会报错：<br>&nbsp;&nbsp;fp2 = &amp;f1; // error C2440: “=” : 无法从“void (__cdecl *)(void)”转换为“void (__cdecl *)(int)”<br>&nbsp;&nbsp;fp1 = &amp;f1; // OK<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;这样，编译器可以帮我们找出编码上的错误，节省了我们的排错时间。C++编译器正致力于这一点。<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;考虑一下C++标准模板库的sort函数：<br>&nbsp;&nbsp;// 快速排序函数<br>&nbsp;&nbsp;template<class class="" pr="" randomaccessiterator=""><br>&nbsp;&nbsp;&nbsp;&nbsp; void sort(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RandomAccessIterator _First, // 需排序数据的第一个元素位置<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RandomAccessIterator _Last,&nbsp; // 需排序数据的最后一个元素位置（不参与排序）<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BinaryPredicate _Comp&nbsp;&nbsp;&nbsp;&nbsp; // 排序使用的比较算法(可以是函数指针、函数对象等)<br>&nbsp;&nbsp;&nbsp;&nbsp; );</class></p>

<p>&nbsp;&nbsp;比如，我们有一个整型数组：<br>&nbsp;&nbsp;int n[5] = {3,2,1,8,9};<br>&nbsp;&nbsp;要对它进行升序排序，我们需定义一个比较函数：<br>&nbsp;&nbsp;bool less(int a, int b)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return a &lt; b; //&nbsp;感谢网友指出笔误之处。原为 return a-b 是错误的。<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;然后用：<br>&nbsp;&nbsp;sort(n, n+5, less);<br>&nbsp;&nbsp;<br>&nbsp; <br>&nbsp;&nbsp;这样，不需要改变sort函数的定义，就可以按任意方法进行排序，是不是很灵活？&nbsp;&nbsp;<br>&nbsp;&nbsp;这种用法以C++的标准模板库(STL)中非常流行。另外，操作系统中也经常使用回调(CallBack)函数，实际上，所谓回调函数，本质就是函数指针。</p>

（附注）<br>
本文中为了说明函数指针，使用了less和great这两个函数。在C/C++的标准模板库中已经有相应的函数可以直接使用，不需要自已定义。<br>
<img src ="http://www.cppblog.com/apollo/aggbug/3656.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-03-02 22:27 <a href="http://www.cppblog.com/apollo/articles/CPPPoint.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>字符串与数之间转换函数</title><link>http://www.cppblog.com/apollo/articles/str2Num.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Thu, 02 Mar 2006 14:07:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/str2Num.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/3654.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/str2Num.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/3654.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/3654.html</trackback:ping><description><![CDATA[<table width="100%">
<tbody><tr><td valign="top" width="80"><div align="right"><font face="宋体" size="2"><br></font></div></td>
<td valign="top"><font face="宋体" size="2"><br>atof（将字符串转换成浮点型数） </font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">相关函数 </font></div></td>
<td valign="top"><font face="宋体" size="2">atoi，atol，strtod，strtol，strtoul<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">表头文件 </font></div></td>
<td valign="top"><font face="宋体" size="2">#include &lt;stdlib.h&gt;<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">定义函数 </font></div></td>
<td valign="top"><font face="宋体" size="2">double atof(const char *nptr);<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">函数说明 </font></div></td>
<td valign="top"><font face="宋体" size="2">atof()会扫描参数nptr字符串，跳过前面的空格字符，直到遇上数字或正负符号才开始做转换，而再遇到非数字或字符串结束时('\0')才结束转换，并将结果返回。参数nptr字符串可包含正负号、小数点或E(e)来表示指数部分，如123.456或123e-2。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">返回值 </font></div></td>
<td valign="top"><font face="宋体" size="2">返回转换后的浮点型数。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">附加说明 </font></div></td>
<td valign="top"><font face="宋体" size="2">atof()与使用strtod(nptr,(char**)NULL)结果相同。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">范例 </font></div></td>
<td valign="top"><font face="宋体" size="2">/* 将字符串a 与字符串b转换成数字后相加*/<br>#include&lt;stdlib.h&gt;<br>main()<br>{<br>char *a=”-100.23”;<br>char *b=”200e-2”;<br>float c;<br>c=atof(a)+atof(b);<br>printf(“c=%.2f\n”,c);<br>}<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">执行 </font></div></td>
<td valign="top"><font face="宋体" size="2">c=-98.23<br></font></td></tr>
<tr>
<td valign="top" width="80">　 
<div align="right"><br><font face="宋体" size="2"><a name="linuxc15"></a></font></div></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2"><br></font></div></td>
<td valign="top"><font face="宋体" size="2"><br>atoi（将字符串转换成整型数） </font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">相关函数 </font></div></td>
<td valign="top"><font face="宋体" size="2">atof，atol，atrtod，strtol，strtoul<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">表头文件 </font></div></td>
<td valign="top"><font face="宋体" size="2">#include&lt;stdlib.h&gt;<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">定义函数 </font></div></td>
<td valign="top"><font face="宋体" size="2">int atoi(const char *nptr);<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">函数说明 </font></div></td>
<td valign="top"><font face="宋体" size="2">atoi()会扫描参数nptr字符串，跳过前面的空格字符，直到遇上数字或正负符号才开始做转换，而再遇到非数字或字符串结束时('\0')才结束转换，并将结果返回。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">返回值 </font></div></td>
<td valign="top"><font face="宋体" size="2">返回转换后的整型数。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">附加说明 </font></div></td>
<td valign="top"><font face="宋体" size="2">atoi()与使用strtol(nptr，(char**)NULL，10)；结果相同。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">范例 </font></div></td>
<td valign="top"><font face="宋体" size="2">/* 将字符串a 与字符串b转换成数字后相加*/<br>#include&lt;stdlib.h&gt;<br>mian()<br>{<br>char a[]=”-100”;<br>char b[]=”456”;<br>int c;<br>c=atoi(a)+atoi(b);<br>printf(c=%d\n”,c);<br>}<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">执行 </font></div></td>
<td valign="top"><font face="宋体" size="2">c=356<br></font></td></tr>
<tr>
<td valign="top" width="80">　 
<div align="right"><br><font face="宋体" size="2"><a name="linuxc16"></a></font></div></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2"><br></font></div></td>
<td valign="top"><font face="宋体" size="2"><br>atol（将字符串转换成长整型数） </font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">相关函数 </font></div></td>
<td valign="top"><font face="宋体" size="2">atof，atoi，strtod，strtol，strtoul<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">表头文件 </font></div></td>
<td valign="top"><font face="宋体" size="2">#include&lt;stdlib.h&gt;<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">定义函数 </font></div></td>
<td valign="top"><font face="宋体" size="2">long atol(const char *nptr);<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">函数说明 </font></div></td>
<td valign="top"><font face="宋体" size="2">atol()会扫描参数nptr字符串，跳过前面的空格字符，直到遇上数字或正负符号才开始做转换，而再遇到非数字或字符串结束时('\0')才结束转换，并将结果返回。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">返回值 </font></div></td>
<td valign="top"><font face="宋体" size="2">返回转换后的长整型数。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">附加说明 </font></div></td>
<td valign="top"><font face="宋体" size="2">atol()与使用strtol(nptr,(char**)NULL,10)；结果相同。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">范例 </font></div></td>
<td valign="top"><font face="宋体" size="2">/*将字符串a与字符串b转换成数字后相加*/<br>#include&lt;stdlib.h&gt;<br>main()<br>{<br>char a[]=”1000000000”;<br>char b[]=” 234567890”;<br>long c;<br>c=atol(a)+atol(b);<br>printf(“c=%d\n”,c);<br>}<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">执行 </font></div></td>
<td valign="top"><font face="宋体" size="2">c=1234567890<br></font></td></tr>
<tr>
<td valign="top" width="80">　 
<div align="right"><br><font face="宋体" size="2"><a name="linuxc17"></a></font></div></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2"><br></font></div></td>
<td valign="top"><font face="宋体" size="2"><br>gcvt（将浮点型数转换为字符串，取四舍五入） </font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">相关函数 </font></div></td>
<td valign="top"><font face="宋体" size="2">ecvt，fcvt，sprintf<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">表头文件 </font></div></td>
<td valign="top"><font face="宋体" size="2">#include&lt;stdlib.h&gt;<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">定义函数 </font></div></td>
<td valign="top"><font face="宋体" size="2">char *gcvt(double number，size_t ndigits，char *buf);<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">函数说明 </font></div></td>
<td valign="top"><font face="宋体" size="2">gcvt()用来将参数number转换成ASCII码字符串，
参数ndigits表示显示的位数。gcvt()与ecvt()和fcvt()不同的地方在于，gcvt()所转换后的字符串包含小数点或正负符号。若转
换成功，转换后的字符串会放在参数buf指针所指的空间。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">返回值 </font></div></td>
<td valign="top"><font face="宋体" size="2">返回一字符串指针，此地址即为buf指针。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">附加说明 </font></div></td>
<td valign="top"><font face="宋体" size="2"><br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">范例 </font></div></td>
<td valign="top"><font face="宋体" size="2">#include&lt;stdlib.h&gt;<br>main()<br>{<br>double a=123.45;<br>double b=-1234.56;<br>char *ptr;<br>int decpt,sign;<br>gcvt(a,5,ptr);<br>printf(“a value=%s\n”,ptr);<br>ptr=gcvt(b,6,ptr);<br>printf(“b value=%s\n”,ptr);<br>}<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">执行 </font></div></td>
<td valign="top"><font face="宋体" size="2">a value=123.45<br>b value=-1234.56<br></font></td></tr>
<tr>
<td valign="top" width="80">　 
<div align="right"><br><font face="宋体" size="2"><a name="linuxc18"></a></font></div></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2"><br></font></div></td>
<td valign="top"><font face="宋体" size="2"><br>strtod（将字符串转换成浮点数） </font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">相关函数 </font></div></td>
<td valign="top"><font face="宋体" size="2">atoi，atol，strtod，strtol，strtoul<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">表头文件 </font></div></td>
<td valign="top"><font face="宋体" size="2">#include&lt;stdlib.h&gt;<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">定义函数 </font></div></td>
<td valign="top"><font face="宋体" size="2">double strtod(const char *nptr,char **endptr);<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">函数说明 </font></div></td>
<td valign="top"><font face="宋体" size="2">strtod()会扫描参数nptr字符串，跳过前面的空格字
符，直到遇上数字或正负符号才开始做转换，到出现非数字或字符串结束时('\0')才结束转换，并将结果返回。若endptr不为NULL，则会将遇到不
合条件而终止的nptr中的字符指针由endptr传回。参数nptr字符串可包含正负号、小数点或E(e)来表示指数部分。如123.456或123e
-2。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">返回值 </font></div></td>
<td valign="top"><font face="宋体" size="2">返回转换后的浮点型数。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">附加说明 </font></div></td>
<td valign="top"><font face="宋体" size="2">参考atof()。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">范例 </font></div></td>
<td valign="top"><font face="宋体" size="2">/*将字符串a，b，c 分别采用10，2，16 进制转换成数字*/<br>#include&lt;stdlib.h&gt;<br>mian()<br>{<br>char a[]=”1000000000”;<br>char b[]=”1000000000”;<br>char c[]=”ffff”;<br>printf(“a=%d\n”,strtod(a,NULL,10));<br>printf(“b=%d\n”,strtod(b,NULL,2));<br>printf(“c=%d\n”,strtod(c,NULL,16));<br>}<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">执行 </font></div></td>
<td valign="top"><font face="宋体" size="2">a=1000000000<br>b=512<br>c=65535<br></font></td></tr>
<tr>
<td valign="top" width="80">　 
<div align="right"><br><font face="宋体" size="2"><a name="linuxc19"></a></font></div></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2"><br></font></div></td>
<td valign="top"><font face="宋体" size="2"><br>strtol（将字符串转换成长整型数） </font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">相关函数 </font></div></td>
<td valign="top"><font face="宋体" size="2">atof，atoi，atol，strtod，strtoul<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">表头文件 </font></div></td>
<td valign="top"><font face="宋体" size="2">#include&lt;stdlib.h&gt;<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">定义函数 </font></div></td>
<td valign="top"><font face="宋体" size="2">long int strtol(const char *nptr,char **endptr,int base);<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">函数说明 </font></div></td>
<td valign="top"><font face="宋体" size="2">strtol()会将参数nptr字符串根据参数base来转换
成长整型数。参数base范围从2至36，或0。参数base代表采用的进制方式，如base值为10则采用10进制，若base值为16则采用16进制
等。当base值为0时则是采用10进制做转换，但遇到如'0x'前置字符则会使用16进制做转换。一开始strtol()会扫描参数nptr字符串，跳
过前面的空格字符，直到遇上数字或正负符号才开始做转换，再遇到非数字或字符串结束时('\0')结束转换，并将结果返回。若参数endptr不为
NULL，则会将遇到不合条件而终止的nptr中的字符指针由endptr返回。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">返回值 </font></div></td>
<td valign="top"><font face="宋体" size="2">返回转换后的长整型数，否则返回ERANGE并将错误代码存入errno中。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">附加说明 </font></div></td>
<td valign="top"><font face="宋体" size="2">ERANGE指定的转换字符串超出合法范围。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">范例 </font></div></td>
<td valign="top"><font face="宋体" size="2">/* 将字符串a，b，c 分别采用10，2，16进制转换成数字*/<br>#include&lt;stdlib.h&gt;<br>main()<br>{<br>char a[]=”1000000000”;<br>char b[]=”1000000000”;<br>char c[]=”ffff”;<br>printf(“a=%d\n”,strtol(a,NULL,10));<br>printf(“b=%d\n”,strtol(b,NULL,2));<br>printf(“c=%d\n”,strtol(c,NULL,16));<br>}<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">执行 </font></div></td>
<td valign="top"><font face="宋体" size="2">a=1000000000<br>b=512<br>c=65535<br></font></td></tr>
<tr>
<td valign="top" width="80">　 
<div align="right"><br><font face="宋体" size="2"><a name="linuxc20"></a></font></div></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2"><br></font></div></td>
<td valign="top"><font face="宋体" size="2"><br>strtoul（将字符串转换成无符号长整型数） </font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">相关函数 </font></div></td>
<td valign="top"><font face="宋体" size="2">atof，atoi，atol，strtod，strtol<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">表头文件 </font></div></td>
<td valign="top"><font face="宋体" size="2">#include&lt;stdlib.h&gt;<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">定义函数 </font></div></td>
<td valign="top"><font face="宋体" size="2">unsigned long int strtoul(const char *nptr,char **endptr,int base);<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">函数说明 </font></div></td>
<td valign="top"><font face="宋体" size="2">strtoul()会将参数nptr字符串根据参数base来转
换成无符号的长整型数。参数base范围从2至36，或0。参数base代表采用的进制方式，如base值为10则采用10进制，若base值为16则采
用16进制数等。当base值为0时则是采用10进制做转换，但遇到如'0x'前置字符则会使用16进制做转换。一开始strtoul()会扫描参数
nptr字符串，跳过前面的空格字符串，直到遇上数字或正负符号才开始做转换，再遇到非数字或字符串结束时('\0')结束转换，并将结果返回。若参数
endptr不为NULL，则会将遇到不合条件而终止的nptr中的字符指针由endptr返回。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">返回值 </font></div></td>
<td valign="top"><font face="宋体" size="2">返回转换后的长整型数，否则返回ERANGE并将错误代码存入errno中。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">附加说明 </font></div></td>
<td valign="top"><font face="宋体" size="2">ERANGE指定的转换字符串超出合法范围。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">范例 </font></div></td>
<td valign="top"><font face="宋体" size="2">参考strtol()<br></font></td></tr>
<tr>
<td valign="top" width="80">　 
<div align="right"><br><font face="宋体" size="2"><a name="linuxc21"></a></font></div></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2"><br></font></div></td>
<td valign="top"><font face="宋体" size="2"><br>toascii（将整型数转换成合法的ASCII 码字符） </font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">相关函数 </font></div></td>
<td valign="top"><font face="宋体" size="2">isascii，toupper，tolower<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">表头文件 </font></div></td>
<td valign="top"><font face="宋体" size="2">#include&lt;ctype.h&gt;<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">定义函数 </font></div></td>
<td valign="top"><font face="宋体" size="2">int toascii(int c)<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">函数说明 </font></div></td>
<td valign="top"><font face="宋体" size="2">toascii()会将参数c转换成7位的unsigned char值，第八位则会被清除，此字符即会被转成ASCII码字符。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">返回值 </font></div></td>
<td valign="top"><font face="宋体" size="2">将转换成功的ASCII码字符值返回。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">范例 </font></div></td>
<td valign="top"><font face="宋体" size="2">#include&lt;stdlib.h&gt;<br>main()<br>{<br>int a=217;<br>char b;<br>printf(“before toascii () : a value =%d(%c)\n”,a,a);<br>b=toascii(a);<br>printf(“after toascii() : a value =%d(%c)\n”,b,b);<br>}<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">执行 </font></div></td>
<td valign="top"><font face="宋体" size="2">before toascii() : a value =217()<br>after toascii() : a value =89(Y)<br></font></td></tr>
<tr>
<td valign="top" width="80">　 
<div align="right"><br><font face="宋体" size="2"><a name="linuxc22"></a></font></div></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2"><br></font></div></td>
<td valign="top"><font face="宋体" size="2"><br>tolower（将大写字母转换成小写字母） </font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">相关函数 </font></div></td>
<td valign="top"><font face="宋体" size="2">isalpha，toupper<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">表头文件 </font></div></td>
<td valign="top"><font face="宋体" size="2">#include&lt;stdlib.h&gt;<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">定义函数 </font></div></td>
<td valign="top"><font face="宋体" size="2">int tolower(int c);<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">函数说明 </font></div></td>
<td valign="top"><font face="宋体" size="2">若参数c为大写字母则将该对应的小写字母返回。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">返回值 </font></div></td>
<td valign="top"><font face="宋体" size="2">返回转换后的小写字母，若不须转换则将参数c值返回。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">附加说明 </font></div></td>
<td valign="top"><font face="宋体" size="2"><br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">范例 </font></div></td>
<td valign="top"><font face="宋体" size="2">/* 将s字符串内的大写字母转换成小写字母*/<br>#include&lt;ctype.h&gt;<br>main()<br>{<br>char s[]=”aBcDeFgH12345;!#$”;<br>int i;<br>printf(“before tolower() : %s\n”,s);<br>for(i=0;I&lt;sizeof(s);i++)<br>s[i]=tolower(s[i]);<br>printf(“after tolower() : %s\n”,s);<br>}<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">执行 </font></div></td>
<td valign="top"><font face="宋体" size="2">before tolower() : aBcDeFgH12345;!#$<br>after tolower() : abcdefgh12345;!#$<br></font></td></tr>
<tr>
<td valign="top" width="80">　 
<div align="right"><br><font face="宋体" size="2"><a name="linuxc23"></a></font></div></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2"><br></font></div></td>
<td valign="top"><font face="宋体" size="2"><br>toupper（将小写字母转换成大写字母） </font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">相关函数 </font></div></td>
<td valign="top"><font face="宋体" size="2">isalpha，tolower<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">表头文件 </font></div></td>
<td valign="top"><font face="宋体" size="2">#include&lt;ctype.h&gt;<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">定义函数 </font></div></td>
<td valign="top"><font face="宋体" size="2">int toupper(int c);<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">函数说明 </font></div></td>
<td valign="top"><font face="宋体" size="2">若参数c为小写字母则将该对映的大写字母返回。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">返回值 </font></div></td>
<td valign="top"><font face="宋体" size="2">返回转换后的大写字母，若不须转换则将参数c值返回。<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">附加说明 </font></div></td>
<td valign="top"><font face="宋体" size="2"><br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">范例 </font></div></td>
<td valign="top"><font face="宋体" size="2">/* 将s字符串内的小写字母转换成大写字母*/<br>#include&lt;ctype.h&gt;<br>main()<br>{<br>char s[]=”aBcDeFgH12345;!#$”;<br>int i;<br>printf(“before toupper() : %s\n”,s);<br>for(i=0;I&lt;sizeof(s);i++)<br>s[i]=toupper(s[i]);<br>printf(“after toupper() : %s\n”,s);<br>}<br></font></td></tr>
<tr>
<td valign="top" width="80">
<div align="right"><font face="宋体" size="2">执行 </font></div></td>
<td valign="top"><font face="宋体" size="2">before toupper() : aBcDeFgH12345;!#$<br>after toupper() : ABCDEFGH12345;!#$</font></td></tr></tbody>
</table>
<img src ="http://www.cppblog.com/apollo/aggbug/3654.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-03-02 22:07 <a href="http://www.cppblog.com/apollo/articles/str2Num.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VC++，掀起你的盖头来</title><link>http://www.cppblog.com/apollo/articles/3570.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Tue, 28 Feb 2006 05:06:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/3570.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/3570.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/3570.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/3570.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/3570.html</trackback:ping><description><![CDATA[<P align=center><FONT size=4>VC++，掀起你的盖头来<BR>——谈VC++对象模型<BR></FONT>（美）简  格雷<BR>程化&nbsp;&nbsp;&nbsp; 译</P>
<P>译者前言</P>
<P>一个C++程序员，想要进一步提升技术水平的话，应该多了解一些语言的语意细节。对于使用VC++的程序员来说，还应该了解一些VC++对于C++的诠释。Inside the C++ Object Model虽然是一本好书，然而，书的篇幅多一些，又和具体的VC++关系小一些。因此，从篇幅和内容来看，译者认为本文是深入理解C++对象模型比较好的一个出发点。<BR>这篇文章以前看到时就觉得很好，旧文重读，感觉理解得更多一些了，于是产生了翻译出来，与大家共享的想法。虽然文章不长，但时间有限，又若干次在翻译时打盹睡着，拖拖拉拉用了小一个月。<BR>一方面因本人水平所限，另一方面因翻译时经常打盹，错误之处恐怕不少，欢迎大家批评指正。</P>
<P>1 前言</P>
<P>了解你所使用的编程语言究竟是如何实现的，对于C++程序员可能特别有意义。首先，它可以去除我们对于所使用语言的神秘感，使我们不至于对于编译器干的活感到完全不可思议；尤其重要的是，它使我们在Debug和使用语言高级特性的时候，有更多的把握。当需要提高代码效率的时候，这些知识也能够很好地帮助我们。</P>
<P>本文着重回答这样一些问题：<BR> * 类如何布局？<BR> * 成员变量如何访问？<BR> * 成员函数如何访问？<BR> * 所谓的“调整块”（adjuster thunk）是怎么回事？<BR> * 使用如下机制时，开销如何：<BR> * 单继承、多重继承、虚继承<BR> * 虚函数调用<BR> * 强制转换到基类，或者强制转换到虚基类<BR> * 异常处理<BR>首先，我们顺次考察C兼容的结构（struct）的布局，单继承，多重继承，以及虚继承；<BR>接着，我们讲成员变量和成员函数的访问，当然，这里面包含虚函数的情况；<BR>再接下来，我们考察构造函数，析构函数，以及特殊的赋值操作符成员函数是如何工作的，数组是如何动态构造和销毁的；<BR>最后，简单地介绍对异常处理的支持。</P>
<P>对每个语言特性，我们将简要介绍该特性背后的动机，该特性自身的语意（当然，本文决不是“C++入门”，大家对此要有充分认识），以及该特性在微软的VC++中是如何实现的。这里要注意区分抽象的C++语言语意与其特定实现。微软之外的其他C++厂商可能提供一个完全不同的实现，我们偶尔也会将VC++的实现与其他实现进行比较。</P>
<P>2 类布局</P>
<P>本节讨论不同的继承方式造成的不同内存布局。<BR></P>
<P>2.1 C结构（struct）</P>
<P>由于C++基于C，所以C++也“基本上”兼容C。特别地，C++规范在“结构”上使用了和C相同的，简单的内存布局原则：成员变量按其被声明的顺序排列，按具体实现所规定的对齐原则在内存地址上对齐。所有的C/C++厂商都保证他们的C/C++编译器对于有效的C结构采用完全相同的布局。这里，A是一个简单的C结构，其成员布局和对齐方式都一目了然。</P>
<P><IMG alt="" src="http://blog.csdn.net/images/blog_csdn_net/hellothere/C++Mem01.gif"><BR>struct A {<BR>&nbsp;&nbsp; char c;<BR>&nbsp;&nbsp; int i;<BR>};</P>
<P><FONT color=#0000ff>译者注：从上图可见，A在内存中占有8个字节，按照声明成员的顺序，前4个字节包含一个字符（实际占用1个字节，3个字节空着，补对齐），后4个字节包含一个整数。A的指针就指向字符开始字节处。<BR></FONT></P>
<P>2.2 有C++特征的C结构</P>
<P><BR>当然了，C++不是复杂的C，C++本质上是面向对象的语言：包含继承、封装，以及多态。原始的C结构经过改造，成了面向对象世界的基石——类。除了成员变量外，C++类还可以封装成员函数和其他东西。然而，有趣的是，除非为了实现虚函数和虚继承引入的隐藏成员变量外，C++类实例的大小完全取决于一个类及其基类的成员变量！成员函数基本上不影响类实例的大小。</P>
<P>这里提供的B是一个C结构，然而，该结构有一些C++特征：控制成员可见性的“public/protected/private”关键字、成员函数、静态成员，以及嵌套的类型声明。虽然看着琳琅满目，实际上只有成员变量才占用类实例的空间。要注意的是，C++标准委员会不限制由“public/protected/private”关键字分开的各段在实现时的先后顺序，因此，不同的编译器实现的内存布局可能并不相同。（在VC++中，成员变量总是按照声明时的顺序排列）。</P>
<P><IMG alt="" src="http://blog.csdn.net/images/blog_csdn_net/hellothere/C++Mem02.gif"></P>
<P>struct B {<BR>public:<BR>&nbsp;&nbsp; int bm1;<BR>protected:<BR>&nbsp;&nbsp; int bm2;<BR>private:<BR>&nbsp;&nbsp; int bm3;<BR>&nbsp;&nbsp; static int bsm;<BR>&nbsp;&nbsp; void bf();<BR>&nbsp;&nbsp; static void bsf();<BR>&nbsp;&nbsp; typedef void* bpv;<BR>&nbsp;&nbsp; struct N { };<BR>};</P>
<P><FONT color=#0000ff>译者注：B中，为何static int bsm不占用内存空间？因为它是静态成员，该数据存放在程序的数据段中，不在类实例中。<BR></FONT></P>
<P>2.3 单继承</P>
<P><BR>C++提供继承的目的是在不同的类型之间提取共性。比如，科学家对物种进行分类，从而有种、属、纲等说法。有了这种层次结构，我们才可能将某些具备特定性质的东西归入到最合适的分类层次上，如“怀孩子的是哺乳动物”。由于这些属性可以被子类继承，所以，我们只要知道“鲸鱼、人”是哺乳动物，就可以方便地指出“鲸鱼、人都可以怀孩子”。那些特例，如鸭嘴兽（生蛋的哺乳动物），则要求我们对缺省的属性或行为进行覆盖。<BR>C++中的继承语法很简单，在子类后加上“:base”就可以了。下面的D继承自基类C。</P>
<P><IMG alt="" src="http://blog.csdn.net/images/blog_csdn_net/hellothere/C++Mem03.gif"></P>
<P>struct C {<BR>&nbsp;&nbsp; int c1;<BR>&nbsp;&nbsp; void cf();<BR>};</P>
<P><IMG alt="" src="http://blog.csdn.net/images/blog_csdn_net/hellothere/C++Mem04.gif"></P>
<P>struct D : C {<BR>&nbsp;&nbsp; int d1;<BR>&nbsp;&nbsp; void df();<BR>};</P>
<P>既然派生类要保留基类的所有属性和行为，自然地，每个派生类的实例都包含了一份完整的基类实例数据。在D中，并不是说基类C的数据一定要放在D的数据之前，只不过这样放的话，能够保证D中的C对象地址，恰好是D对象地址的第一个字节。这种安排之下，有了派生类D的指针，要获得基类C的指针，就不必要计算偏移量了。几乎所有知名的C++厂商都采用这种内存安排。在单继承类层次下，每一个新的派生类都简单地把自己的成员变量添加到基类的成员变量之后。看看上图，C对象指针和D对象指针指向同一地址。<BR></P>
<P>2.4 多重继承</P>
<P><BR>大多数情况下，其实单继承就足够了。但是，C++为了我们的方便，还提供了多重继承。</P>
<P>比如，我们有一个组织模型，其中有经理类（分任务），工人类（干活）。那么，对于一线经理类，即既要从上级经理那里领取任务干活，又要向下级工人分任务的角色来说，如何在类层次中表达呢？单继承在此就有点力不胜任。我们可以安排经理类先继承工人类，一线经理类再继承经理类，但这种层次结构错误地让经理类继承了工人类的属性和行为。反之亦然。当然，一线经理类也可以仅仅从一个类（经理类或工人类）继承，或者一个都不继承，重新声明一个或两个接口，但这样的实现弊处太多：多态不可能了；未能重用现有的接口；最严重的是，当接口变化时，必须多处维护。最合理的情况似乎是一线经理从两个地方继承属性和行为——经理类、工人类。</P>
<P>C++就允许用多重继承来解决这样的问题：</P>
<P>struct Manager ... { ... };<BR>struct Worker ... { ... };<BR>struct MiddleManager : Manager, Worker { ... };</P>
<P>这样的继承将造成怎样的类布局呢？下面我们还是用“字母类”来举例：</P>
<P><IMG alt="" src="http://blog.csdn.net/images/blog_csdn_net/hellothere/C++Mem05.gif"></P>
<P>struct E {<BR>&nbsp;&nbsp; int e1;<BR>&nbsp;&nbsp; void ef();<BR>};</P>
<P><IMG alt="" src="http://blog.csdn.net/images/blog_csdn_net/hellothere/C++Mem06.gif"></P>
<P>struct F : C, E {<BR>&nbsp;&nbsp; int f1;<BR>&nbsp;&nbsp; void ff();<BR>&nbsp; <BR>&nbsp; <BR>};<BR>&nbsp; <BR>结构F从C和E多重继承得来。与单继承相同的是，F实例拷贝了每个基类的所有数据。与单继承不同的是，在多重继承下，内嵌的两个基类的对象指针不可能全都与派生类对象指针相同：<BR>&nbsp; <BR>F f;<BR>// (void*)&amp;f == (void*)(C*)&amp;f;<BR>// (void*)&amp;f &lt;&nbsp; (void*)(E*)&amp;f;<BR><FONT color=#0000ff>译者注：上面那行说明C对象指针与F对象指针相同，下面那行说明E对象指针与F对象指针不同。</FONT></P>
<P>观察类布局，可以看到F中内嵌的E对象，其指针与F指针并不相同。正如后文讨论强制转化和成员函数时指出的，这个偏移量会造成少量的调用开销。</P>
<P>具体的编译器实现可以自由地选择内嵌基类和派生类的布局。VC++按照基类的声明顺序先排列基类实例数据，最后才排列派生类数据。当然，派生类数据本身也是按照声明顺序布局的（本规则并非一成不变，我们会看到，当一些基类有虚函数而另一些基类没有时，内存布局并非如此）。<BR></P>
<P>2.5 虚继承</P>
<P><BR>回到我们讨论的一线经理类例子。让我们考虑这种情况：如果经理类和工人类都继承自“雇员类”，将会发生什么？<BR>&nbsp; <BR>struct Employee { ... };<BR>struct Manager : Employee { ... };<BR>struct Worker : Employee { ... };<BR>struct MiddleManager : Manager, Worker { ... };<BR>&nbsp; <BR>如果经理类和工人类都继承自雇员类，很自然地，它们每个类都会从雇员类获得一份数据拷贝。如果不作特殊处理，一线经理类的实例将含有两个雇员类实例，它们分别来自两个雇员基类。如果雇员类成员变量不多，问题不严重；如果成员变量众多，则那份多余的拷贝将造成实例生成时的严重开销。更糟的是，这两份不同的雇员实例可能分别被修改，造成数据的不一致。因此，我们需要让经理类和工人类进行特殊的声明，说明它们愿意共享一份雇员基类实例数据。</P>
<P>很不幸，在C++中，这种“共享继承”被称为“虚继承”，把问题搞得似乎很抽象。虚继承的语法很简单，在指定基类时加上virtual关键字即可。<BR>&nbsp; <BR>struct Employee { ... };<BR>struct Manager : virtual Employee { ... };<BR>struct Worker : virtual Employee { ... };<BR>struct MiddleManager : Manager, Worker { ... };<BR>&nbsp; <BR>使用虚继承，比起单继承和多重继承有更大的实现开销、调用开销。回忆一下，在单继承和多重继承的情况下，内嵌的基类实例地址比起派生类实例地址来，要么地址相同（单继承，以及多重继承的最靠左基类），要么地址相差一个固定偏移量（多重继承的非最靠左基类）。然而，当虚继承时，一般说来，派生类地址和其虚基类地址之间的偏移量是不固定的，因为如果这个派生类又被进一步继承的话，最终派生类会把共享的虚基类实例数据放到一个与上一层派生类不同的偏移量处。请看下例：<BR>&nbsp; <IMG alt="" src="http://blog.csdn.net/images/blog_csdn_net/hellothere/C++Mem07.gif"><BR>struct G : virtual C {<BR>&nbsp;&nbsp; int g1;<BR>&nbsp;&nbsp; void gf();<BR>};<BR>&nbsp; <BR><FONT color=#0000ff>译者注：GdGvbptrG（In G, the displacement of G’s virtual base pointer to G）意思是：在G中，G对象的指针与G的虚基类表指针之间的偏移量，在此可见为0，因为G对象内存布局第一项就是虚基类表指针； GdGvbptrC（In G, the displacement of G’s virtual base pointer to C）意思是：在G中，C对象的指针与G的虚基类表指针之间的偏移量，在此可见为4。</FONT></P>
<P><IMG alt="" src="http://blog.csdn.net/images/blog_csdn_net/hellothere/C++Mem08.gif"></P>
<P>struct H : virtual C {<BR>&nbsp;&nbsp; int h1;<BR>&nbsp;&nbsp; void hf();<BR>};<BR><IMG alt="" src="http://blog.csdn.net/images/blog_csdn_net/hellothere/C++Mem09.gif">&nbsp; <BR>struct I : G, H {<BR>&nbsp;&nbsp; int i1;<BR>&nbsp;&nbsp; void _if();<BR>};<BR>&nbsp; <BR>暂时不追究vbptr成员变量从何而来。从上面这些图可以直观地看到，在G对象中，内嵌的C基类对象的数据紧跟在G的数据之后，在H对象中，内嵌的C基类对象的数据也紧跟在H的数据之后。但是，在I对象中，内存布局就并非如此了。VC++实现的内存布局中，G对象实例中G对象和C对象之间的偏移，不同于I对象实例中G对象和C对象之间的偏移。当使用指针访问虚基类成员变量时，由于指针可以是指向派生类实例的基类指针，所以，编译器不能根据声明的指针类型计算偏移，而必须找到另一种间接的方法，从派生类指针计算虚基类的位置。</P>
<P>在VC++中，对每个继承自虚基类的类实例，将增加一个隐藏的“虚基类表指针”（vbptr）成员变量，从而达到间接计算虚基类位置的目的。该变量指向一个全类共享的偏移量表，表中项目记录了对于该类而言，“虚基类表指针”与虚基类之间的偏移量。</P>
<P>其它的实现方式中，有一种是在派生类中使用指针成员变量。这些指针成员变量指向派生类的虚基类，每个虚基类一个指针。这种方式的优点是：获取虚基类地址时，所用代码比较少。然而，编译器优化代码时通常都可以采取措施避免重复计算虚基类地址。况且，这种实现方式还有一个大弊端：从多个虚基类派生时，类实例将占用更多的内存空间；获取虚基类的虚基类的地址时，需要多次使用指针，从而效率较低等等。</P>
<P>在VC++中，G拥有一个隐藏的“虚基类表指针”成员，指向一个虚基类表，该表的第二项是GdGvbptrC。（在G中，虚基类对象C的地址与G的“虚基类表指针”之间的偏移量（当对于所有的派生类来说偏移量不变时，省略“d”前的前缀））。比如，在32位平台上，GdGvptrC是8个字节。同样，在I实例中的G对象实例也有“虚基类表指针”，不过该指针指向一个适用于“G处于I之中”的虚基类表，表中一项为IdGvbptrC，值为20。</P>
<P>观察前面的G、H和I，我们可以得到如下关于VC++虚继承下内存布局的结论：<BR> 首先排列非虚继承的基类实例；<BR> 有虚基类时，为每个基类增加一个隐藏的vbptr，除非已经从非虚继承的类那里继承了一个vbptr；<BR> 排列派生类的新数据成员；<BR> 在实例最后，排列每个虚基类的一个实例。</P>
<P>该布局安排使得虚基类的位置随着派生类的不同而“浮动不定”，但是，非虚基类因此也就凑在一起，彼此的偏移量固定不变。</P>
<P>3 成员变量</P>
<P>介绍了类布局之后，我们接着考虑对不同的继承方式，访问成员变量的开销究竟如何。</P>
<P>没有继承。没有任何继承关系时，访问成员变量和C语言的情况完全一样：从指向对象的指针，考虑一定的偏移量即可。<BR>&nbsp; <BR>C* pc;<BR>pc-&gt;c1; // *(pc + dCc1);<BR><FONT color=#0000ff>译者注：pc是指向C的指针。<BR> 访问C的成员变量c1，只需要在pc上加上固定的偏移量dCc1（在C中，C指针地址与其c1成员变量之间的偏移量值），再获取该指针的内容即可。</FONT></P>
<P>单继承。由于派生类实例与其基类实例之间的偏移量是常数0，所以，可以直接利用基类指针和基类成员之间的偏移量关系，如此计算得以简化。<BR>&nbsp; <BR>D* pd;<BR>pd-&gt;c1; // *(pd + dDC + dCc1); // *(pd + dDc1);<BR>pd-&gt;d1; // *(pd + dDd1);<BR><FONT color=#0000ff>译者注：D从C单继承，pd为指向D的指针。<BR> 当访问基类成员c1时，计算步骤本来应该为“pd+dDC+dCc1”，即为先计算D对象和C对象之间的偏移，再在此基础上加上C对象指针与成员变量c1之间的偏移量。然而，由于dDC恒定为0，所以直接计算C对象地址与c1之间的偏移就可以了。<BR> 当访问派生类成员d1时，直接计算偏移量。</FONT></P>
<P>多重继承。虽然派生类与某个基类之间的偏移量可能不为0，然而，该偏移量总是一个常数。只要是个常数，访问成员变量，计算成员变量偏移时的计算就可以被简化。可见即使对于多重继承来说，访问成员变量开销仍然不大。<BR>&nbsp; <BR>F* pf;<BR>pf-&gt;c1; // *(pf + dFC + dCc1); // *(pf + dFc1);<BR>pf-&gt;e1; // *(pf + dFE + dEe1); // *(pf + dFe1);<BR>pf-&gt;f1; // *(pf + dFf1);<BR><FONT color=#0000ff>译者注：F继承自C和E，pf是指向F对象的指针。<BR> 访问C类成员c1时，F对象与内嵌C对象的相对偏移为0，可以直接计算F和c1的偏移；<BR> 访问E类成员e1时，F对象与内嵌E对象的相对偏移是一个常数，F和e1之间的偏移计算也可以被简化；<BR> 访问F自己的成员f1时，直接计算偏移量。</FONT></P>
<P>虚继承。当类有虚基类时，访问非虚基类的成员仍然是计算固定偏移量的问题。然而，访问虚基类的成员变量，开销就增大了，因为必须经过如下步骤才能获得成员变量的地址：获取“虚基类表指针”；获取虚基类表中某一表项的内容；把内容中指出的偏移量加到“虚基类表指针”的地址上。然而，事情并非永远如此。正如下面访问I对象的c1成员那样，如果不是通过指针访问，而是直接通过对象实例，则派生类的布局可以在编译期间静态获得，偏移量也可以在编译时计算，因此也就不必要根据虚基类表的表项来间接计算了。</P>
<P>I* pi;<BR>pi-&gt;c1; // *(pi + dIGvbptr + (*(pi+dIGvbptr))[1] + dCc1);<BR>pi-&gt;g1; // *(pi + dIG + dGg1); // *(pi + dIg1);<BR>pi-&gt;h1; // *(pi + dIH + dHh1); // *(pi + dIh1);<BR>pi-&gt;i1; // *(pi + dIi1);<BR>I i;<BR>i.c1; // *(&amp;i + IdIC + dCc1); // *(&amp;i + IdIc1);<BR><FONT color=#0000ff>译者注：I继承自G和H，G和H的虚基类是C，pi是指向I对象的指针。<BR> 访问虚基类C的成员c1时，dIGvbptr是“在I中，I对象指针与G的“虚基类表指针”之间的偏移”，*(pi + dIGvbptr)是虚基类表的开始地址，*(pi + dIGvbptr)[1]是虚基类表的第二项的内容（在I对象中，G对象的“虚基类表指针”与虚基类之间的偏移），dCc1是C对象指针与成员变量c1之间的偏移；<BR> 访问非虚基类G的成员g1时，直接计算偏移量；<BR> 访问非虚基类H的成员h1时，直接计算偏移量；<BR> 访问自身成员i1时，直接使用偏移量；<BR> 当声明了一个对象实例，用点“.”操作符访问虚基类成员c1时，由于编译时就完全知道对象的布局情况，所以可以直接计算偏移量</FONT>。</P>
<P>当访问类继承层次中，多层虚基类的成员变量时，情况又如何呢？比如，访问虚基类的虚基类的成员变量时？一些实现方式为：保存一个指向直接虚基类的指针，然后就可以从直接虚基类找到它的虚基类，逐级上推。VC++优化了这个过程。VC++在虚基类表中增加了一些额外的项，这些项保存了从派生类到其各层虚基类的偏移量。</P>
<P>4 强制转化</P>
<P>如果没有虚基类的问题，将一个指针强制转化为另一个类型的指针代价并不高昂。如果在要求转化的两个指针之间有“基类-派生类”关系，编译器只需要简单地在两者之间加上或者减去一个偏移量即可（并且该量还往往为0）。</P>
<P>F* pf;<BR>(C*)pf; // (C*)(pf ? pf + dFC : 0); // (C*)pf;<BR>(E*)pf; // (E*)(pf ? pf + dFE : 0);</P>
<P>C和E是F的基类，将F的指针pf转化为C*或E*，只需要将pf加上一个相应的偏移量。转化为C类型指针C*时，不需要计算，因为F和C之间的偏移量为0。转化为E类型指针E*时，必须在指针上加一个非0的偏移常量dFE。C++规范要求NULL指针在强制转化后依然为NULL，因此在做强制转化需要的运算之前，VC++会检查指针是否为NULL。当然，这个检查只有当指针被显示或者隐式转化为相关类型指针时才进行；当在派生类对象中调用基类的方法，从而派生类指针被在后台转化为一个基类的Const “this” 指针时，这个检查就不需要进行了，因为在此时，该指针一定不为NULL。</P>
<P>正如你猜想的，当继承关系中存在虚基类时，强制转化的开销会比较大。具体说来，和访问虚基类成员变量的开销相当。</P>
<P>I* pi;<BR>(G*)pi; // (G*)pi;<BR>(H*)pi; // (H*)(pi ? pi + dIH : 0);<BR>(C*)pi; // (C*)(pi ? (pi+dIGvbptr + (*(pi+dIGvbptr))[1]) : 0);<BR><FONT color=#0000ff>译者注：pi是指向I对象的指针，G,H是I的基类，C是G,H的虚基类。<BR> 强制转化pi为G*时，由于G*和I*的地址相同，不需要计算；<BR> 强制转化pi为H*时，只需要考虑一个常量偏移；<BR> 强制转化pi为C*时，所作的计算和访问虚基类成员变量的开销相同，首先得到G的虚基类表指针，再从虚基类表的第二项中取出G到虚基类C的偏移量，最后根据pi、虚基类表偏移和虚基类C与虚基类表指针之间的偏移计算出C*。</FONT></P>
<P>一般说来，当从派生类中访问虚基类成员时，应该先强制转化派生类指针为虚基类指针，然后一直使用虚基类指针来访问虚基类成员变量。这样做，可以避免每次都要计算虚基类地址的开销。见下例。</P>
<P>/* before: */&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ... pi-&gt;c1 ... pi-&gt;c1 ...<BR>/* faster: */ C* pc = pi; ... pc-&gt;c1 ... pc-&gt;c1 ...<BR><FONT color=#0000ff>译者注：前者一直使用派生类指针pi，故每次访问c1都有计算虚基类地址的较大开销；后者先将pi转化为虚基类指针pc，故后续调用可以省去计算虚基类地址的开销。</FONT></P>
<P>5 成员函数</P>
<P>一个C++成员函数只是类范围内的又一个成员。X类每一个非静态的成员函数都会接受一个特殊的隐藏参数——this指针，类型为X* const。该指针在后台初始化为指向成员函数工作于其上的对象。同样，在成员函数体内，成员变量的访问是通过在后台计算与this指针的偏移来进行。<BR>&nbsp;<IMG alt="" src="http://blog.csdn.net/images/blog_csdn_net/hellothere/C++Mem10.gif"><BR>struct P {<BR>&nbsp;&nbsp; int p1;<BR>&nbsp;&nbsp; void pf(); // new<BR>&nbsp;&nbsp; virtual void pvf(); // new<BR>&nbsp; <BR>&nbsp; <BR>};<BR>&nbsp; </P>
<P>P有一个非虚成员函数pf()，以及一个虚成员函数pvf()。很明显，虚成员函数造成对象实例占用更多内存空间，因为虚成员函数需要虚函数表指针。这一点以后还会谈到。这里要特别指出的是，声明非虚成员函数不会造成任何对象实例的内存开销。现在，考虑P::pf()的定义。<BR>&nbsp; <BR>void P::pf() { // void P::pf([P *const this])<BR>&nbsp;&nbsp; ++p1;&nbsp;&nbsp; // ++(this-&gt;p1);<BR>}</P>
<P>这里P:pf()接受了一个隐藏的this指针参数，对于每个成员函数调用，编译器都会自动加上这个参数。同时，注意成员变量访问也许比看起来要代价高昂一些，因为成员变量访问通过this指针进行，在有的继承层次下，this指针需要调整，所以访问的开销可能会比较大。然而，从另一方面来说，编译器通常会把this指针缓存到寄存器中，所以，成员变量访问的代价不会比访问局部变量的效率更差。<BR>译者注：访问局部变量，需要到SP寄存器中得到栈指针，再加上局部变量与栈顶的偏移。在没有虚基类的情况下，如果编译器把this指针缓存到了寄存器中，访问成员变量的过程将与访问局部变量的开销相似。<BR></P>
<P>5.1 覆盖成员函数</P>
<P><BR>和成员变量一样，成员函数也会被继承。与成员变量不同的是，通过在派生类中重新定义基类函数，一个派生类可以覆盖，或者说替换掉基类的函数定义。覆盖是静态（根据成员函数的静态类型在编译时决定）还是动态（通过对象指针在运行时动态决定），依赖于成员函数是否被声明为“虚函数”。</P>
<P>Q从P继承了成员变量和成员函数。Q声明了pf()，覆盖了P::pf()。Q还声明了pvf()，覆盖了P::pvf()虚函数。Q还声明了新的非虚成员函数qf()，以及新的虚成员函数qvf()。</P>
<P><IMG alt="" src="http://blog.csdn.net/images/blog_csdn_net/hellothere/C++Mem11.gif"></P>
<P>struct Q : P {<BR>&nbsp;&nbsp; int q1;<BR>&nbsp;&nbsp; void pf();&nbsp; // overrides P::pf<BR>&nbsp;&nbsp; void qf();&nbsp; // new<BR>&nbsp;&nbsp; void pvf(); // overrides P::pvf<BR>&nbsp;&nbsp; virtual void qvf(); // new<BR>};<BR>&nbsp; <BR>对于非虚的成员函数来说，调用哪个成员函数是在编译时，根据“-&gt;”操作符左边指针表达式的类型静态决定的。特别地，即使ppq指向Q的实例，ppq-&gt;pf()仍然调用的是P::pf()，因为ppq被声明为“P*”。（注意，“-&gt;”操作符左边的指针类型决定隐藏的this参数的类型。）<BR>&nbsp; <BR>P p; P* pp = &amp;p; Q q; P* ppq = &amp;q; Q* pq = &amp;q;<BR>pp-&gt;pf();&nbsp; // pp-&gt;P::pf();&nbsp; // P::pf(pp);<BR>ppq-&gt;pf(); // ppq-&gt;P::pf(); // P::pf(ppq);<BR>pq-&gt;pf();&nbsp; // pq-&gt;Q::pf();&nbsp; // Q::pf((P*)pq); （错误!）<BR>pq-&gt;qf();&nbsp; // pq-&gt;Q::qf();&nbsp; // Q::qf(pq);<BR><FONT color=#0000ff>译者注：标记“错误”处，P*似应为Q*。因为pf非虚函数，而pq的类型为Q*，故应该调用到Q的pf函数上，从而该函数应该要求一个Q* const类型的this指针。</FONT></P>
<P>对于虚函数调用来说，调用哪个成员函数在运行时决定。不管“-&gt;”操作符左边的指针表达式的类型如何，调用的虚函数都是由指针实际指向的实例类型所决定。比如，尽管ppq的类型是P*，当ppq指向Q的实例时，调用的仍然是Q::pvf()。<BR>&nbsp; <BR>pp-&gt;pvf();&nbsp; // pp-&gt;P::pvf();&nbsp; // P::pvf(pp);<BR>ppq-&gt;pvf(); // ppq-&gt;Q::pvf(); // Q::pvf((Q*)ppq);<BR>pq-&gt;pvf();&nbsp; // pq-&gt;Q::pvf();&nbsp; // Q::pvf((P*)pq); （错误！）<BR><FONT color=#0000ff>译者注：标记“错误”处，P*似应为Q*。因为pvf是虚函数，pq本来就是Q*，又指向Q的实例，从哪个方面来看都不应该是P*。</FONT></P>
<P>为了实现这种机制，引入了隐藏的vfptr成员变量。一个vfptr被加入到类中（如果类中没有的话），该vfptr指向类的虚函数表（vftable）。类中每个虚函数在该类的虚函数表中都占据一项。每项保存一个对于该类适用的虚函数的地址。因此，调用虚函数的过程如下：取得实例的vfptr；通过vfptr得到虚函数表的一项；通过虚函数表该项的函数地址间接调用虚函数。也就是说，在普通函数调用的参数传递、调用、返回指令开销外，虚函数调用还需要额外的开销。</P>
<P>回头再看看P和Q的内存布局，可以发现，VC++编译器把隐藏的vfptr成员变量放在P和Q实例的开始处。这就使虚函数的调用能够尽量快一些。实际上，VC++的实现方式是，保证任何有虚函数的类的第一项永远是vfptr。这就可能要求在实例布局时，在基类前插入新的vfptr，或者要求在多重继承时，虽然在右边，然而有vfptr的基类放到左边没有vfptr的基类的前面。</P>
<P>许多C++的实现会共享或者重用从基类继承来的vfptr。比如，Q并不会有一个额外的vfptr，指向一个专门存放新的虚函数qvf()的虚函数表。Qvf项只是简单地追加到P的虚函数表的末尾。如此一来，单继承的代价就不算高昂。一旦一个实例有vfptr了，它就不需要更多的vfptr。新的派生类可以引入更多的虚函数，这些新的虚函数只是简单地在已存在的，“每类一个”的虚函数表的末尾追加新项。<BR></P>
<P>5.2 多重继承下的虚函数<BR></P>
<P>如果从多个有虚函数的基类继承，一个实例就有可能包含多个vfptr。考虑如下的R和S类：<BR>&nbsp; <IMG alt="" src="http://blog.csdn.net/images/blog_csdn_net/hellothere/C++Mem12.gif"><BR>struct R {<BR>&nbsp;&nbsp; int r1;<BR>&nbsp;&nbsp; virtual void pvf(); // new<BR>&nbsp;&nbsp; virtual void rvf(); // new<BR>};<BR>&nbsp; <IMG alt="" src="http://blog.csdn.net/images/blog_csdn_net/hellothere/C++Mem13.gif"></P>
<P>struct S : P, R {<BR>&nbsp;&nbsp; int s1;<BR>&nbsp;&nbsp; void pvf(); // overrides P::pvf and R::pvf<BR>&nbsp;&nbsp; void rvf(); // overrides R::rvf<BR>&nbsp;&nbsp; void svf(); // new<BR>};<BR>&nbsp; </P>
<P>这里R是另一个包含虚函数的类。因为S从P和R多重继承，S的实例内嵌P和R的实例，以及S自身的数据成员S::s1。注意，在多重继承下，靠右的基类R，其实例的地址和P与S不同。S::pvf覆盖了P::pvf()和R::pvf()，S::rvf()覆盖了R::rvf()。<BR>&nbsp; <BR>S s; S* ps = &amp;s;<BR>((P*)ps)-&gt;pvf(); // (*(P*)ps)-&gt;P::vfptr[0])((S*)(P*)ps)<BR>((R*)ps)-&gt;pvf(); // (*(R*)ps)-&gt;R::vfptr[0])((S*)(R*)ps)<BR>ps-&gt;pvf();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // one of the above; calls S::pvf()<BR><FONT color=#0000ff>译者注：<BR> 调用((P*)ps)-&gt;pvf()时，先到P的虚函数表中取出第一项，然后把ps转化为S*作为this指针传递进去；<BR> 调用((R*)ps)-&gt;pvf()时，先到R的虚函数表中取出第一项，然后把ps转化为S*作为this指针传递进去；</FONT></P>
<P>因为S::pvf()覆盖了P::pvf()和R::pvf()，在S的虚函数表中，相应的项也应该被覆盖。然而，我们很快注意到，不光可以用P*，还可以用R*来调用pvf()。问题出现了：R的地址与P和S的地址不同。表达式(R*)ps与表达式(P*)ps指向类布局中不同的位置。因为函数S::pvf希望获得一个S*作为隐藏的this指针参数，虚函数必须把R*转化为S*。因此，在S对R虚函数表的拷贝中，pvf函数对应的项，指向的是一个“调整块”的地址，该调整块使用必要的计算，把R*转换为需要的S*。<BR><FONT color=#0000ff>译者注：这就是“thunk1: this-= sdPR; goto S::pvf”干的事。先根据P和R在S中的偏移，调整this为P*，也就是S*，然后跳转到相应的虚函数处执行。</FONT></P>
<P>在微软VC++实现中，对于有虚函数的多重继承，只有当派生类虚函数覆盖了多个基类的虚函数时，才使用调整块。<BR></P>
<P>5.3 地址点与“逻辑this调整”<BR></P>
<P>考虑下一个虚函数S::rvf()，该函数覆盖了R::rvf()。我们都知道S::rvf()必须有一个隐藏的S*类型的this参数。但是，因为也可以用R*来调用rvf()，也就是说，R的rvf虚函数槽可能以如下方式被用到：<BR>&nbsp; <BR>((R*)ps)-&gt;rvf(); // (*((R*)ps)-&gt;R::vfptr[1])((R*)ps)<BR>&nbsp; <BR>所以，大多数实现用另一个调整块将传递给rvf的R*转换为S*。还有一些实现在S的虚函数表末尾添加一个特别的虚函数项，该虚函数项提供方法，从而可以直接调用ps-&gt;rvf()，而不用先转换R*。MSC++的实现不是这样，MSC++有意将S::rvf编译为接受一个指向S中嵌套的R实例，而非指向S实例的指针（我们称这种行为是“给派生类的指针类型与该虚函数第一次被引入时接受的指针类型相同”）。所有这些在后台透明发生，对成员变量的存取，成员函数的this指针，都进行“逻辑this调整”。</P>
<P>当然，在debugger中，必须对这种this调整进行补偿。<BR>&nbsp; <BR>ps-&gt;rvf(); // ((R*)ps)-&gt;rvf(); // S::rvf((R*)ps)<BR><FONT color=#0000ff>译者注：调用rvf虚函数时，直接给入R*作为this指针。</FONT></P>
<P>所以，当覆盖非最左边的基类的虚函数时，MSC++一般不创建调整块，也不增加额外的虚函数项。<BR></P>
<P>5.4 调整块<BR></P>
<P>正如已经描述的，有时需要调整块来调整this指针的值（this指针通常位于栈上返回地址之下，或者在寄存器中），在this指针上加或减去一个常量偏移，再调用虚函数。某些实现（尤其是基于cfront的）并不使用调整块机制。它们在每个虚函数表项中增加额外的偏移数据。每当虚函数被调用时，该偏移数据（通常为0）,被加到对象的地址上，然后对象的地址再作为this指针传入。</P>
<P>ps-&gt;rvf();<BR>// struct { void (*pfn)(void*); size_t disp; };<BR>// (*ps-&gt;vfptr[i].pfn)(ps + ps-&gt;vfptr[i].disp);<BR><FONT color=#0000ff>译者注：当调用rvf虚函数时，前一句表示虚函数表每一项是一个结构，结构中包含偏移量；后一句表示调用第i个虚函数时，this指针使用保存在虚函数表中第i项的偏移量来进行调整。</FONT></P>
<P>这种方法的缺点是虚函数表增大了，虚函数的调用也更加复杂。</P>
<P>现代基于PC的实现一般采用“调整—跳转”技术：<BR>&nbsp; <BR>S::pvf-adjust: // MSC++<BR>this -= SdPR;<BR>goto S::pvf()<BR>&nbsp; <BR>当然，下面的代码序列更好（然而，当前没有任何实现采用该方法）：<BR>&nbsp;<BR>S::pvf-adjust:<BR>this -= SdPR; // fall into S::pvf()<BR>S::pvf() { ... }<BR><FONT color=#0000ff>译者注：IBM的C++编译器使用该方法。<BR></FONT></P>
<P>5.5 虚继承下的虚函数<BR></P>
<P>T虚继承P，覆盖P的虚成员函数，声明了新的虚函数。如果采用在基类虚函数表末尾添加新项的方式，则访问虚函数总要求访问虚基类。在VC++中，为了避免获取虚函数表时，转换到虚基类P的高昂代价，T中的新虚函数通过一个新的虚函数表获取，从而带来了一个新的虚函数表指针。该指针放在T实例的顶端。<BR>&nbsp;<IMG alt="" src="http://blog.csdn.net/images/blog_csdn_net/hellothere/C++Mem14.gif"> <BR>struct T : virtual P {<BR>&nbsp;&nbsp; int t1;<BR>&nbsp;&nbsp; void pvf();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // overrides P::pvf<BR>&nbsp;&nbsp; virtual void tvf(); // new<BR>};<BR>&nbsp;<BR>void T::pvf() {<BR>&nbsp;&nbsp; ++p1; // ((P*)this)-&gt;p1++; // vbtable lookup!<BR>&nbsp;&nbsp; ++t1; // this-&gt;t1++;<BR>}<BR>&nbsp; <BR>如上所示，即使是在虚函数中，访问虚基类的成员变量也要通过获取虚基类表的偏移，实行计算来进行。这样做之所以必要，是因为虚函数可能被进一步继承的类所覆盖，而进一步继承的类的布局中，虚基类的位置变化了。下面就是这样的一个类：<BR>&nbsp; <BR>struct U : T {<BR>&nbsp;&nbsp; int u1;<BR>};<BR>&nbsp; </P>
<P>在此U增加了一个成员变量，从而改变了P的偏移。因为VC++实现中，T::pvf()接受的是嵌套在T中的P的指针，所以，需要提供一个调整块，把this指针调整到T::t1之后（该处即是P在T中的位置）。<BR></P>
<P>5.6 特殊成员函数<BR></P>
<P>本节讨论编译器合成到特殊成员函数中的隐藏代码。</P>
<P>5.6.1 构造函数和析构函数</P>
<P>正如我们所见，在构造和析构过程中，有时需要初始化一些隐藏的成员变量。最坏的情况下，一个构造函数要执行如下操作：</P>
<P>&nbsp; * 如果是“最终派生类”，初始化vbptr成员变量，调用虚基类的构造函数；<BR>&nbsp; * 调用非虚基类的构造函数<BR>&nbsp; * 调用成员变量的构造函数<BR>&nbsp; * 初始化虚函数表成员变量<BR>&nbsp; * 执行构造函数体中，程序所定义的其他初始化代码</P>
<P>（注意：一个“最终派生类”的实例，一定不是嵌套在其他派生类实例中的基类实例）</P>
<P>所以，如果你有一个包含虚函数的很深的继承层次，即使该继承层次由单继承构成，对象的构造可能也需要很多针对虚函数表的初始化。<BR>反之，析构函数必须按照与构造时严格相反的顺序来“肢解”一个对象。</P>
<P> * 合成并初始化虚函数表成员变量<BR> * 执行析构函数体中，程序定义的其他析构代码<BR> * 调用成员变量的析构函数（按照相反的顺序）<BR> * 调用直接非虚基类的析构函数（按照相反的顺序）<BR> * 如果是“最终派生类”，调用虚基类的析构函数（按照相反顺序）</P>
<P>在VC++中，有虚基类的类的构造函数接受一个隐藏的“最终派生类标志”，标示虚基类是否需要初始化。对于析构函数，VC++采用“分层析构模型”，代码中加入一个隐藏的析构函数，该函数被用于析构包含虚基类的类（对于“最终派生类”实例而言）；代码中再加入另一个析构函数，析构不包含虚基类的类。前一个析构函数调用后一个。</P>
<P>5.6.2 虚析构函数与delete操作符</P>
<P>考虑结构V和W。<BR>&nbsp; <IMG alt="" src="http://blog.csdn.net/images/blog_csdn_net/hellothere/C++Mem16.gif"><BR>struct V {<BR>&nbsp;&nbsp; virtual ~V();<BR>};<BR>&nbsp; <IMG alt="" src="http://blog.csdn.net/images/blog_csdn_net/hellothere/C++Mem17.gif"><BR>&nbsp; struct W : V {<BR>&nbsp;&nbsp; operator delete();<BR>};<BR>&nbsp; <BR>析构函数可以为虚。一个类如果有虚析构函数的话，将会象有其他虚函数一样，拥有一个虚函数表指针，虚函数表中包含一项，其内容为指向对该类适用的虚析构函数的地址。这些机制和普通虚函数相同。虚析构函数的特别之处在于：当类实例被销毁时，虚析构函数被隐含地调用。调用地（delete发生的地方）虽然不知道销毁的动态类型，然而，要保证调用对该类型合适的delete操作符。例如，当pv指向W的实例时，当W::~W被调用之后，W实例将由W类的delete操作符来销毁。<BR>&nbsp; <BR>V* pv = new V;<BR>delete pv;&nbsp;&nbsp; // pv-&gt;~V::V(); // use ::operator delete()<BR>pv = new W;<BR>delete pv;&nbsp;&nbsp; // pv-&gt;~W::W(); // use W::operator delete()<BR>pv = new W;<BR>::delete pv; // pv-&gt;~W::W(); // use ::operator delete()<BR><FONT color=#0000ff>译者注：<BR> V没有定义delete操作符，delete时使用函数库的delete操作符；<BR> W定义了delete操作符，delete时使用自己的delete操作符；<BR> 可以用全局范围标示符显示地调用函数库的delete操作符。</FONT></P>
<P>为了实现上述语意，VC++扩展了其“分层析构模型”，从而自动创建另一个隐藏的析构帮助函数——“deleting析构函数”，然后，用该函数的地址来替换虚函数表中“实际”虚析构函数的地址。析构帮助函数调用对该类合适的析构函数，然后为该类有选择性地调用合适的delete操作符。</P>
<P>6 数组</P>
<P>堆上分配空间的数组使虚析构函数进一步复杂化。问题变复杂的原因有两个：<BR>1、 堆上分配空间的数组，由于数组可大可小，所以，数组大小值应该和数组一起保存。因此，堆上分配空间的数组会分配额外的空间来存储数组元素的个数；<BR>2、 当数组被删除时，数组中每个元素都要被正确地释放，即使当数组大小不确定时也必须成功完成该操作。然而，派生类可能比基类占用更多的内存空间，从而使正确释放比较困难。<BR>&nbsp; <BR>struct WW : W { int w1; };<BR>pv = new W[m];<BR>delete [] pv; // delete m W's&nbsp; (sizeof(W)&nbsp; == sizeof(V))<BR>pv = new WW[n];<BR>delete [] pv; // delete n WW's (sizeof(WW) &gt;&nbsp; sizeof(V))<BR><FONT color=#0000ff>译者注：WW从W继承，增加了一个成员变量，因此，WW占用的内存空间比W大。然而，不管指针pv指向W的数组还是WW的数组，delete[]都必须正确地释放WW或W对象占用的内存空间。</FONT></P>
<P>虽然从严格意义上来说，数组delete的多态行为C++标准并未定义，然而，微软有一些客户要求实现该行为。因此，在MSC++中，该行为是用另一个编译器生成的虚析构帮助函数来完成。该函数被称为“向量delete析构函数”（因其针对特定的类定制，比如WW，所以，它能够遍历数组的每个元素，调用对每个元素适用的析构函数）。</P>
<P>7 异常处理</P>
<P>简单说来，异常处理是C++标准委员会工作文件提供的一种机制，通过该机制，一个函数可以通知其调用者“异常”情况的发生，调用者则能据此选择合适的代码来处理异常。该机制在传统的“函数调用返回，检查错误状态代码”方法之外，给程序提供了另一种处理错误的手段。</P>
<P>因为C++是面向对象的语言，很自然地，C++中用对象来表达异常状态。并且，使用何种异常处理也是基于“抛出的”异常对象的静态或动态类型来决定的。不光如此，既然C++总是保证超出范围的对象能够被正确地销毁，异常实现也必须保证当控制从异常抛出点转换到异常“捕获”点时（栈展开），超出范围的对象能够被自动、正确地销毁。<BR>考虑如下例子：<BR>&nbsp; <BR>struct X { X(); }; // exception object class<BR>struct Z { Z(); ~Z(); }; // class with a destructor<BR>extern void recover(const X&amp;);<BR>void f(int), g(int);</P>
<P>int main() {<BR>&nbsp;&nbsp; try {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; f(0);<BR>&nbsp;&nbsp; } catch (const X&amp; rx) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; recover(rx);<BR>&nbsp;&nbsp; }<BR>&nbsp;&nbsp; return 0;<BR>}</P>
<P>void f(int i) {<BR>&nbsp;&nbsp; Z z1;<BR>&nbsp;&nbsp; g(i);<BR>&nbsp;&nbsp; Z z2;<BR>&nbsp;&nbsp; g(i-1);<BR>}</P>
<P>void g(int j) {<BR>&nbsp;&nbsp; if (j &lt; 0)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw X();<BR>}<BR><FONT color=#0000ff>译者注：X是异常类，Z是带析构函数的工作类，recover是错误处理函数，f和g一起产生异常条件，g实际抛出异常。</FONT></P>
<P>这段程序会抛出异常。在main中，加入了处理异常的try &amp; catch框架，当调用f(0)时，f构造z1，调用g(0)后，再构造z2，再调用g(-1)，此时g发现参数为负，抛出X异常对象。我们希望在某个调用层次上，该异常能够得到处理。既然g和f都没有建立处理异常的框架，我们就只能希望main函数建立的异常处理框架能够处理X异常对象。实际上，确实如此。当控制被转移到main中异常捕获点时，从g中的异常抛出点到main中的异常捕获点之间，该范围内的对象都必须被销毁。在本例中，z2和z1应该被销毁。</P>
<P>谈到异常处理的具体实现方式，一般情况下，在抛出点和捕获点都使用“表”来表述能够捕获异常对象的类型；并且，实现要保证能够在特定的捕获点真正捕获特定的异常对象；一般地，还要运用抛出的对象来初始化捕获语句的“实参”。通过合理地选择编码方案，可以保证这些表格不会占用过多的内存空间。</P>
<P>异常处理的开销到底如何？让我们再考虑一下函数f。看起来f没有做异常处理。f确实没有包含try，catch，或者是throw关键字，因此，我们会猜异常处理应该对f没有什么影响。错！编译器必须保证一旦z1被构造，而后续调用的任何函数向f抛回了异常，异常又出了f的范围时，z1对象能被正确地销毁。同样，一旦z2被构造，编译器也必须保证后续抛出异常时，能够正确地销毁z2和z1。</P>
<P>要实现这些“展开”语意，编译器必须在后台提供一种机制，该机制在调用者函数中，针对调用的函数抛出的异常动态决定异常环境（处理点）。这可能包括在每个函数的准备工作和善后工作中增加额外的代码，在最糟糕的情况下，要针对每一套对象初始化的情况更新状态变量。例如，上述例子中，z1应被销毁的异常环境当然与z2和z1都应该被销毁的异常环境不同，因此，不管是在构造z1后，还是继而在构造z2后，VC++都要分别在状态变量中更新（存储）新的值。</P>
<P>所有这些表，函数调用的准备和善后工作，状态变量的更新，都会使异常处理功能造成可观的内存空间和运行速度开销。正如我们所见，即使在没有使用异常处理的函数中，该开销也会发生。</P>
<P>幸运的是，一些编译器可以提供编译选项，关闭异常处理机制。那些不需要异常处理机制的代码，就可以避免这些额外的开销了。</P>
<P>8 小结</P>
<P>好了，现在你可以写C++编译器了（开个玩笑）。<BR>在本文中，我们讨论了许多重要的C++运行实现问题。我们发现，很多美妙的C++语言特性的开销很低，同时，其他一些美妙的特性（译者注：主要是和“虚”字相关的东西）将造成较大的开销。C++很多实现机制都是在后台默默地为你工作。一般说来，单独看一段代码时，很难衡量这段代码造成的运行时开销，必须把这段代码放到一个更大的环境中来考察，运行时开销问题才能得到比较明确的答案。<BR></P><img src ="http://www.cppblog.com/apollo/aggbug/3570.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-02-28 13:06 <a href="http://www.cppblog.com/apollo/articles/3570.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ 的MetaProgramming </title><link>http://www.cppblog.com/apollo/articles/MetaProgramming.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Mon, 27 Feb 2006 15:37:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/MetaProgramming.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/3559.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/MetaProgramming.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/3559.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/3559.html</trackback:ping><description><![CDATA[<p>C++ 的另一个新世界</p>
<p>C++ 的 MetaProgramming </p>
<p>废话就不说了, 按照C的传统惯例,介绍programming的最好方式就是show代码, 第一个例子就是Hello,world, 这篇文章也不例外</p>
<p>在任何一个cpp文件中,输入</p>
<p>struct hello_world; //forward declaration<br>struct A : hello_world<br>{<br>};</p>
<p>然后编译..,注意我没有说"编译运行",而仅仅说的是"编译", 如果不意外的话,在你编译器的输出窗口会出现<br>base class hello_world undefined<br>或者<br>base class `hello_world' has incomplete type</p>
<p>等类似的语句, 至少在你的屏幕上打印出了 "hello_world" 字样,对吧? 对了,这就是这个例子的目的, 我不也打印出来的吗?</p>
<p>上面这个简陋的例子阐述了一个重要的现象, "编译时"而不是运行时, 这就是meta programming的世界, 一个处于编译期间, 而不是运行期间的世界.</p>
<p>运行时我们能作的事情很多在编译时我们不能作, 例如我们不能调用函数, 我们不能创建对象, 我们也不能设置断点, 一切都交给你的C++编译器.</p>
<p><br>接下来, 首先回顾一下一些C++的基本模板知识. <br>由于C++的编译器符合ISO 标准的程度不一, 我使用的是VC++ 6 和 gcc version 3.2.3 (mingw special 20030504-1)<br>下面的例子我在这两个编译器中都测试过. </p>
<p>C++模板的最经常的认识就是STL中的容器, 例如<br>vector&lt;int&gt; 就是一个可以装int的动态数组, vector&lt;sharp*&gt; 就是一个可以装sharp对象指针的数组.</p>
<p>然后我们还需要一点点模板特化的知识.<br>例如 </p>
<p>template&lt;class T&gt; struct Foo {}; </p>
<p>这是一个通用模板, 必配任何类型, 如果我们需要对int进行特别处理, 那么</p>
<p>template&lt;&gt; struct Foo&lt;int&gt;&nbsp; {};&nbsp; </p>
<p>这样就实现了对 int 类型的完全特化 . VC6 只支持完全特化, 不支持偏特化, 或者部分特化.<br>不过还是稍微介绍一下:<br>什么是遍特化了? 还就上面这个例子而言, 如果我们想对所有的指针进行特化, 那么应该是<br>template&lt;class T&gt; struct Foo&lt;T*&gt; {} </p>
<p>那么什么又是部分特化了, 看看这个:<br>template&lt;class T, class U&gt; struct bar {};</p>
<p>template&lt;class T&gt; struct bar&lt;T, int&gt;&nbsp; {};</p>
<p>后面这个就是对U模板参数的部分特化,使得 U为 int的时候 使用这个版本. </p>
<p>这篇文章由于针对VC6, 因此你不会遇到偏特化和部分特化的情况. </p>
<p><br>hello,world的例子以后, 我们准备干点有意思的事情. 例如求两数之和. 首先看看在运行时的函数我们应该如何实现:</p>
<p>定义:<br>int sum(int x, int y) { return x+y; } </p>
<p>调用:<br>int j =&nbsp; sum(3, 4) </p>
<p><br>那么如何用meta programming的方式实现了? </p>
<p>meta programming 由于处于编译器, 因此给它的参数必须是编译时就可以确定的, 在当前C++中允许的为,integer 和 type.</p>
<p>就上面这个例子, 对于模板的调用应该是:<br>int j = sum_&lt;3,4&gt;::value;</p>
<p>3,4 都为整形常量, 编译时确定, 然后返回值如何取得? 记住在编译时是无法进行真正的函数调用的,因此我们只有通过定义在模板类中的一个常量<br>来获得返回结果. 最简单的方法就是在一个 struct定义一个匿名的enum .</p>
<p>sum的定义如下:<br>template&lt;int x, int y&gt;<br>struct sum_<br>{<br>&nbsp; enum { value = x + y };<br>};</p>
<p>然后你可以编译后"运行"检查检查看看运行结果</p>
<p>#include &lt;iostream&gt;</p>
<p>using namespace std;</p>
<p>template&lt;int x, int y&gt;<br>struct sum_</p>
<p>{<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; enum { value = x + y };</p>
<p>};</p>
<p>int main()</p>
<p>{<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp; cout &lt;&lt; sum_&lt;3, 4&gt;::value &lt;&lt; endl;<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp; return 0;</p>
<p>}</p>
<p><br>上面之所以使用struct sum_而不是class sum_是因为struct的默认作用范围上public, 可以省略几个键击.</p>
<p>这个例子通用展示了一个重要的观点, 对应通常可以在运行时调用的函数<br>int foo(int a, int b) <br>其对应的meta 实现为:<br>foo&lt;a, b&gt;::value <br>也就是我们的foo现在为一个struct name, 参数通过&lt; &gt; 中的模板投递, 结果通过 ::value 获得其中定义的一个匿名enum值.</p>
<p>那么如何计算 3,4,5的和? <br>你可能会想如下:<br>&nbsp;sum_&lt;3,4,5&gt;::value</p>
<p>但是c++不支持一个模板类使用不同的参数参数存在, 换一个方式, <br>你如何在 int sum(int a, int b) 存在的情况下获得3个数的和?<br>我们可以这样：<br>sum( 3, sum(4, 5)) <br>有lisp 背景的可能发现这很符合他们的思考方式, 至少以我浮浅的emacs lisp知识, 不使用中间变量. 同样,meta中你也可以这样使用:</p>
<p>sum_&lt;&nbsp;&nbsp; //开始参数<br>sum_&lt; 3 //第一个参数为3<br>sum_&lt; 3, sum_&lt;&nbsp;&nbsp; //第二个参数是另外一个表达式的结果<br>sum_&lt; 3, sum_&lt;4, //这个表达式的第一个参数为４<br>sum_&lt; 3, sum_&lt;4, 5&gt; //这个表达式的第二个参数为５<br>sum_&lt; 3, sum_&lt;4, 5&gt;::value //通过::value获得这个表达式的结果<br>sum_&lt; 3, sum_&lt;4, 5&gt;::value &gt;::value //然后获得整个表达式的结果</p>
<p>ok, 就这么多, 看出来没有, 再解释一次, 将上面我们的<br>&nbsp; cout &lt;&lt; sum_&lt;3, 4&gt;::value &lt;&lt; endl;<br>&nbsp;&nbsp;&nbsp; </p>
<p>中４的位置用一个sum_ 替换就得到了我们需要的三个数之和.</p>
<p><br>&nbsp; cout &lt;&lt; sum_&lt;3, ?? &gt;::value &lt;&lt; endl;<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;===&gt; <br>&nbsp;&nbsp; ?? =&nbsp; sum_&lt;4, 5&gt;::value</p>
<p>&nbsp;===&gt; then<br>&nbsp; cout &lt;&lt; sum_&lt;3, sum_&lt;4, 5&gt;::value &gt;::value &lt;&lt; endl;<br>&nbsp;&nbsp;&nbsp; </p>
<p><br>如果我需要算 2, 3, 4, 5之和呢? <br>同样简单, 你将上面的3, 4 ,5 中的任何一个常量替换成对sum_ 进行一个调用就可以了.<br>例如:</p>
<p>out &lt;&lt; sum_&lt; ?? , sum_&lt;4, 5&gt;::value &gt;::value &lt;&lt; endl;<br>&nbsp;&nbsp;&nbsp; </p>
<p>?? =&nbsp; sum_&lt; 2, 3 &gt;::value</p>
<p>合并后为</p>
<p>cout &lt;&lt; sum_&lt; sum_&lt;2, 3&gt;::value , sum_&lt;4, 5&gt;::value &gt;::value &lt;&lt; endl;<br>运行的结果为 14. </p>
<p><br>这就是meta中最简单的一个例子, 顺序调用, 如果你看明白了同时觉得有点意思的话, 下来我们讲讲<br>循环语句, 通常我们写程序都避免递归, 因为容易造成堆栈和大脑溢出,但是在 meta 中必须使用递归的方式. <br></p>
<p>下面看看一个计算"阶乘"的例子, 其实这个才真正是meta 中的hello,world.</p>
<p>先看后面, 我们调用的方式:</p>
<p>cout &lt;&lt; fac&lt;5&gt;::value ;&nbsp; // 结果应该是 5 * 4 * 3 * 2 * 1 = 120;</p>
<p>通过前面的知识, 你知道fac是一个template struct的名字, 有一个模板参数int, value是其中的一个匿名枚举变量<br>于是你可以毫不犹豫的写下:</p>
<p>template&lt;int i&gt;<br>struct fac<br>{<br>&nbsp; enum { value = ??? };<br>};</p>
<p>但是在value的地方你卡住了, 如果根据 i 得到 value? </p>
<p>让我们将大脑从"编译时世界"切换到"运行时的世界", 你如何写一个通常的递归函数来计算阶乘?</p>
<p>int fac(int n)<br>{<br>&nbsp; if( n == 1)<br>&nbsp;&nbsp;&nbsp; return 1;<br>&nbsp; return n * fac(n-1);<br>}</p>
<p>注意 n == 1是一个递归退出条件,先不考虑n为1时的递归退出, <br>其他情况下是将n 乘以 fac (n - 1). 有了前面的sum_ 知识, 你应该可以推出 value = ???<br>中的??? 应该是<br>n *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //n* <br>fac&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //调用下一个fac<br>fac&lt;n-1&gt;&nbsp; //参数为n-1<br>fac&lt;n-1&gt;::value //获得结果</p>
<p>因此fac "函数"的模板实现就是</p>
<p>template&lt;int i&gt;<br>struct fac<br>{<br>&nbsp; enum { value = i * fac&lt;i - 1&gt;::value };<br>};</p>
<p>然后我们再考虑递归退出条件, 为1时value应该为1, 拿起C++中的特化模板武器来<br>template&lt;&gt; <br>struct fac&lt;1&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //参数为1时的特化<br>{<br>&nbsp; enum { value = 1 };<br>};</p>
<p>这样就将参数为 1 时的返回值设置为1, 结束递归.</p>
<p>这样,当你输入<br>cout &lt;&lt; fac&lt;5&gt;::value &lt;&lt; endl;<br>时,编译器会实例化<br>template&lt;&gt; <br>struct fac&lt;5&gt;<br>{<br>&nbsp; enum { value = 5 * fac&lt;4&gt;::value };<br>};</p>
<p>由于fac&lt;5&gt; 需要 fac&lt;4&gt; , 因此然后实例化 fac&lt;4&gt;, 同样的原因, fac&lt;3&gt; , fac&lt;2&gt;, fac&lt;1&gt;</p>
<p>到fac&lt;1&gt; , 编译器发现了一个特化版本fac&lt;1&gt; 匹配, 在fac&lt;1&gt;中的value已经是一个常量, 不依赖其他的fac实例, 递归退出, 最后<br>我们得到最终结果120 .</p>
<p><br>easy, 对不? </p>
<p>然后再介绍 if语句. <br>还是上面的这个fac例子, 负数的阶乘是没有意义的,先不考虑数学问题,假设我们希望在这个情况下返回-1,如何实现? </p>
<p>如果我们输入fac&lt;-2&gt;::value , 那么编译器会尝试实例化fac&lt;-3&gt;, fac&lt;-4&gt;, ......<br>你发现这是一个无限递归条件, 在运行时会造成你堆栈溢出, 由于我们在"编译时世界", 取决于你编译器, 最终总有结束的时候.</p>
<p>例如VC6 报错: fatal error C1202: recursive type or function dependency context too complex<br>G++报错&nbsp;&nbsp;&nbsp;&nbsp; : template instantiation depth exceeds maximum of 500</p>
<p>因此我们需要一个if判断语句, 发现当模板参数 &lt; 1的时候返回 -1. </p>
<p>按照测试先行的原则, 我们可以预计<br>fac&lt;-1&gt;::value == -1&nbsp; 是成立的.<br>现在的问题是如何实现? 下次再说吧! 也给个机会折磨折磨你的大脑. 记住, 模板不仅仅可以通过enum返回整数, 还可以通过嵌套 typedef返回一个类型.<br>
</p>
<p>上回说到一个fac的版本, 希望在负数的情况下返回-1, 而不是无限递归下去. <br>还是按照我们的思维, 先写个对应"运行时世界"的版本.</p>
<p>int safe_fac(int n)<br>{<br>&nbsp; if( n &lt; 1)<br>&nbsp;&nbsp;&nbsp;&nbsp; return -1;<br>&nbsp; return fac(n);<br>}</p>
<p>这个if逻辑很简单, 如果模板参数&lt;1, 那么直接返回 -1, 否则 还是使用前面的fac那个版本. <br>好, 转换成我们的meta 版本.</p>
<p>你想,用个 ?: 运算符不就解决了吗? </p>
<p>template&lt;int n&gt;<br>struct safe_fac<br>{<br>&nbsp; enum { value =&nbsp; (n &lt; 1 ? -1 : fac&lt;n&gt;::value ) };<br>};</p>
<p>可惜不对,&nbsp; ?= 只有在"运行时世界"才能使用. 那么 value 后面的???写什么好呢? </p>
<p>先轻松轻松, 写一个if的meta 版本, 我敢保证你能看得懂.<br>template&lt; bool b , class T, class U&gt;<br>struct if_<br>{<br>&nbsp; typedef T type;<br>};</p>
<p>注意了, 如果以前我们提到的例如sum_, fac等meta functions(其实就是c++中的模板类, 称之为meta function是因为它们就像是function)<br>是通过一个 在enum中的value 返回整形的话, 上面刚刚的if_这个例子就展示了 meta中的另外一个武器, 通过typedef 一个type 返回一个类型.</p>
<p>如果我们这样调用<br>if_&lt;true, int, double&gt;::type&nbsp; 的结果就是 int 类型, 注意是"类型", 不是对象. </p>
<p>我们想在b为false的时候返回第二个类型U, 即:<br>if_&lt;false, int, double&gt;::type 的返回结果是double</p>
<p>那么还是很简单, 部分特化 b 参数就可以了.即:<br>template&lt;class T, class U&gt;<br>struct if_&lt;false, T, U&gt;<br>{<br>&nbsp; typedef U type;<br>};</p>
<p>我最前面说了, VC6不支持部分特化, 但是别忘了计算机时间的一条公理:<br>任何计算机问题都可以通过增加一层来解决. 大部分VC6中的模板的问题还是可以解决的. 如果你不使用VC6, 这部分就不用看了.</p>
<p>VC6是支持全部特化的, 因此我们可以将true, false特化出来</p>
<p>template&lt;bool&gt;<br>struct if_help<br>{<br>&nbsp;&nbsp; ...<br>};</p>
<p>template&lt;&gt;<br>struct if_help&lt;false&gt;<br>{<br>&nbsp;&nbsp; ...<br>};</p>
<p>这个在vc6中是支持的. 然后我们还需要两个额外的类型参数T,U, 这可以通过嵌套类来实现. 即</p>
<p>template&lt;bool&gt;<br>struct if_help<br>{<br>&nbsp; template&lt;class T, class U&gt;<br>&nbsp; struct In<br>&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp; typedef T type;<br>&nbsp; };<br>};</p>
<p>template&lt;&gt;<br>struct if_help&lt;false&gt;<br>{<br>&nbsp; template&lt;class T, class U&gt;<br>&nbsp; struct In<br>&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp; typedef U type;<br>&nbsp; };<br>};</p>
<p>然后我们真正的if_ "meta 函数"如下定义:</p>
<p>template&lt;bool b, class T, class U&gt;<br>struct if_<br>{<br>&nbsp;&nbsp; typedef if_help&lt;b&gt;::In&lt;T, U&gt;::type type;<br>};</p>
<p>先根据b的内容实例化一个对应的if_help, : if_help&lt;b&gt;<br>然后给其中的In模板投递T,U参数, ::In&lt;T, U&gt;<br>然后通过type获得其中的返回类型 ::type<br>最后typedef type一下作为自己的返回类型, 这样外部就可以通过<br>if_&lt;true, int, double&gt;::type&nbsp; 获得返回的类型了.</p>
<p>上面if_ 的实现实际上要用几个C++关键字修饰一下:<br>typedef if_help&lt;b&gt;::In&lt;T, U&gt;::type type;<br>&nbsp;===&gt; <br>typedef typename if_help&lt;b&gt;::template In&lt;T, U&gt;::type type;</p>
<p>为什么要加上typename 和 template, 这个解释起来到是很费劲. 有空再说. </p>
<p>好了, 从模板的语法世界中清醒过来, 现在你知道的是, 我们有了一个if_ 的meta函数, 接受3个参数bool b, class T, class U,<br>如果b为true, 那么它的返回值 (通过 if_::type 返回) 就是T, <br>如果b为false, 那么它的返回值 (通过 if_::type 返回) 就是U. </p>
<p>前面我提过了, 参数是通过&lt;&gt;来传递的, 因此一个例子就是</p>
<p>if_&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
//函数名<br>if_&lt;true,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
//第一个参数, bool 型<br>if_&lt;true, int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //第二个参数, 类型<br>if_&lt;true, int, double&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //第3个参数,&nbsp; 类型<br>if_&lt;true, int, doubble&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //右括号表示参数结束<br>if_&lt;true, int, double&gt;::type //通过::type获得返回结果, 不是value了, 当然这仅仅是一个命名惯例.</p>
<p>因此上面的那个 if_&lt;true, int, double&gt;::type 返回的就是 int, <br>在"运行时世界", 你可以如下使用:</p>
<p>for( if_&lt;true, int, double&gt;::type i = 0; i &lt; 10; i++) {<br>&nbsp; cout &lt;&lt; "line " &lt;&lt; i &lt;&lt; "\n"; <br>}</p>
<p>等同于<br>for( int i = 0; i &lt; 10; i++) {<br>&nbsp; cout &lt;&lt; "line " &lt;&lt; i &lt;&lt; "\n"; <br>}</p>
<p>当然对于这个例子这样使用是"有病". 我们等会会用到if_来实现前面的&nbsp; safe_fac 实现了.</p>
<p>注意我说的返回值并不是前面sum_例子中的整形了, 这个时候返回一个类型. 类型不是实例对象, 这点我想你应该清楚. <br>编译时不可能返回对象, 因为要调用构造函数, 要确定对象地址, 我们还没有进入到" 运行时世界" , 对吧?<br>实际上meta programming 最重要的使用并不是前面我们提到过的sum_, fac这些, 因为毕竟拿个计算器算一下也花不了几个时间.<br>但是返回type就不同了. <br>那么type可以是什么呢? 可以是int, double这样的基本类型, 也可以我们前面的 sum_ 模板类等等.</p>
<p>然后再看safe_fac的实现:<br>先不考虑 &lt;1 的情况, 那么value就应该是直接调用以前的 fac 函数</p>
<p>template&lt;int n&gt;<br>struct safe_fac<br>{<br>&nbsp; enum { value = fac&lt;n&gt;::value };<br>};</p>
<p>然后再使得 &gt;= 1时才使用fac函数, 那么利用我们前面的if_, 先忽略语法错误, 那么可以如下</p>
<p>enum <br>{ <br>value = if_&lt; n &lt; 1,???,&nbsp; fac&lt;n&gt; &gt;::type::value<br>};</p>
<p>首先, n &lt; 1 为真时返回一个类型???, 暂时我们还没有实现, 为false时返回<br>fac&lt;n&gt;类型, 然后通过::type获得返回的类型,或者为???, 或者为fac&lt;n&gt;, <br>然后通过::value得到这个类型的整数结果.</p>
<p>那么 ??? 应该是什么呢? 当然不能直接是-1, 否则 -1::value 就是语法错误. </p>
<p>因此我们可以定义一个简单的"函数", 返回-1:</p>
<p>struct return_neg1<br>{<br>&nbsp;&nbsp; enum { value = -1 };<br>};</p>
<p>如果我们需要返回-2怎么办? 又定义一个return_neg2 "函数"? 干脆我们一劳永逸, 定义如下:</p>
<p>template&lt;int n&gt;<br>struct int_<br>{<br>&nbsp;&nbsp; enum { value = n };<br>};</p>
<p>这样int_ 这个"函数"就是你给我什么, 我就返回什么. 不过int_是一个类型, 例如:<br>通过如下调用 int_&lt;3&gt;::value&nbsp; 返回它的结果3. </p>
<p>有了这个, 我们的代码就如下:</p>
<p>value = if_&lt; n &lt; 1, int_&lt;-1&gt;,&nbsp; fac&lt;n&gt; &gt;::type::value</p>
<p>原理清楚了, 最终的版本就是:</p>
<p>template&lt;int n&gt;<br>struct safe_fac<br>{<br>&nbsp; enum { value = if_&lt; n &lt; 1, int_&lt;-1&gt;,&nbsp; fac&lt;n&gt; &gt;::type::value };<br>};</p>
<p>试试:<br>cout &lt;&lt; safe_fac&lt;-1&gt;::value 输出 -1.</p>
<p>循环(递归表示), 条件判断, 顺序执行都有了, 剩下的就看你自己了. </p>
<p>--------------------------------------------------------------------------------<br>Boost中的mpl (meta programming library) 提供了一个专门用于metaprogramming的library, 同时前面提到的if_, int_等等就<br>是从mpl中拷贝来的, 当然我简化了很多. </p>
<p>Modern C++ Design 其中的Typelist将meta progamming的循环(就是递归)发挥得淋漓尽致, 在侯捷的网站上<a href="http://www.jjhou.com/">www.jjhou.com</a>有免费的前4章可读. Typelist在第三章. <br>书中序言部分, Effective C++的作者Meyers说到, 如果第3章的typelists没有让你感到振奋, 那你一定是很沉闷. <br>就我亲身体验, 我觉得Meyers可能是说到委婉了些:<br>如果第3章的typelists没有让你感到振奋, 那1%的可能是你是很沉闷, 99%的可能是你没有看懂. I did.<br>GoF之一的 John Vlissides同样提到了typelists这一章就值得本书的价格. I believe.</p>
<p>另外, 我发现即使在这本让人抓狂的天才之作中, 作者仍然使用了n个TYPELIST_n 这样的预处理宏来处理多个type的情况, 但是在sourceforge<br>下的Loki库中我发现已经有了一个MakeTypelist"函数", 看来 meta programming 确实是, 啊...<br>是不是作者当时都没有预见到还能够以C++编译器内建的模板能力, 而不是依赖预处理宏来处理typelist.?</p>
<p>又, mpl中有专门装type的容器....</p>
<img src ="http://www.cppblog.com/apollo/aggbug/3559.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-02-27 23:37 <a href="http://www.cppblog.com/apollo/articles/MetaProgramming.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ Templates几个要点</title><link>http://www.cppblog.com/apollo/articles/CpptmplNotes.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Mon, 27 Feb 2006 15:19:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/CpptmplNotes.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/3558.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/CpptmplNotes.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/3558.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/3558.html</trackback:ping><description><![CDATA[<br>
模板派生类(下面的D) 从一个 确定性基类(指B)继承, <br>
在D的定义中, 编译器优先查找基类中的名字, 然后才是模板参数placeholder (即Type) .<br>
<br>
<br>
例如:<br>
struct B<br>
{<br>
&nbsp;&nbsp; typedef int Type;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //基类中有一个Type名字<br>
};<br>
<br>
template&lt;class Type&gt;<br>
class D : public B&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //从非依赖基类B派生, <br>
{<br>
public:<br>
&nbsp; Type i;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Type既可以是模板参数, 有可能是基类B中被typedef的int, 优先选择后者<br>
};<br>
<br>
int&nbsp; main()<br>
{<br>
&nbsp;&nbsp; D&lt;char&gt; d;<br>
&nbsp;&nbsp; d.i = 29;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //d.i 的确切类型应该是 B中定义的 int, 而不是模板实参指定的char. <br>
<br>
&nbsp;&nbsp; return 0;<br>
}<br>
<br>
VC7.1 确实如此.<br>
<br>
这样, 是否造成一种现象，就是如果一个模板类需要继承一个普通的基类，它在确定模板参数名字的时候还要考虑<br>
到基类中去看看有没有同名冲突？　<br>
<br>
或者使用一种防御性的模板参数命名方法，即仅仅将模板参数命名为T, U这样的简单类型？<br>
<br>
<p>C++ Templates &lt;The complete guide&gt; 中的一个例子:</p>
<p>一个模板基类<br>template&lt;class T&gt;<br>class Base<br>{<br>public:<br>&nbsp;&nbsp; int field;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // #1<br>};</p>
<p>派生类, 从上面的模板基类继承<br>注意, 在此, 基类并不能确定就是上面的Base&lt;T&gt;, <br>因为 下面#3 处可以看到, 程序对Base&lt;int&gt;进行了特化</p>
<p>template&lt;class T&gt;<br>class Derived : public Base&lt;T&gt;<br>{<br>public:<br>&nbsp;void f()<br>&nbsp;{<br>&nbsp;&nbsp;field++;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //#2 哪个field? #1处还是#3处,<br>&nbsp;}<br>};</p>
<p><br>#2处的field到底是char还是int类型? 即#1处还是#3处 ? 显然无法确定, 只有当<br>Derived被某个特定的T类型实例化的时候才知道.</p>
<p><br>template&lt;&gt;<br>class Base&lt;int&gt;<br>{<br>public:<br>&nbsp;char field;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //#3<br>};</p>
<p><br>#2处的field是一个unqualified name, 而基类Base&lt;T&gt;是一个dependent name, 因此不去其中查找. </p>
<p>正确的编译器做法是: 在#1处报错.&nbsp; VC7.1就是如此. </p>
因此在Derived&lt;T&gt;模板类中, 如果确实需要指定Base&lt;T&gt;中的field, 应该使用 this-&gt;field 或者 Base&lt;T&gt;::field.&nbsp; <br>
<br>
<img src ="http://www.cppblog.com/apollo/aggbug/3558.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-02-27 23:19 <a href="http://www.cppblog.com/apollo/articles/CpptmplNotes.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ Templates (给模板参数命名)</title><link>http://www.cppblog.com/apollo/articles/templateArg.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Mon, 27 Feb 2006 15:14:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/templateArg.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/3557.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/templateArg.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/3557.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/3557.html</trackback:ping><description><![CDATA[<p><font color="#0000ff">看C++ Templates </font><font color="#0000ff"><font color="#000000">16.1 Named Template Arguments</font></font></p>
<p>书中的例子实现手法使用多重/虚拟继承, 实现手法感觉比较诡秘. 但是至少告诉我是可以实现的.<br> </p>
<p>于是干脆自己也练了练手,&nbsp; 博君一笑. 只在VC7.1下测试过, VC6也许可能可以迂回实现, 但是估计工作量太大. </p>
<p>1. 首先需要一个基本的 If 语句. <br> </p>
template &lt;bool, class T, class U&gt;<br>
struct if_<br>
{<br>
&nbsp;&nbsp;&nbsp; typedef T type;<br>
};<br>
<br>
template&lt;class T, class U&gt;<br>
struct if_&lt;false,&nbsp; T,&nbsp; U&gt;<br>
{<br>
&nbsp;&nbsp;&nbsp; typedef U type;<br>
};<br>
<br>
<p>2. 然后使用一个 type_selector meta-function,
N表示第几个默认参数(注意我的默认Policy参数DefaultPolicyArgs里面有一个meta data, 为0.
如果是用户定义的Policy, 那么形如Policy2_is的模板类里面有一个meta data为2. 这个数字主要是用于定位. </p>
<p>最后的DefaultType是当扫描一遍, 发现没有任何对应N位置的自定义Policy参数, 那么就取这个为默认值, 结束递归.(下面的4个void的特化版本就是干这个的) </p>
template&lt; <br>
&nbsp;&nbsp; &nbsp;int N,<br>
&nbsp;&nbsp;&nbsp; class T1,<br>
&nbsp;&nbsp;&nbsp; class T2,<br>
&nbsp;&nbsp;&nbsp; class T3,<br>
&nbsp;&nbsp;&nbsp; class T4,<br>
&nbsp;&nbsp;&nbsp; class DefaultType&gt;<br>
struct type_selector<br>
{<br>
&nbsp;&nbsp;&nbsp; typedef typename if_ &lt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (T1::value == N), <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; T1, <br>
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;type_selector&lt;N, T2, T3, T4, void, DefaultType&gt; &gt;::type eval_type;<br>
<br>
&nbsp;&nbsp;&nbsp; typedef typename eval_type::type type;<br>
};<br>
<br>
//shift以后, 如果都是默认值, 递归会来到这里, 结束.<br>
template&lt;<br>
&nbsp;&nbsp;&nbsp; int N,<br>
&nbsp;&nbsp;&nbsp; class DefaultType&gt;<br>
struct type_selector&lt;N, void, void, void, void, DefaultType&gt;<br>
{<br>
&nbsp;&nbsp;&nbsp; typedef DefaultType type;<br>
};<br>
<br>
struct DefaultPolicy1 {};<br>
struct DefaultPolicy2 {};<br>
struct DefaultPolicy3 {<br>
&nbsp; public:<br>
&nbsp;&nbsp;&nbsp; static void doPrint() {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "DefaultPolicy3::doPrint()\n";<br>
&nbsp;&nbsp;&nbsp; }<br>
};<br>
class DefaultPolicy4 {};<br>
<br>
struct&nbsp; DefaultPolicyArgs {<br>
&nbsp;&nbsp;&nbsp; static const int value = 0;<br>
};<br>
<br>
<br>
template &lt;typename Policy&gt;<br>
struct Policy1_is<br>
{<br>
&nbsp;&nbsp;&nbsp; typedef Policy type;<br>
&nbsp;&nbsp;&nbsp; static const int value = 1;<br>
};<br>
<br>
template &lt;typename Policy&gt;<br>
struct Policy2_is<br>
{<br>
&nbsp;&nbsp;&nbsp; typedef Policy type;<br>
&nbsp;&nbsp;&nbsp; static const int value = 2;<br>
};<br>
<br>
<br>
template &lt;typename Policy&gt;<br>
struct Policy3_is<br>
{<br>
&nbsp;&nbsp;&nbsp; typedef Policy type;<br>
&nbsp;&nbsp;&nbsp; static const int value = 3;<br>
};<br>
<br>
<br>
template &lt;typename Policy&gt;<br>
struct Policy4_is<br>
{<br>
&nbsp;&nbsp;&nbsp; typedef Policy type;<br>
&nbsp;&nbsp;&nbsp; static const int value = 4;<br>
};<br>
<br>
<br>
template&lt;class T1, class T2, class T3, class T4&gt;<br>
struct PolicySelector<br>
{<br>
&nbsp;&nbsp;&nbsp; typedef typename type_selector&lt;1, T1, T2, T3, T4, DefaultPolicy1&gt;::type P1;<br>
&nbsp;&nbsp;&nbsp; typedef typename type_selector&lt;2, T1, T2, T3, T4, DefaultPolicy2&gt;::type P2;<br>
&nbsp;&nbsp;&nbsp; typedef typename type_selector&lt;3, T1, T2, T3, T4, DefaultPolicy3&gt;::type P3;<br>
&nbsp;&nbsp;&nbsp; typedef typename type_selector&lt;4, T1, T2, T3, T4, DefaultPolicy4&gt;::type P4;<br>
};<br>
&nbsp;&nbsp; &nbsp;<br>
<br>
template &lt;typename T1 = DefaultPolicyArgs,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typename T2 = DefaultPolicyArgs,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typename T3 = DefaultPolicyArgs,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typename T4 = DefaultPolicyArgs&gt;<br>
class BreadSlicer {<br>
&nbsp;&nbsp;&nbsp; typedef typename PolicySelector&lt;T1, T2, T3, T4&gt; Policies;<br>
&nbsp;&nbsp; &nbsp;<br>
&nbsp; public:<br>
&nbsp;&nbsp;&nbsp; void print () {<br>
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;std::cout &lt;&lt; typeid(Policies::P3).name() &lt;&lt; std::endl;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Policies::P3::doPrint();<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; void&nbsp; print_2()<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; typeid(Policies::P2).name() &lt;&lt; std::endl;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Policies::P2::print_2();<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; //...<br>
};<br>
<br>
<br>

//下面的就是测试代码了.<br>
<br>
class CustomPolicy {<br>
&nbsp; public:&nbsp;&nbsp; &nbsp;<br>
&nbsp;&nbsp;&nbsp; static void doPrint() {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "CustomPolicy::doPrint()\n";<br>
&nbsp;&nbsp;&nbsp; }<br>
};<br>
<br>
class CustomPolicy2 {<br>
public:<br>
&nbsp;&nbsp;&nbsp; static void print_2()<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "Here is CustomPolicy2 instance" &lt;&lt; std::endl;<br>
&nbsp;&nbsp;&nbsp; }<br>
};<br>
&nbsp;&nbsp; &nbsp;<br>
int main()<br>
{<br>
&nbsp;&nbsp;&nbsp; BreadSlicer&lt;&gt; bc1;<br>
&nbsp;&nbsp;&nbsp; bc1.print();<br>
<br>
&nbsp;&nbsp;&nbsp; BreadSlicer&lt; Policy3_is&lt;CustomPolicy&gt;,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Policy2_is&lt;CustomPolicy2&gt; &gt; bc2;<br>
&nbsp;&nbsp; &nbsp;<br>
&nbsp;&nbsp;&nbsp; bc2.print();<br>
&nbsp;&nbsp;&nbsp; return 0;<br>
}<br>
<br>

		上面那个帖子的实现手法不太好, 当client使用的时候, 还是需要<br>
<br>
&nbsp;BreadSlicer&lt; Policy3_is&lt;CustomPolicy&gt;, Policy2_is&lt;CustomPolicy2&gt; &gt; bc;<br>
<br>
复杂的嵌套模板语法, 如果能够去掉PolicyN_is, 例如可以这样<br>
<br>
&nbsp;BreadSlicer&lt;&gt; bc2;&nbsp; //全部默认policies<br>
<br>
如果定制其中的policy2, 这样<br>
&nbsp;BreadSlicer&lt; CustomPolicy2 &gt; bc;<br>
<br>
如果需要定制2, 3, 这样<br>
<br>
&nbsp;BreadSlicer&lt; CustomPolicy2, CustomPolicy3 &gt; bc;<br>
<br>
与顺序无关, 先写3, 再写2也可以<br>
&nbsp;BreadSlicer&lt; CustomPolicy3, CustomPolicy2 &gt; bc;<br>
<br>
那就更加简单了. <br>
<br>
幸运的是, 这也是可以实现的, 而且与前面的帖子相比, 这个新的实现还直白简单, 使用起来由于直接使用Policy class作为参数, <br>
而无需通过PolicyN_is这样的包裹, 使用起来也更加优雅. <br>
<br>
还是看看代码:<br>
<br>
1. 同上, 定义一个if语句. <br>
<br>
template &lt;bool, class T, class U&gt;<br>
struct if_<br>
{<br>
&nbsp;&nbsp;&nbsp; typedef typename T type;<br>
};<br>
<br>
template&lt;class T, class U&gt;<br>
struct if_&lt;false,&nbsp; T,&nbsp; U&gt;<br>
{<br>
&nbsp;&nbsp;&nbsp; typedef typename U type;<br>
};<br>
<br>
2. 定义一个wrapper, 使得 type_wrapper&lt;T&gt;::type 有效(为T). 因为直接使用 T::type 可能遇到T根本没有type这个typedef内嵌类型. <br>
<br>
template&lt;class T&gt;<br>
struct type_wrapper<br>
{<br>
&nbsp;&nbsp;&nbsp; typedef T type;<br>
};<br>
<br>
struct&nbsp; DefaultPolicyArgs {<br>
&nbsp;&nbsp;&nbsp; static const int value =
0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
//特殊meta-data, 为0表示默认参数<br>
};<br>
<br>
<br>
3.
然后使用一个 type_selector meta-function,
N表示第几个默认参数(注意我的默认Policy参数DefaultPolicyArgs里面有一个meta data, 为0.
如果是用户定义的Policy, 那么它也应该定义一个meta data,.
这个数字主要是用于告诉selector它是想覆盖第几个默认的policy参数. <br>
<br>
最后的DefaultType是当扫描一遍, 发现没有任何对应N位置的自定义Policy参数, 那么就取这个为默认值, 结束递归.(下面的4个DefaultPolicyArgs的特化版本就是干这个的) <br>
<br>
与前面的一个版本相比, 我不再使用void, 而是使用DefaultPolicyArgs来填充, 这样在大部分情况下匹配速度要快. (指编译速度)<br>
<br>
template&lt; <br>
&nbsp;&nbsp;&nbsp; int N,<br>
&nbsp;&nbsp;&nbsp; class T1,<br>
&nbsp;&nbsp;&nbsp; class T2,<br>
&nbsp;&nbsp;&nbsp; class T3,<br>
&nbsp;&nbsp;&nbsp; class T4,<br>
&nbsp;&nbsp;&nbsp; class DefaultType&gt;<br>
struct type_selector<br>
{<br>
&nbsp;&nbsp;&nbsp; typedef typename if_ &lt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (T1::value == N), <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type_wrapper&lt;T1&gt;,<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; type_selector&lt;N, T2, T3, T4, DefaultPolicyArgs, DefaultType&gt; &gt;::type eval_type;<br>
<br>
&nbsp;&nbsp;&nbsp; typedef typename eval_type::type type;<br>
};<br>
<br>
//shift以后最终来到这里, 结束递归<br>
template&lt;<br>
&nbsp;&nbsp;&nbsp; int N,<br>
&nbsp;&nbsp;&nbsp; class DefaultType&gt;<br>
struct type_selector&lt;N, DefaultPolicyArgs, DefaultPolicyArgs, DefaultPolicyArgs, DefaultPolicyArgs, DefaultType&gt;<br>
{<br>
&nbsp;&nbsp;&nbsp; typedef DefaultType type;<br>
};<br>
<br>
<br>
struct DefaultPolicy1 {};<br>
struct DefaultPolicy2 {};<br>
struct DefaultPolicy3 {<br>
&nbsp; public:<br>
&nbsp;&nbsp;&nbsp; static void doPrint() {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "DefaultPolicy3::doPrint()\n";<br>
&nbsp;&nbsp;&nbsp; }<br>
};<br>
class DefaultPolicy4 {};<br>
<br>
<br>
template&lt;class T1, class T2, class T3, class T4&gt;<br>
struct PolicySelector<br>
{<br>
&nbsp;&nbsp;&nbsp; typedef typename type_selector&lt;1, T1, T2, T3, T4, DefaultPolicy1&gt;::type P1;<br>
&nbsp;&nbsp;&nbsp; typedef typename type_selector&lt;2, T1, T2, T3, T4, DefaultPolicy2&gt;::type P2;<br>
&nbsp;&nbsp;&nbsp; typedef typename type_selector&lt;3, T1, T2, T3, T4, DefaultPolicy3&gt;::type P3;<br>
&nbsp;&nbsp;&nbsp; typedef typename type_selector&lt;4, T1, T2, T3, T4, DefaultPolicy4&gt;::type P4;<br>
};<br>
&nbsp;&nbsp;&nbsp; <br>
<br>
<br>
template &lt;typename T1 = DefaultPolicyArgs,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typename T2 = DefaultPolicyArgs,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typename T3 = DefaultPolicyArgs,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typename T4 = DefaultPolicyArgs&gt;<br>
class BreadSlicer {<br>
&nbsp;&nbsp;&nbsp; typedef typename PolicySelector&lt;T1, T2, T3, T4&gt; Policies;<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp; public:<br>
&nbsp;&nbsp;&nbsp; void print () {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; std::cout &lt;&lt; typeid(Policies::P3).name() &lt;&lt; std::endl;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Policies::P3::doPrint();<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; void&nbsp; print_2()<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; typeid(Policies::P2).name() &lt;&lt; std::endl;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Policies::P2::print_2();<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; //...<br>
};<br>
<br>
<br>
class CustomPolicy2 {<br>
public:<br>
&nbsp;&nbsp;&nbsp; static const int value = 2;&nbsp;&nbsp;&nbsp;&nbsp; //关键的修改在此, 这个是实现定制Policy时需要提供的meta data<br>
&nbsp;&nbsp;&nbsp; static void print_2()<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "Here is CustomPolicy2 instance" &lt;&lt; std::endl;<br>
&nbsp;&nbsp;&nbsp; }<br>
};<br>
<br>
class CustomPolicy3 {<br>
&nbsp; public:&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; static const int value = 3;&nbsp;&nbsp;&nbsp;&nbsp; //meta data, 同上, 3表示这个代表的是用了替换Policy3<br>
&nbsp;&nbsp;&nbsp; static void doPrint() {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "CustomPolicy3::doPrint()\n";<br>
&nbsp;&nbsp;&nbsp; }<br>
};<br>
<br>
<br>
//这样, PolicyN_is 就没有了, 唯一的要求就是, 当实现custom policy的时候, 别忘了在其中定义一个叫做<br>
value的整形常量, N代表替换哪个默认的policy参数. <br>
<br>
int main()<br>
{<br>
&nbsp;&nbsp;&nbsp; BreadSlicer&lt;&gt;
bc1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
//全部默认<br>
&nbsp;&nbsp;&nbsp; bc1.print();<br>
<br>
&nbsp;&nbsp;&nbsp; BreadSlicer&lt; CustomPolicy2, CustomPolicy3 &gt; bc2;&nbsp;&nbsp; //2,3定制, 是不是干净一些? <br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; bc2.print();<br>
&nbsp;&nbsp;&nbsp; bc2.print_2();<br>
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; std::flush;<br>
&nbsp;&nbsp;&nbsp; return 0;<br>
}<br>
<img src ="http://www.cppblog.com/apollo/aggbug/3557.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-02-27 23:14 <a href="http://www.cppblog.com/apollo/articles/templateArg.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用std::find查找文件流中的内容</title><link>http://www.cppblog.com/apollo/articles/IfsrteamAndFind.html</link><dc:creator>笑笑生</dc:creator><author>笑笑生</author><pubDate>Mon, 27 Feb 2006 14:59:00 GMT</pubDate><guid>http://www.cppblog.com/apollo/articles/IfsrteamAndFind.html</guid><wfw:comment>http://www.cppblog.com/apollo/comments/3556.html</wfw:comment><comments>http://www.cppblog.com/apollo/articles/IfsrteamAndFind.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/apollo/comments/commentRss/3556.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/apollo/services/trackbacks/3556.html</trackback:ping><description><![CDATA[&nbsp;在一般的情况下, 我是很少使用迭代器istream_iterator的。最近在为项目编写一个读特定格式文件的功能时，发现使用istream_iterator和std::find能非常方便的实现文件内容的查找。<br>

<hr>


<p>注：以下全部假定是文本文件，二进制文件没有测试过。</p>

<p>
</p>
<hr>
<br>
假定要查找的是一个文件中的某个string，可以这样实现：

<p>&nbsp;</p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="../../Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;ifstream&nbsp;fIn(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">yourfile</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br><img src="../../Images/OutliningIndicators/None.gif" align="top">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(fIn)<br><img id="Codehighlighter1_40_439_Open_Image" onclick="this.style.display='none'; Codehighlighter1_40_439_Open_Text.style.display='none'; Codehighlighter1_40_439_Closed_Image.style.display='inline'; Codehighlighter1_40_439_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_40_439_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_40_439_Closed_Text.style.display='none'; Codehighlighter1_40_439_Open_Image.style.display='inline'; Codehighlighter1_40_439_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top">&nbsp;&nbsp;</span><span id="Codehighlighter1_40_439_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_40_439_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;istream_iterator</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 255);">string</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;strReader(fIn);</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;file&nbsp;begin</span><span style="color: rgb(0, 128, 0);"><br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;istream_iterator</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 255);">string</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;strEOF;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;file&nbsp;end</span><span style="color: rgb(0, 128, 0);"><br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: rgb(0, 0, 0);"><br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">string</span><span style="color: rgb(0, 0, 0);">&nbsp;strToFind&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">mythma</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">;<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;strReader</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">find(strReader,&nbsp;strEOF,&nbsp;strToFind);<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);">(strReader&nbsp;</span><span style="color: rgb(0, 0, 0);">!=</span><span style="color: rgb(0, 0, 0);">&nbsp;strEOF)<br><img id="Codehighlighter1_263_435_Open_Image" onclick="this.style.display='none'; Codehighlighter1_263_435_Open_Text.style.display='none'; Codehighlighter1_263_435_Closed_Image.style.display='inline'; Codehighlighter1_263_435_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_263_435_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_263_435_Closed_Text.style.display='none'; Codehighlighter1_263_435_Open_Image.style.display='inline'; Codehighlighter1_263_435_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_263_435_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_263_435_Open_Text"><span style="color: rgb(0, 0, 0);">{&nbsp;<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">strReader;&nbsp;&nbsp;<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"><img src="../../Images/dot.gif">&nbsp;do&nbsp;something&nbsp;<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">*strReader;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">dereference&nbsp;to&nbsp;get&nbsp;current&nbsp;string<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;find&nbsp;next&nbsp;</span><span style="color: rgb(0, 128, 0);"><br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;strReader</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">find(strReader,&nbsp;strEOF,&nbsp;strToFind);<br><img src="../../Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp;}</span></span><span style="color: rgb(0, 0, 0);"><br><img src="../../Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">&nbsp;&nbsp;}</span></span><span style="color: rgb(0, 0, 0);"><br><img src="../../Images/OutliningIndicators/None.gif" align="top"><br><img src="../../Images/OutliningIndicators/None.gif" align="top"></span></div>

<p><br>从上面的代码可以看出, 此时fIn可以看作是一个存放const string的容器。</p>

<p>
</p>
<hr>
<br>
<strong><font size="5">题外话:</font></strong> <br>
<br>
<strong>1、什么时候可以考虑使用istream_iterator?<br></strong><br>
我觉得,当文件中是同构数据的时候,使用istream_iterator可以方便的读取、查找对象。<br>
1) 如果文件中的内容都是同一种基本类型的数据，如int，可以这样用istream_iterator:<br>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="../../Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;istream_iterator</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;intReader(fIn);</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;file&nbsp;begin</span><span style="color: rgb(0, 128, 0);"><br><img src="../../Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;istream_iterator</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;intEOF;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;file&nbsp;end</span></div>
<br>
2) 如果是一个个自定义CUser对象的数据顺序存放的，需要重载operator &gt;&gt;，然后这样用：<br>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="../../Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;istream_iterator</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">CUser</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;intReader(fIn);</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;file&nbsp;begin</span><span style="color: rgb(0, 128, 0);"><br><img src="../../Images/OutliningIndicators/None.gif" align="top"></span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;istream_iterator</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">CUser</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;intEOF;&nbsp;&nbsp;</span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">&nbsp;file&nbsp;end</span></div>
<br>
如果需要查找对象，在特定的情况下还需要重载比较运算符。

<p><strong>2、文件中是异构数据情况的处理<br></strong><br>首先文件中所有的内容都可以用string来操作，这种处理方式无需讨论。<br>若用istream_iterator&lt;int&gt;读取包含非int数据的文件时会出现什么情况？<br>经测试，当istream_iterator&lt;int&gt;遇到第一个非int数据时，迭代终止。<br>---<br>测试代码：<br></p>

<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: rgb(238, 238, 238);"><img src="../../Images/OutliningIndicators/None.gif" align="top"><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">using</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">namespace</span><span style="color: rgb(0, 0, 0);">&nbsp;std;<br><img src="../../Images/OutliningIndicators/None.gif" align="top">&nbsp;&nbsp;ifstream&nbsp;fIn(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">test.txt</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br><img src="../../Images/OutliningIndicators/None.gif" align="top">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(fIn)<br><img id="Codehighlighter1_63_204_Open_Image" onclick="this.style.display='none'; Codehighlighter1_63_204_Open_Text.style.display='none'; Codehighlighter1_63_204_Closed_Image.style.display='inline'; Codehighlighter1_63_204_Closed_Text.style.display='inline';" src="../../Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_63_204_Closed_Image" style="display: none;" onclick="this.style.display='none'; Codehighlighter1_63_204_Closed_Text.style.display='none'; Codehighlighter1_63_204_Open_Image.style.display='inline'; Codehighlighter1_63_204_Open_Text.style.display='inline';" src="../../Images/OutliningIndicators/ContractedBlock.gif" align="top">&nbsp;&nbsp;</span><span id="Codehighlighter1_63_204_Closed_Text" style="border: 1px solid rgb(128, 128, 128); display: none; background-color: rgb(255, 255, 255);"><img src="../../Images/dot.gif"></span><span id="Codehighlighter1_63_204_Open_Text"><span style="color: rgb(0, 0, 0);">{<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;istream_iterator</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;intReader(fIn);<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;istream_iterator</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;intEOF;<br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top"><br><img src="../../Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;copy(intReader,&nbsp;intEOF,&nbsp;ostream_iterator</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">(cout,&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">));<br><img src="../../Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">&nbsp;&nbsp;}</span></span><span style="color: rgb(0, 0, 0);"><br><img src="../../Images/OutliningIndicators/None.gif" align="top"></span></div>

<p><br>---<br>测试文件test.txt：<br>1 22 3.4 haha 44 hello<br>---<br>输出结果：<br>1 22 3</p>

<p><strong>3、效率问题</strong><br>istream_iterator除了使代码看起来比较简洁外，大家最关心的恐怕就是效率问题。我没有测试比较过<img src="../../Emoticons/QQ/16.gif" border="0" height="20" width="20">。</p>
<img src ="http://www.cppblog.com/apollo/aggbug/3556.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/apollo/" target="_blank">笑笑生</a> 2006-02-27 22:59 <a href="http://www.cppblog.com/apollo/articles/IfsrteamAndFind.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>