﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-逆水行舟-随笔分类-C++</title><link>http://www.cppblog.com/yearner/category/4821.html</link><description>智慧需要点滴的积累</description><language>zh-cn</language><lastBuildDate>Thu, 20 Nov 2008 17:57:44 GMT</lastBuildDate><pubDate>Thu, 20 Nov 2008 17:57:44 GMT</pubDate><ttl>60</ttl><item><title> Quoted printable 编码说明</title><link>http://www.cppblog.com/yearner/archive/2008/11/20/67421.html</link><dc:creator>(Leyn)顽主</dc:creator><author>(Leyn)顽主</author><pubDate>Thu, 20 Nov 2008 13:46:00 GMT</pubDate><guid>http://www.cppblog.com/yearner/archive/2008/11/20/67421.html</guid><wfw:comment>http://www.cppblog.com/yearner/comments/67421.html</wfw:comment><comments>http://www.cppblog.com/yearner/archive/2008/11/20/67421.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yearner/comments/commentRss/67421.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yearner/services/trackbacks/67421.html</trackback:ping><description><![CDATA[<font size="2" face="Default Sans Serif, Verdana, Arial, Helvetica, sans-serif">
<p class="EC_MsoNormal"><span lang="EN-US"><span></span></span></p>
<p class="EC_MsoListParagraph" style="text-indent: -1cm;"><span style="font-family: 'arial','sans-serif';" lang="EN-US"><span><font size="3">3.2</font><span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><font size="3"><span style="font-family: 'arial','sans-serif';" lang="EN-US">Quoted printable </span><span style="font-family: 仿宋_GB2312;">编码</span><span style="font-family: 'arial','sans-serif';" lang="EN-US"></span></font></p>
<p class="EC_MsoListParagraph" style="text-indent: 0cm;"><font size="3"><span lang="EN-US"><span><font face="Calibri">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span><span style="font-family: 'arial','sans-serif';" lang="EN-US">QP </span><span style="font-family: 仿宋_GB2312;">编码用于表示含有大量对应可打印字符的数组，这种编码方式使字符单元在传输过程中被更改的可能性很小。如果正在编码的数据大部分是</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">ASCII</span><span style="font-family: 仿宋_GB2312;">文本，那么编码后的形式具有很高的可读性。一个完全是</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">ASCII</span><span style="font-family: 仿宋_GB2312;">值的正文数据由</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">QP</span><span style="font-family: 仿宋_GB2312;">编码后可以保证数据在字符翻译或经由网关时数据的完整性。</span><span style="font-family: 'arial','sans-serif';" lang="EN-US"></span></font></p>
<p class="EC_MsoListParagraph" style="text-indent: 0cm;"><font size="3"><span style="font-family: 'arial','sans-serif';" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 仿宋_GB2312;">编码规则如下：</span><span style="font-family: 'arial','sans-serif';" lang="EN-US"></span></font></p>
<p class="EC_MsoListParagraph" style="text-indent: 0cm;"><font size="3"><span style="font-family: 'arial','sans-serif';" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 仿宋_GB2312;">规则</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">1</span><span style="font-family: 仿宋_GB2312;">：</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">(</span><span style="font-family: 仿宋_GB2312;">一般</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">8</span><span style="font-family: 仿宋_GB2312;">位组的表示方式</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">), </span><span style="font-family: 仿宋_GB2312;">任何的八位组，都可以用</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">&#8221;=&#8221;</span><span style="font-family: 仿宋_GB2312;">后加该八位组的</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">16</span><span style="font-family: 仿宋_GB2312;">进制值来表示，除了那些根据数据编码规范中新行的惯例来指定短行的表示单位。必须用大写字母。比如值是</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">12 </span><span style="font-family: 仿宋_GB2312;">，则表示为</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">&#8221;=0C&#8221;</span><span style="font-family: 仿宋_GB2312;">。</span><span style="font-family: 'arial','sans-serif';" lang="EN-US"></span></font></p>
<p class="EC_MsoListParagraph" style="text-indent: 0cm;"><font size="3"><span style="font-family: 'arial','sans-serif';" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 仿宋_GB2312;">规则</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">2</span><span style="font-family: 仿宋_GB2312;">：</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">(</span><span style="font-family: 仿宋_GB2312;">文字表示</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">)</span><span style="font-family: 仿宋_GB2312;">值在</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">33-60 </span><span style="font-family: 仿宋_GB2312;">，以及</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">62-126</span><span style="font-family: 仿宋_GB2312;">的八位组</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">(</span><span style="font-family: 仿宋_GB2312;">包含头尾值</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">)</span><span style="font-family: 仿宋_GB2312;">，可以表示成那些八位组对应的</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">ASCII</span><span style="font-family: 仿宋_GB2312;">字符。</span><span style="font-family: 'arial','sans-serif';" lang="EN-US"></span></font></p>
<p class="EC_MsoListParagraph" style="text-indent: 0cm;"><font size="3"><span style="font-family: 'arial','sans-serif';" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 仿宋_GB2312;">规则</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">3</span><span style="font-family: 仿宋_GB2312;">：</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">(</span><span style="font-family: 仿宋_GB2312;">空格</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">) </span><span style="font-family: 仿宋_GB2312;">值是</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">9</span><span style="font-family: 仿宋_GB2312;">和</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">32</span><span style="font-family: 仿宋_GB2312;">的八位组可以分别表示为</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">ASCII </span><span style="font-family: 仿宋_GB2312;">的</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">TAB</span><span style="font-family: 仿宋_GB2312;">和</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">SPACE</span><span style="font-family: 仿宋_GB2312;">值，但是不可以出现在编码行的末尾。任何在编码行的</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">TAB</span><span style="font-family: 仿宋_GB2312;">或</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">SPACE</span><span style="font-family: 仿宋_GB2312;">字符必须后面有可打印字符出现。特殊情况下，编码行的末尾出现的</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">&#8221;=&#8221;</span><span style="font-family: 仿宋_GB2312;">，表示断行，其前面可能是一个或多个</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">TAB</span><span style="font-family: 仿宋_GB2312;">或</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">SPACE</span><span style="font-family: 仿宋_GB2312;">。</span><span style="font-family: 'Arial','sans-serif';"> </span><span style="font-family: 仿宋_GB2312;">实行这条规则的原因是一些</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">METs(Message Transport Agents-</span><span style="font-family: 仿宋_GB2312;">消息传输单元</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">)</span><span style="font-family: 仿宋_GB2312;">会在文本末尾补上</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">SPACE</span><span style="font-family: 仿宋_GB2312;">，因此，解码时，任何跟在行后的空格必须删除。</span><span style="font-family: 'arial','sans-serif';" lang="EN-US"></span></font></p>
<p class="EC_MsoListParagraph" style="text-indent: 0cm;"><font size="3"><span style="font-family: 'arial','sans-serif';" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 仿宋_GB2312;">规则</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">4</span><span style="font-family: 仿宋_GB2312;">：</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">(</span><span style="font-family: 仿宋_GB2312;">断行</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">)</span><span style="font-family: 仿宋_GB2312;">在原文中的断行必须表示成协议中的断行符</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">-CRLF</span><span style="font-family: 仿宋_GB2312;">序列<span style="color: red;">（</span></span><span style="color: red; font-family: 'arial','sans-serif';" lang="EN-US">"=0D=0A&#8221; </span><span style="color: red; font-family: 仿宋_GB2312;">）</span><span style="font-family: 仿宋_GB2312;">。由于非文本类型的规范表示一般不包括断行，所以这种类型的</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">qp</span><span style="font-family: 仿宋_GB2312;">编码没有硬换行。通常，</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">base64</span><span style="font-family: 仿宋_GB2312;">编码在二进制编码上更占优势。</span><span style="font-family: 'arial','sans-serif';" lang="EN-US"></span></font></p>
<p class="EC_MsoListParagraph" style="text-indent: 0cm;"><font size="3"><span style="font-family: 'arial','sans-serif';" lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 仿宋_GB2312;">规则</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">5</span><span style="font-family: 仿宋_GB2312;">：</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">(</span><span style="font-family: 仿宋_GB2312;">软换行</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">)QP</span><span style="font-family: 仿宋_GB2312;">编码要求编码后每行不能超过</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">76</span><span style="font-family: 仿宋_GB2312;">个字符。当超过这个限制时，将适用软换行，用</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">&#8221;=&#8221;</span><span style="font-family: 仿宋_GB2312;">表示编码行的断行，后接</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">CRLF</span><span style="font-family: 仿宋_GB2312;">。（</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">76</span><span style="font-family: 仿宋_GB2312;">的限制包括</span><span style="font-family: 'arial','sans-serif';" lang="EN-US">&#8221;=&#8221;</span><span style="font-family: 仿宋_GB2312;">）。</span><span style="font-family: 'arial','sans-serif';" lang="EN-US"></span></font></p>
<p class="EC_MsoListParagraph" style="text-indent: 0cm;"><span style="font-family: 'arial','sans-serif';" lang="EN-US"><font size="3"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></font></span></p>
</font><img src ="http://www.cppblog.com/yearner/aggbug/67421.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yearner/" target="_blank">(Leyn)顽主</a> 2008-11-20 21:46 <a href="http://www.cppblog.com/yearner/archive/2008/11/20/67421.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Base 64 编码说明</title><link>http://www.cppblog.com/yearner/archive/2008/11/20/67418.html</link><dc:creator>(Leyn)顽主</dc:creator><author>(Leyn)顽主</author><pubDate>Thu, 20 Nov 2008 13:45:00 GMT</pubDate><guid>http://www.cppblog.com/yearner/archive/2008/11/20/67418.html</guid><wfw:comment>http://www.cppblog.com/yearner/comments/67418.html</wfw:comment><comments>http://www.cppblog.com/yearner/archive/2008/11/20/67418.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yearner/comments/commentRss/67418.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yearner/services/trackbacks/67418.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 3.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Base 64编码Base 64 编码采用了US-ASCII 的65个字符集，每个字符都由6位来表示（0-&nbsp; 2 6-1），而第65位字符&#8220;=&#8221;用来表示字符串的结束。&nbsp;                        ...&nbsp;&nbsp;<a href='http://www.cppblog.com/yearner/archive/2008/11/20/67418.html'>阅读全文</a><img src ="http://www.cppblog.com/yearner/aggbug/67418.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yearner/" target="_blank">(Leyn)顽主</a> 2008-11-20 21:45 <a href="http://www.cppblog.com/yearner/archive/2008/11/20/67418.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MIME邮件格式说明</title><link>http://www.cppblog.com/yearner/archive/2008/11/20/67417.html</link><dc:creator>(Leyn)顽主</dc:creator><author>(Leyn)顽主</author><pubDate>Thu, 20 Nov 2008 13:44:00 GMT</pubDate><guid>http://www.cppblog.com/yearner/archive/2008/11/20/67417.html</guid><wfw:comment>http://www.cppblog.com/yearner/comments/67417.html</wfw:comment><comments>http://www.cppblog.com/yearner/archive/2008/11/20/67417.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yearner/comments/commentRss/67417.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yearner/services/trackbacks/67417.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 邮件格式说明Mutiple Internet Mail ExtensionsRefer to Internet Official Protocol Standards RFC 8221&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 概述网络间传递的电子邮件需要公共认同的格式，以便于客户端邮箱软件识别拆解其间的信息。邮件本身是由ASCII字符构成...&nbsp;&nbsp;<a href='http://www.cppblog.com/yearner/archive/2008/11/20/67417.html'>阅读全文</a><img src ="http://www.cppblog.com/yearner/aggbug/67417.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yearner/" target="_blank">(Leyn)顽主</a> 2008-11-20 21:44 <a href="http://www.cppblog.com/yearner/archive/2008/11/20/67417.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转 ]浅谈C++的智能指针 </title><link>http://www.cppblog.com/yearner/archive/2008/11/09/66447.html</link><dc:creator>(Leyn)顽主</dc:creator><author>(Leyn)顽主</author><pubDate>Sun, 09 Nov 2008 12:43:00 GMT</pubDate><guid>http://www.cppblog.com/yearner/archive/2008/11/09/66447.html</guid><wfw:comment>http://www.cppblog.com/yearner/comments/66447.html</wfw:comment><comments>http://www.cppblog.com/yearner/archive/2008/11/09/66447.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yearner/comments/commentRss/66447.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yearner/services/trackbacks/66447.html</trackback:ping><description><![CDATA[<h1 id="subject_tpc" class="fl">浅谈C++的智能指针</h1>
<div class="tpc_content" id="read_tpc">内存泄露是C++程序员都头疼的大<span onclick="sendmsg('pw_ajax.php','action=relatetag&amp;tagname=问题',this.id)" style="border-bottom: 1px solid #fa891b; cursor: pointer;" id="rlt_4">问题</span>。C++缺乏像JAVA、C#一样，拥有GC这么一项有利的武器，它将内存管理的部分<span onclick="sendmsg('pw_ajax.php','action=relatetag&amp;tagname=权限',this.id)" style="border-bottom: 1px solid #fa891b; cursor: pointer;" id="rlt_2">权限</span>交给了程序员。虽然GC的存在节约了开发、排错的时间与成本，但是C++为了追求运行<span onclick="sendmsg('pw_ajax.php','action=relatetag&amp;tagname=速度',this.id)" style="border-bottom: 1px solid #fa891b; cursor: pointer;" id="rlt_1">速度</span>而20年来坚决不予补充进其标准。（题外话：C++通过加大开发难度去换取执行速度的做法，在现在看来不知是否能给与正面的评价，还是留给将来再说吧。）<br><br>&nbsp; 从此，在堆上申请了内存忘了释放、所造成的内存泄露的问题就一直困扰着C++程序员。也许为了稍许弥补没有垃圾回收器所造成的开发门槛高，各大厂商开发的C++库中都像COM学习引入智能指针试图解决部分目前存在的问题。<br><br>&nbsp;
智能指针是存储指向动态分配（堆）对象指针的类, 用于生存期控制,
能够确保自动正确的销毁动态分配的对象，防止内存泄露。它的一种通用实现技术是使用引用计数(reference
count)。智能指针类将一个计数器与类指向的对象相关联，引用计数跟踪该类有多少个对象共享同一指针。每次创建类的新对象时，初始化指针并将引用计数
置为1；当对象作为另一对象的副本而创建时，拷贝构造函数拷贝指针并增加与之相应的引用计数；对一个对象进行赋值时，赋值操作符减少左操作数所指对象的引
用计数（如果引用计数为减至0，则删除对象），并增加右操作数所指对象的引用计数；调用析构函数时，构造函数减少引用计数（如果引用计数减至0，则删除基
础对象）。<br><br>&nbsp; 说到智能指针，我们一定要看看标准C++库提供的&#8220;搞笑的&#8221;智能指针:auto_ptr。<br><br>&nbsp;
标准库中提供了C++程序的基本设施。虽然C++标准库随着C++标准折腾了许多年，直到标准的出台才正式定型，网上评论C++标准库时都说：&#8220;在标准库
的实现上却很令人欣慰得看到多种实现，并且已被实践证明为有工业级别强度的佳作。&#8221;但目前的标准C++中，只有一种独苗智能指
针：std::auto_ptr。<br><br>&nbsp; auto_ptr指针是一个RAII对象,它初始化时获得资源,析构时自动释放资源(生命期结束).它的缺点数不胜数：<br> 1、auto_ptr要求一个对象只能有一个拥有者，严禁一物二主<br> 2、缺少对引用数和数组的支持。<br> 3、不可将auto_ptr对象作为STL容器的元素。C++标准明确禁止这样做，否则可能会碰到不可预见的结果。（这一条晕死一<span onclick="sendmsg('pw_ajax.php','action=relatetag&amp;tagname=大片',this.id)" style="border-bottom: 1px solid #fa891b; cursor: pointer;" id="rlt_5">大片</span>）。<br>4、auto_ptr在被复制的时候会传输所有权<br><br> 反正由此可见：标准库的智能指针就是无甚大用。<br><br>&nbsp; &nbsp; 在这样的情况下，C++标准委员会自然需要考虑引入新的智能指针。目前由C++标准委员会库工作组发起的Boost 组织开发了Boost系列智能指针。<br><br>&nbsp; 在Boost中的智能指针有五种： scoped_ptr，scoped_array，shared_ptr，shared_array，weak_ptr.<br><br>前4种完全是针对标准库中的auto_ptr提出解决方案，如：scope_ptr是针对&#8220;auto_ptr在被复制的时候会传输所有权&#8221;这一弱点提出的。最后一种没见过，看名字像是弱引用智能指针，我怀疑<span onclick="sendmsg('pw_ajax.php','action=relatetag&amp;tagname=是不是',this.id)" style="border-bottom: 1px solid #fa891b; cursor: pointer;" id="rlt_3">是不是</span>类似于JAVA中弱引用一样,有待进一步学习。</div><img src ="http://www.cppblog.com/yearner/aggbug/66447.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yearner/" target="_blank">(Leyn)顽主</a> 2008-11-09 20:43 <a href="http://www.cppblog.com/yearner/archive/2008/11/09/66447.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]C++中的指针--智能指针</title><link>http://www.cppblog.com/yearner/archive/2008/11/09/66445.html</link><dc:creator>(Leyn)顽主</dc:creator><author>(Leyn)顽主</author><pubDate>Sun, 09 Nov 2008 12:37:00 GMT</pubDate><guid>http://www.cppblog.com/yearner/archive/2008/11/09/66445.html</guid><wfw:comment>http://www.cppblog.com/yearner/comments/66445.html</wfw:comment><comments>http://www.cppblog.com/yearner/archive/2008/11/09/66445.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yearner/comments/commentRss/66445.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yearner/services/trackbacks/66445.html</trackback:ping><description><![CDATA[<p>Smart Pointer是<a  href="http://www.bc-cn.net/Article/kfyy/cjj/Index.html" class="channel_keylink">C++</a>中的一个大题目，要说清楚他的所有好处很需要费点力气。我就一个功能一个功能的说。有我理解不透的地方希望大家指点。<br><br>1.copy-to-write<br>当生成一个<a  href="http://www.bc-cn.net/Article/kfyy/cjj/Index.html" class="channel_keylink">C++</a> object的时候如果这个class很大，这个object会占用很多空间。那么每生成一个就占用一片空间，这样会占用很多系统资源。同时降低效率。一个解决方法就是对用拷贝构造<a  href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=%BA%AF%CA%FD" class="channel_keylink">函数</a>生成的object，让他不存储数据，而只存储一个指向原来object数据的<a  href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=%D6%B8%D5%EB&amp;Submit=+%CB%D1%CB%F7+" class="channel_keylink">指针</a>。 这样空间就节省了很多。但问题在于这样两个object完全联结在了一起。如果修改了其中一个，另一个也跟着变了。所以这种方法不可取。这里讲的 copy-to-write技术就是解决这类问题的方法。当通过引用一个已有object去拷贝构造新object时，新object只有一个指向已有 object的<a  href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=%D6%B8%D5%EB&amp;Submit=+%CB%D1%CB%F7+" class="channel_keylink">指针</a>。
这两个object共享数据。直到其中一个需要修改数据的时候，再把这两块数据分离。这里举一个最简化的例子。假设一个class叫
CLargeObject，里面存有很多数据。我们用一个inner
class来把所有数据放在一起，叫CData。CData里面存有大量数据，例如一个<a  href="http://www.bc-cn.net/Article/sjk/Index.html" class="channel_keylink">数据库</a>。这里用最简单的模型来表示，假设只有一个整数int m_nVal; CData里面需要包含另一个变量。叫作索引数目(reference count)。它记录了指向这个CData object的来自CLargetObject类的<a  href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=%D6%B8%D5%EB&amp;Submit=+%CB%D1%CB%F7+" class="channel_keylink">指针</a>各数。也就是说，总共有多少CLargeObject的object正在引用着当前的CData object。<br><br>class CLargeObject<br>{<br>private:<br>&nbsp;&nbsp;&nbsp;&nbsp;struct CData<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;private:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int m_nVal;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int m_nReferenceCount;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>};<br><br>对于每个CLargeObject的object，我们用一个CData类的<a  href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=%D6%B8%D5%EB&amp;Submit=+%CB%D1%CB%F7+" class="channel_keylink">指针</a>来指向其数据。<br>CData *m_pData;<br><br>CLargeObject至少有两个构造<a  href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=%BA%AF%CA%FD" class="channel_keylink">函数</a>。第一个是标准的构造<a  href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=%BA%AF%CA%FD" class="channel_keylink">函数</a>，初始化其数据。这时数据是唯一的，所以必须新生成一个CData的object来存储数据。<br>CLargeObject::CLargeObject(int nVal)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;m_pData = new Data(nVal);<br>}<br>而对于CData类的构造<a  href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=%BA%AF%CA%FD" class="channel_keylink">函数</a>而言，初始化他的CLargeObject是第一个指向他的，这一时刻索引数目m_nReferenceCount是1。<br>CLargeObject::Data::Data(int nVal) : m_nVal(nVal), m_nReferenceCount(1) {}<br><br>CLargeObject的第二个构造<a  href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=%BA%AF%CA%FD" class="channel_keylink">函数</a>是拷贝构造(copy constructor)。这样生成的object不需要有新的数据，和已有的object共享数据就可以了。这是索引数目需要加1。表示又有一个object指向当前的CData了。<br>CLargeObject::CLargeObject(const CLargeObject &amp;ob) // copy constructor<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;ob.m_pData-&gt;m_nReferenceCount++;<br>&nbsp;&nbsp;&nbsp;&nbsp;m_pData = ob.m_pData;<br>}<br><br><br>这样CLargeObject就构造好了，使用了可能的最少的内存。下面看看他的析够<a  href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=%BA%AF%CA%FD" class="channel_keylink">函数</a>(destructor)。当一个object被delete的时候，它的数据不一定无效，如果别的object还在引用着这个数据，数据需要留下来。当然，数据的索引数目无论如何都要减1。<br>CLargeObject::~CLargeObject()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;if (--m_pData-&gt;m_nReferenceCount == 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete m_pData;<br>}<br><br>下面看一看赋值操作。先说用已有的CLargeObject赋值给这个CLargeObject。这时当前CLargeObject里面的数据要指向已有的这个object，就搞定了。<br>CLargeObject&amp; CLargeObject::operator = (const CLargeObject&amp; ob)&nbsp;&nbsp;&nbsp;&nbsp;// copy assignment<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;ob.m_pData-&gt;m_nReferenceCount++;<br>&nbsp;&nbsp;&nbsp;&nbsp;if (--m_pData-&gt;m_nReferenceCount == 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete m_pData;<br>&nbsp;&nbsp;&nbsp;&nbsp;m_pData = ob.m_pData;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;return *this;<br>}<br><br>再来看看如何对CLargeObject里面的数据进行真正的修改。这样就一定需要对当前的object独立操作了，否则就影响到了其它指向同一块数据的CLargeObject。这样CData类需要一个新的<a  href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=%BA%AF%CA%FD" class="channel_keylink">函数</a>，生成只用于当前CLargetObject的数据。如果当前的引用数目是1，那么当然这个CData就是只用于这个CLargeObject的了。否则就重新new一个CData返回。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Data* CLargeObject::CData::get_own_copy()&nbsp;&nbsp;&nbsp;&nbsp;// clone if necessary<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (m_nReferenceCount==1)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return this;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_nReferenceCount--;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return new Data(m_nVal);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>CLargeObject修改前用这个<a  href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=%BA%AF%CA%FD" class="channel_keylink">函数</a>得到唯一的object，然后对它赋值。<br>void CLargeObject::SetVal(int nNewVal)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;m_pData = m_pData-&gt;get_own_copy();<br>&nbsp;&nbsp;&nbsp;&nbsp;m_pData-&gt;m_nVal = nNewVal;<br>}<br>对于所有可能改变CData值的操作，都需要用这种方法。<br><br>下面是只读<a  href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=%BA%AF%CA%FD" class="channel_keylink">函数</a>，简单。直接返回值，什么特殊的都不用作。<br>int CLargeObject::GetVal() const<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;return m_pData-&gt;m_nVal;<br>}<br><br><br>这样copy-to-write技术就实现了。下面把完整的程序写一下：<br>class CLargeObject<br>{<br>public:<br>&nbsp;&nbsp;&nbsp;&nbsp;CLargeObject(int nVal);<br>&nbsp;&nbsp;&nbsp;&nbsp;CLargeObject(const CLargeObject &amp;ob);<br>&nbsp;&nbsp;&nbsp;&nbsp;~CLargeObject();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;CLargeObject&amp; operator = (const CLargeObject&amp; ob);<br>&nbsp;&nbsp;&nbsp;&nbsp;void SetVal(int nNewVal);<br>&nbsp;&nbsp;&nbsp;&nbsp;int GetVal() const;<br>private:<br>&nbsp;&nbsp;&nbsp;&nbsp;struct Data<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;public:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Data(int nVal) : m_nVal(nVal), m_nReferenceCount(1) {}<br>&nbsp;&nbsp;&nbsp;&nbsp;private: <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;friend class CLargeObject;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Data* get_own_copy()&nbsp;&nbsp;&nbsp;&nbsp;// clone if necessary<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (m_nReferenceCount==1)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return this;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_nReferenceCount--;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return new Data(m_nVal);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// control variables.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int m_nReferenceCount;<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// actual data portion<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int m_nVal;<br>&nbsp;&nbsp;&nbsp;&nbsp;};</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;Data *m_pData;<br>};</p>
<p>CLargeObject::CLargeObject(int nVal)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;m_pData = new Data(nVal);<br>}</p>
<p>CLargeObject::CLargeObject(const CLargeObject &amp;ob) // copy constructor<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;ob.m_pData-&gt;m_nReferenceCount++;<br>&nbsp;&nbsp;&nbsp;&nbsp;m_pData = ob.m_pData;<br>}</p>
<p>CLargeObject::~CLargeObject()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;if (--m_pData-&gt;m_nReferenceCount == 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete m_pData;<br>}</p>
<p>CLargeObject&amp; CLargeObject::operator = (const CLargeObject&amp; ob)&nbsp;&nbsp;&nbsp;&nbsp;// copy assignment<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;ob.m_pData-&gt;m_nReferenceCount++;<br>&nbsp;&nbsp;&nbsp;&nbsp;if (--m_pData-&gt;m_nReferenceCount == 0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete m_pData;<br>&nbsp;&nbsp;&nbsp;&nbsp;m_pData = ob.m_pData;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;return *this;<br>}</p>
<p>void CLargeObject::SetVal(int nNewVal)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;m_pData = m_pData-&gt;get_own_copy();<br>&nbsp;&nbsp;&nbsp;&nbsp;m_pData-&gt;m_nVal = nNewVal;<br>}</p>
<p>int CLargeObject::GetVal() const<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;return m_pData-&gt;m_nVal;<br>}<br><br><br>很多存储数据的系统class，如string，CString等都有这种设计。所以记住这个应用是很有必要的。</p><img src ="http://www.cppblog.com/yearner/aggbug/66445.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yearner/" target="_blank">(Leyn)顽主</a> 2008-11-09 20:37 <a href="http://www.cppblog.com/yearner/archive/2008/11/09/66445.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]利用Rational Rose进行C++代码和数据库结构分析</title><link>http://www.cppblog.com/yearner/archive/2008/10/28/65350.html</link><dc:creator>(Leyn)顽主</dc:creator><author>(Leyn)顽主</author><pubDate>Tue, 28 Oct 2008 09:36:00 GMT</pubDate><guid>http://www.cppblog.com/yearner/archive/2008/10/28/65350.html</guid><wfw:comment>http://www.cppblog.com/yearner/comments/65350.html</wfw:comment><comments>http://www.cppblog.com/yearner/archive/2008/10/28/65350.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yearner/comments/commentRss/65350.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yearner/services/trackbacks/65350.html</trackback:ping><description><![CDATA[<table cellSpacing=0 cellPadding=0 width=760 align=center border=0>
    <tbody>
        <tr>
            <td class=title vAlign=center align=middle height=56><strong><font color=#ff0000 size=3>利用Rational Rose进行C++代码和数据库结构分析<br><!-- #EndEditable --></font></strong></td>
        </tr>
        <tr>
            <td class=formtitle align=middle height=40><!-- #BeginEditable "2" -->申 震杰, IBM 中国软件开发中心软件工程师<br><!-- #EndEditable --></td>
        </tr>
    </tbody>
</table>
<table height=65 cellSpacing=0 cellPadding=0 width=760 align=center border=0>
    <tbody>
        <tr>
            <td class=content height=65><!-- #BeginEditable "3" -->
            <table class=p11 cellSpacing=0 cellPadding=0 width="100%" align=center border=0>
                <tbody>
                    <tr>
                        <td class=content style="WORD-WRAP: break-word" height=52>
                        <p>本文内容包括: <br>　<a href="http://www.uml.org.cn/umltools/200607123.htm#1"><u><font color=#800080>一．Rational Rose逆向工程介绍 </font></u></a><br>　<a href="http://www.uml.org.cn/umltools/200607123.htm#2"><u><font color=#800080>二．如何用Rational Rose进行C++代码分析 </font></u></a><br>　<a href="http://www.uml.org.cn/umltools/200607123.htm#3"><u><font color=#800080>三．如何用Rational Rose进行数据库结构分析</font></u></a> <br>　<a href="http://www.uml.org.cn/umltools/200607123.htm#4"><u><font color=#800080>四．如何得到逆向工程的模型图 </font></u></a><br>　<a href="http://www.uml.org.cn/umltools/200607123.htm#5"><u><font color=#800080>五．总结</font></u></a> <br>　<a href="http://www.uml.org.cn/umltools/200607123.htm#6"><u><font color=#800080>注释</font></u></a> <br><br>　Rational Rose是利用UML（统一建模语言）进行分析和设计面向对象软件系统的强大的可视化工具，可以进行项目需求分析、结构规划和生成框架代码，还可以支持从现有系统逆向转出工程代码，生成Rose模型的功能。<br>2004年10月，IBM推出了支持最新的UML2.0的可视化建模工具 Rational Software Architect（见注释①） 和IBM Rational Software Modeler（见注释②）。虽然它们支持在建模功能上有了更好的改进、支持了更新的标准，但是RSA的精彩功能主要是集中在对Java应用的支持，而IBM Rational Software Modeler则是主要关注系统的模型设计，如果要从结构上分析C++编写的系统的代码，Rational Rose还是首选的工具。</p>
                        <p>接下来的文章将会对如何利用Rational Rose 的逆向转出工程来进行系统分析进行更加详细地阐述。</p>
                        <p><strong><a name=1></a>一．Rational Rose逆向工程介绍</strong></p>
                        <p>逆向工程（Reverse Engineer）就是从现有系统的代码来生成模型的功能。分析已有的代码其主要的目的就是了解代码结构和数据结构，这些对应到模型图就是类图、数据模型图和组件图（对UML各种模型图的描述见注释③），也就是通过Rational Rose的逆向工程所得到的结果。Rational Rose所支持的逆向工程功能很强大，包括的编程语言有C++, VB, VC, Java, CORBA，以及数据库DDL脚本等等，并且可以直接连接DB2, SQLServer, Oracle和Sybase等数据库导入Schema并生成数据模型。</p>
                        <p>很多大型的C++开发的产品都涉及到数据库的使用，对这种大型系统的开发，尤其是做二次开发的情况下，主要的难点就是对源码和数据库结构的分析。而利用Rose的逆向工程这一功能，就可以完成代码'类图以及数据库Schema-&gt;数据模型图的转换，解决这两大难点，可以使开发和设计人员在对这种大型系统的升级、分析和开发中，更为方便、快捷、有条理地掌握系统结构，不用再为分析庞大的系统结构而头疼。</p>
                        <p><a name=2></a><strong>二．如何用Rational Rose进行C++代码分析</strong></p>
                        <p>这一节主要介绍用户如何使用Rose的逆向工程生成UML模型，并用来进行C++代码的结构分析。</p>
                        <p>Rational Rose可以支持标准C++和Visual C++的模型到代码的转换以及逆向工程。下面将详细地说明这两种C++ project的逆向工程的步骤和具体操作。</p>
                        <p>1． ANSI C++（标准C++）逆向工程（Reverse Engineer）使用标准C++逆向工程，需要在组件图（component view）中创建一个组件（component），设置好需要进行转换的组件的信息，也就是该组件的语言、所包含的文件、文件所在的路径、文件后缀等等信息，然后Reverse Engineer就可以根据给定的信息将代码转换成类图了。</p>
                        <p>a) 右键点击组件视图（Component View），选择New-&gt;Component，创建一个新的组件<br>　<img height=398 src="http://www.uml.org.cn/umltools/images/001.png" width=508> <br><br>　b) 将component的language属性设定为ANSI C++</p>
                        <p>①选中创建的component，点击右键，选中Open Specification<br>　<img height=283 src="http://www.uml.org.cn/umltools/images/003.png" width=405> </p>
                        <p>②在这个对话框中将该component的language设定为ANSI C++</p>
                        <p><img height=340 src="http://www.uml.org.cn/umltools/images/005.png" width=516><br></p>
                        <p>c) 配置该ANSI C++ component，设置好该component中包含的C++代码文件，并进行C++语言的详细设置</p>
                        <p>①选中该component，点击右键，选择ANSI C++-&gt;Open ANSI C++ Specification</p>
                        <p><img height=356 src="http://www.uml.org.cn/umltools/images/007.png" width=564><br></p>
                        <p>②把Source file root directory设定为你的C++源码文件所在的路径，并且将需要转换的文件添加到Project Files中，视你的需要来做其它的设定，比如：头文件扩展名等等。</p>
                        <p><img height=436 src="http://www.uml.org.cn/umltools/images/009.png" width=572></p>
                        <p>d) 将设置好的component转换成模型图</p>
                        <p>①选中设置好的component，点击右键，选中ANSI C++-&gt;Reverse Engineer</p>
                        <p><img height=330 src="http://www.uml.org.cn/umltools/images/011.png" width=572><br><br>　②选中需要转换的class，点击ok，一个component的逆向转换就完成了。</p>
                        <p><img height=431 src="http://www.uml.org.cn/umltools/images/013.png" width=547><br><br>　2． Visual C++ 在使用这个功能的时候，要求用户的机器上同时安装Visual Studio。Visual C++的逆向工程也需要首先创建一个component，并将该component的language属性设置为VC++。Rational Rose对VC++模型的转换是通过读取VC++ Project File的信息来实现的，用户只需要将对应的project file信息指定给component就可以了。</p>
                        <p>a) 将VC++ Project的信息赋给刚刚创建好的component。</p>
                        <p>①选择该component，点击右键，选择Assign To Project</p>
                        <p><img height=301 src="http://www.uml.org.cn/umltools/images/015.png" width=424><br></p>
                        <p>②在对话框中找到刚刚创建的component，右键点击并选择Properties。</p>
                        <p><img height=413 src="http://www.uml.org.cn/umltools/images/017.png" width=513><br></p>
                        <p>③在下面对话框中选中需要进行转换的Project，点击ok，该component就与需要转换的project关联上了。</p>
                        <p><img height=468 src="http://www.uml.org.cn/umltools/images/019.png" width=403><br><br>　b) 将设置好的component转换成模型图</p>
                        <p>选中设置好的component，点击右键，Update Model&#8230;，将会弹出确认对话框，选中需要转换的class，点击finish就可以了。</p>
                        <p><img height=262 src="http://www.uml.org.cn/umltools/images/021.png" width=376><br></p>
                        <p><img height=428 src="http://www.uml.org.cn/umltools/images/023.png" width=572> </p>
                        <p><a name=3></a><strong>三．如何用Rational Rose进行数据库结构分析</strong></p>
                        <p>利用Rational Rose可以进行关系数据库的数据模型设计并导出DDL语言脚本，相反还可以导入已有的DDL脚本生成数据模型以及连接SQLServer, DB2, Oracle等数据库并导入数据库的schema生成数据模型。</p>
                        <p>下面以SQL Server为例说明一下逆向转换工程的步骤。</p>
                        <p>a) 首先，选择Tools-&gt;Data Modeler-&gt; Reverse Engineer</p>
                        <p><img height=420 src="http://www.uml.org.cn/umltools/images/025.png" width=557><br>　<br>　b) 在进行逆向工程转换的过程中可以选择是从数据库还是DDL脚本进行转换，如果是DDL脚本转换，就直接给定DDL脚本文件位置就可以了。本例子给出的是连接SQLServer数据库将schema导入生成数据模型的过程，所以选中Database，进入下一步。</p>
                        <p><img height=345 src="http://www.uml.org.cn/umltools/images/027.png" width=572><br><br>　c) 填写数据库相关信息</p>
                        <p><img height=373 src="http://www.uml.org.cn/umltools/images/029.png" width=572><br><br>　d) 选中所有需要转换的schema</p>
                        <p><img height=373 src="http://www.uml.org.cn/umltools/images/031.png" width=572><br><br>　e) 选择需要将哪些数据库中的元素导入到数据模型中<br><img height=372 src="http://www.uml.org.cn/umltools/images/033.png" width=572> </p>
                        <p>转换操作会自动在组件图（Component View）中添加数据库组件，并在逻辑图（Logical View）中生成以《Schema》作为命名开头的数据模型。</p>
                        <p><img height=406 src="http://www.uml.org.cn/umltools/images/035.png" width=361><br><br>　打开数据模型，可以看到从数据库中转换过来的各个表和视图。</p>
                        <p><img height=540 src="http://www.uml.org.cn/umltools/images/037.png" width=572><br><br>　从数据模型图中可以看到表的结构以及各个表和视图之间的逻辑关系。</p>
                        <p><a name=4></a><strong>四．如何得到逆向工程的模型图</strong></p>
                        <p>在Rational Rose中，有些模型图是不会自动生成的，很多时候这个工作需要用户手工来完成。也就是说，Rational Rose只负责生成模型，包括模型中的元素、元素的属性以及各个元素之间的关系，但是需要用户做一些额外的工作来得到视图。</p>
                        <p>首先，通过逆向工程，用户已经得到了UML模型或者数据模型的各个组件以及它们之间的关系。 下一步需要在该模型上创建一个视图，它们可以是类图（class diagram，描述系统的静态结构）或者数据模型图（Data model digram，描述关系数据结构）。然后，手动从左边的explorer中将各个元素拖进视图中，在这个过程中，各个元素之间的关联关系会自动在图中表示出来，而不需要用户再做其他工作。</p>
                        <p>例如：生成一个数据模型的数据模型图的过程</p>
                        <p>从左边将数据模型中的数据元素拖到右边的数据模型图中，表CustomerCustomerDemo和表CustomerDemographics之间的依赖关系的菱形箭头是自动生成的，无需手工操作。</p>
                        <p><img height=380 src="http://www.uml.org.cn/umltools/images/039.png" width=572><br></p>
                        <p>一般来说，一个系统中所涉及的数据元素非常多，导致视图很拥挤，排版也非常困难。Rational Rose提供的自动排版功能可以很方便地帮助用户解决这个问题。</p>
                        <p>选择Format-&gt;Layout Diagram，系统会将图中的所有元素用最优方式重新排列，给用户一个清晰的视图。</p>
                        <p><img height=526 src="http://www.uml.org.cn/umltools/images/041.png" width=399><br></p>
                        <p><img height=519 src="http://www.uml.org.cn/umltools/images/043.png" width=772> </p>
                        <p><br>　<a name=5></a><strong>五．总结</strong></p>
                        <p>了解了Rational Rose的逆向工程功能，用户就可以方便地利用这一工具进行大型数据库相关的C++系统的分析和研究了。</p>
                        <p><a name=6></a><strong>注释</strong></p>
                        <p>①IBM Rational Software Architect是一个集成式设计和开发工具，使用户可以用UML模型驱动的开发方式开发出结构清晰的应用程序和服务。</p>
                        <p>②IBM Rational Software Modeler是基于UML2.0的可定制的可视化建模和设计工具，遵循它所提供的工作流程，可以使得系统设计师，系统分析师，设计人员等写出更为清晰的文档，更为有效地进行沟通和设计工作。</p>
                        <p>③UML提供的各种类型的模型描述图</p>
                        <p>用例图(Use Case Diagram)：描述系统提供的一个功能单元，主要目的是帮助开发团队以一种可视化的方式理解系统的功能需求，包括基于基本流程的"角色"（actors，也就是与系统交互的其他实体）关系，以及系统内用例之间的关系。</p>
                        <p>序列图(Sequence Diagram)：显示具体用例（或者是用例的一部分）的详细流程。</p>
                        <p>状态图(Statechart Diagram)：表示某个类所处的不同状态和该类的状态转换信息。</p>
                        <p>活动图(Activity Diagram)：表示在处理某个活动时，两个或者更多类对象之间的过程控制流。</p>
                        <p>类图(Class Diagram)：表示不同的实体（人、事物和数据）如何彼此相关；换句话说，它显示了系统的静态结构。</p>
                        <p>组件图(Component Diagram)：提供系统的物理视图。组件（Component）表示模型代码库、执行库和其它组件的信息。组件是代码的实际模块，组件图主要用户是负责控制代码和编译部署应用程序的人。有些组件是代码库，有些组件是运行组件，如执行文件或动态链接库（DLL）文件。）</p>
                        <p>部署图(Deployment View)：表示该软件系统如何部署到硬件环境中。</p>
                        <p>数据模型图(Data Model Diagram)：描述关系数据结构。</p>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cppblog.com/yearner/aggbug/65350.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yearner/" target="_blank">(Leyn)顽主</a> 2008-10-28 17:36 <a href="http://www.cppblog.com/yearner/archive/2008/10/28/65350.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>COM 学习笔记(2)-引用计数</title><link>http://www.cppblog.com/yearner/archive/2008/10/08/63500.html</link><dc:creator>(Leyn)顽主</dc:creator><author>(Leyn)顽主</author><pubDate>Wed, 08 Oct 2008 13:57:00 GMT</pubDate><guid>http://www.cppblog.com/yearner/archive/2008/10/08/63500.html</guid><wfw:comment>http://www.cppblog.com/yearner/comments/63500.html</wfw:comment><comments>http://www.cppblog.com/yearner/archive/2008/10/08/63500.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yearner/comments/commentRss/63500.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yearner/services/trackbacks/63500.html</trackback:ping><description><![CDATA[引用计数<br>&nbsp;COM接口采用引用计数来控制组件的生命周期。<br>&nbsp;主要用AddRef ,Release 来进行内存管理，当客户从组件中取得一个接口时，此引用计数值将增1。当客户使用完某个接口后，组件的引用计数值将减1。<br>&nbsp;当引用计数值为0时，组件即可将自己从内从中删除。<br>&nbsp;<br>&nbsp;(1)正确使用引用计数的三条简单原则: <br>&nbsp;&nbsp;&nbsp;1)在返回之前调用AddRef.<br>&nbsp;&nbsp;&nbsp;2)使用完接口后调用Release.<br>&nbsp;&nbsp;&nbsp;3)在赋值之后调用AddRef(指针复制).<br>&nbsp;&nbsp;基本原则是避免在使用组件时，组件已被删除。<br>&nbsp;&nbsp;QueryInterface 和CreateInstance中已经调用了AddRef,因此不必再调用它。<br>&nbsp;&nbsp;但两者返回的IUnknow接口和一般接口，用完后都需要调用Release来释放。<br>&nbsp;&nbsp;一般而言，每当复制一个接口的指针时，都应该相应的增加引用计数。<br>&nbsp;&nbsp;&nbsp;IUnknown* pIUnknown=CreateInstance();<br>&nbsp;&nbsp;&nbsp;IX * pIX=NULL;<br>&nbsp;&nbsp;&nbsp;HRESULT hr= pIUnknown-&gt;QueryInterface(IID_IX,(void **)&amp;pIX);<br>&nbsp;&nbsp;&nbsp;pIUnknown-&gt;Release();<br>&nbsp;&nbsp;&nbsp;if(SUCCEEDED(hr))<br>&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;pIX-&gt;Fx();&nbsp;&nbsp;&nbsp;&nbsp;//Fx()为功能函数<br>&nbsp;&nbsp;&nbsp;&nbsp;IX * pIX2=pIX;&nbsp;&nbsp; //复制指针，即增加了一个使用组件(的接口)的可能，<br>&nbsp;&nbsp;&nbsp;&nbsp;pIX2-&gt;AddRef();&nbsp; //所以要增加计数，并在使用完之后release<br>&nbsp;&nbsp;&nbsp;&nbsp;pIX2-&gt;Fx();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;pIX2-&gt;Release(); //<br>&nbsp;&nbsp;&nbsp;&nbsp;pIX-&gt;Release();&nbsp; <br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;//上面代码中，作为复制指针pIX2，其生存周期与pIX相同，即，在pIX Release之前pIX2就已经不再使用了，<br>&nbsp;&nbsp;&nbsp;pIX保证了组件使用安全的前提下，pIX不用AddRef和Release是肯定没问题的。<br>&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;但有时很难判断某些没有加上AddRef和Release的调用是不是正确，是优化还是程序错误。一般用智能来封装<br>&nbsp;&nbsp;&nbsp;引用计数，从而解决这个问题。(智能指针)<br>&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;组件可以对其每一个接口分别维护一个引用计数，也可以对整个组件维护单个的引用计数。原则上选择了为每一个<br>&nbsp;&nbsp;&nbsp;接口单独维护一个引用计数而不是针对整个维护计数，原因，一，使程序调试更方便，二，支持系统资源的按需获取。<br>&nbsp;&nbsp;&nbsp;<br>&nbsp;(2)AddRef\Release 实现<br>&nbsp;&nbsp;&nbsp;主要是改变成员变量m_cRef的数值。AddRef增加其数值，Release减小数值，并在此值为0时将组件删除。<br>&nbsp;&nbsp;&nbsp;简单实现：<br>&nbsp;&nbsp;&nbsp;&nbsp;ULONG _stdcall AddRef()<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return ++m_cRef;//return InterlockIncrement(&amp;m_cRef);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;ULONG _stdcall Release()<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(--m_cRef==0)//if(InterlockDecrement(&amp;m_cRef)==0)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete this;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return m_cRef;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;一般用InterlockIncrement和InterlockDecrement来实现AddRef\Release; 可以确保同一时间只有同一线程来访问成员变量。<br>&nbsp; 3)引用计数的优化原则<br>&nbsp; &nbsp;&nbsp;就像(1)中例子，pIX能保障在pIX2生命周期内，组件肯定会在内存内存留。即，那些生命周期嵌套在引用同一接口的指针的生命周期之内时，外层的已有引用计数，内层的就可以不要了。<br>&nbsp; &nbsp;&nbsp;注意那些生命周期重叠的指针。<br>&nbsp; &nbsp;&nbsp;(1)输出参数原则<br>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;如果接口指针以函数返回值或者以传出参数传出，那么在函数内部，返回参数前调用AddRef.<br>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;例 QueryInterface/CreateInstance;<br>&nbsp; &nbsp;&nbsp;(2)输入参数原则<br>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;若接口指针作为参数传递给一个函数，该函数不修改也将其返回调用者，此时无需调用AddRef\Release例：<br>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void foo(pIX *pIX)<br>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pIX-&gt;Fx();<br>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;因为函数的生命周期嵌套在调用者的生命周期之内的。<br>&nbsp; &nbsp;&nbsp;(3)输入输出参数原则<br>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;对于传递进来的接口指针，必须在给他附另外一个接口指针之前调用release；返回之前，还必须对输出参数指向的新接口调用AddRef;<br>&nbsp; 4)局部变量原则<br>&nbsp; &nbsp;&nbsp;它们是在函数的生存周期内才存在，因此不需要调用AddRef\Release<br>&nbsp; 5)全局变量原则<br>&nbsp; &nbsp;&nbsp;在传递给另一个函数之前，必须调用AddRef.<br>&nbsp; 6)不确定的情况<br>&nbsp; &nbsp;&nbsp;此时需要调用AddRef\Release 以防万一<br><img src ="http://www.cppblog.com/yearner/aggbug/63500.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yearner/" target="_blank">(Leyn)顽主</a> 2008-10-08 21:57 <a href="http://www.cppblog.com/yearner/archive/2008/10/08/63500.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>COM 学习笔记（1）</title><link>http://www.cppblog.com/yearner/archive/2008/07/22/56882.html</link><dc:creator>(Leyn)顽主</dc:creator><author>(Leyn)顽主</author><pubDate>Tue, 22 Jul 2008 10:50:00 GMT</pubDate><guid>http://www.cppblog.com/yearner/archive/2008/07/22/56882.html</guid><wfw:comment>http://www.cppblog.com/yearner/comments/56882.html</wfw:comment><comments>http://www.cppblog.com/yearner/archive/2008/07/22/56882.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yearner/comments/commentRss/56882.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yearner/services/trackbacks/56882.html</trackback:ping><description><![CDATA[<p class="MsoNormal"><span lang="EN-US">COM </span><span style="font-family: 宋体;">学习笔记</span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span lang="EN-US">QueryInterface</span><span style="font-family: 宋体;">函数</span></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-family: 宋体;">主要用于</span><span lang="EN-US">COM</span><span style="font-family: 宋体;">接口的查询。它是</span><span lang="EN-US">COM</span><span style="font-family: 宋体;">接口定义</span><span lang="EN-US">IUnknown</span><span style="font-family: 宋体;">的成员函数，客户可以调用</span><span lang="EN-US">QueryInterface</span><span style="font-family: 宋体;">来决定组件是否支持某个特定的接口。</span></p>
<p class="MsoNormal"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体;">组件</span><span lang="EN-US">COM</span><span style="font-family: 宋体;">接口都是从</span><span lang="EN-US">IUnkonwn</span><span style="font-family: 宋体;">接口继承而来，任何一个接口都可以用</span><span lang="EN-US">IUnknown</span><span style="font-family: 宋体;">的成员</span><span lang="EN-US">QueryInterface</span><span style="font-family: 宋体;">来获取它所支持的其它接口。</span></p>
<p class="MsoNormal" style="text-indent: 21pt;"><span lang="EN-US">1</span><span style="font-family: 宋体;">）定义：</span></p>
<p class="MsoNormal"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>HRESULT
_stdcall QueryInterface(const IID&amp; iid,void ** ppv);</span></p>
<p class="MsoNormal"><span style="font-family: 宋体;">第一个参数十所需接口的标识，是一个接口标识符</span><span lang="EN-US">IID</span><span style="font-family: 宋体;">结构。</span> <span style="font-family: 宋体;">第二个参数存放所请求接口指针的地址。</span></p>
<p class="MsoNormal"><span lang="EN-US"><span>&nbsp;</span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span>2</span><span style="font-family: 宋体;">）使用过程：</span></p>
<p class="MsoNormal"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体;">假定已有一个指向</span><span lang="EN-US">IUnknown</span><span style="font-family: 宋体;">的指针</span><span lang="EN-US">pI</span><span style="font-family: 宋体;">，为知道相应的组件是否支持某个特定的接口，调用</span><span lang="EN-US">QueryInterface</span><span style="font-family: 宋体;">，传给它一个接口标识符。若成功返回，那就是可以使用它返回的指针。</span></p>
<p class="MsoNormal" style="text-indent: 21.75pt;"><span lang="EN-US">Void
foo(IUnknown * pI)</span></p>
<p class="MsoNormal" style="text-indent: 21.75pt;"><span lang="EN-US">{</span></p>
<p class="MsoNormal" style="text-indent: 21.75pt;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>IX *pIX=NULL;</span></p>
<p class="MsoNormal" style="margin-left: 20.25pt; text-indent: 21.75pt;"><span lang="EN-US">HRESULT hr=pI-&gt;QueryInterface(IID_IX,(void **)&amp;pIX);</span></p>
<p class="MsoNormal" style="margin-left: 20.25pt; text-indent: 21.75pt;"><span lang="EN-US">If(SUCCEEDED(hr))</span></p>
<p class="MsoNormal" style="margin-left: 41.25pt; text-indent: 21.75pt;"><span lang="EN-US">pIX-&gt;Fx();</span></p>
<p class="MsoNormal" style="text-indent: 21.75pt;"><span lang="EN-US">}</span></p>
<p class="MsoNormal" style="text-indent: 21.75pt;"><span style="font-family: 宋体;">该函数用于查询</span><span lang="EN-US">pI</span><span style="font-family: 宋体;">是否支持由</span><span lang="EN-US">IID_IX</span><span style="font-family: 宋体;">所标识的接口。</span></p>
<p class="MsoNormal" style="text-indent: 21.75pt;"><span lang="EN-US">IUnknown</span><span style="font-family: 宋体;">的继承不是虚拟基类。</span><span lang="EN-US">COM</span><span style="font-family: 宋体;">接口不能按照虚拟方式继承它。</span></p>
<p class="MsoNormal" style="text-indent: 21.75pt;"><span lang="EN-US">3</span><span style="font-family: 宋体;">）实现：</span></p>
<p class="MsoNormal" style="text-indent: 21.75pt;"><span lang="EN-US">Interface IX</span><span style="font-family: 宋体;">：</span><span lang="EN-US">IUnknown{/**/}</span><span style="font-family: 宋体;">；</span></p>
<p class="MsoNormal" style="text-indent: 21.75pt;"><span lang="EN-US">Interface IY</span><span style="font-family: 宋体;">：</span><span lang="EN-US">IUnknown{/**/}</span><span style="font-family: 宋体;">；</span></p>
<p class="MsoNormal" style="text-indent: 21.75pt;"><span lang="EN-US">Class CA</span><span style="font-family: 宋体;">：</span><span lang="EN-US">public IX,public IY{/**/};</span></p>
<p class="MsoNormal" style="text-indent: 21.75pt;"><span style="font-family: 宋体;">主要通过判断标识符是否为</span><span lang="EN-US">CA</span><span style="font-family: 宋体;">的支持类型，来判断是否为存在在</span><span lang="EN-US">CA</span><span style="font-family: 宋体;">中的</span><span lang="EN-US">COM</span></p>
<p class="MsoNormal" style="text-indent: 21.75pt;"><span lang="EN-US">HRESULT
_stdcall CA:;QueryInterface(const IID &amp;iid,void **ppv)</span></p>
<p class="MsoNormal" style="text-indent: 21.75pt;"><span lang="EN-US">{</span></p>
<p class="MsoNormal" style="text-indent: 21.75pt;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>If(iid==IID_IUnknown)</span></p>
<p class="MsoNormal" style="margin-left: 20.25pt; text-indent: 21.75pt;"><span lang="EN-US">{</span></p>
<p class="MsoNormal" style="margin-left: 20.25pt; text-indent: 21.75pt;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>*ppv=static_cast&lt;IX
*&gt;(this);</span></p>
<p class="MsoNormal" style="margin-left: 20.25pt; text-indent: 21.75pt;"><span lang="EN-US">}</span></p>
<p class="MsoNormal" style="margin-left: 20.25pt; text-indent: 21.75pt;"><span lang="EN-US">Else if(iid==IID_IX)</span></p>
<p class="MsoNormal" style="margin-left: 20.25pt; text-indent: 21.75pt;"><span lang="EN-US">{</span></p>
<p class="MsoNormal" style="margin-left: 20.25pt; text-indent: 21.75pt;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>*ppv=static_cast&lt;IX*&gt;(this);</span></p>
<p class="MsoNormal" style="margin-left: 20.25pt; text-indent: 21.75pt;"><span lang="EN-US">}</span></p>
<p class="MsoNormal" style="margin-left: 20.25pt; text-indent: 21.75pt;"><span lang="EN-US">Else if (iid==IID_IY)</span></p>
<p class="MsoNormal" style="margin-left: 20.25pt; text-indent: 21.75pt;"><span lang="EN-US">{</span></p>
<p class="MsoNormal" style="margin-left: 20.25pt; text-indent: 21.75pt;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>*ppv=static_cast&lt;IY*&gt;(this);</span></p>
<p class="MsoNormal" style="margin-left: 20.25pt; text-indent: 21.75pt;"><span lang="EN-US">}</span></p>
<p class="MsoNormal" style="margin-left: 20.25pt; text-indent: 21.75pt;"><span lang="EN-US">Else </span></p>
<p class="MsoNormal" style="margin-left: 20.25pt; text-indent: 21.75pt;"><span lang="EN-US">{</span></p>
<p class="MsoNormal" style="margin-left: 20.25pt; text-indent: 21.75pt;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>*ppv=NULL;</span></p>
<p class="MsoNormal" style="margin-left: 20.25pt; text-indent: 21.75pt;"><span lang="EN-US">Return E_NOINTERFACE;</span></p>
<p class="MsoNormal" style="margin-left: 20.25pt; text-indent: 21.75pt;"><span lang="EN-US">}</span></p>
<p class="MsoNormal" style="margin-left: 20.25pt; text-indent: 21.75pt;"><span lang="EN-US">Static_cast&lt;IUnknown*&gt;(*ppv)-&gt;AddRef();</span></p>
<p class="MsoNormal" style="margin-left: 20.25pt; text-indent: 21.75pt;"><span lang="EN-US">Return S_OK;</span></p>
<p class="MsoNormal" style="text-indent: 21.75pt;"><span lang="EN-US">}</span></p>
<p class="MsoNormal" style="text-indent: 21.75pt;"><span lang="EN-US">4</span><span style="font-family: 宋体;">）关于其中的类型转换</span></p>
<p class="MsoNormal" style="text-indent: 21.75pt;"><span lang="EN-US"><span>&nbsp;&nbsp; </span></span><span style="font-family: 宋体;">程序中若将</span><span lang="EN-US">this</span><span style="font-family: 宋体;">指针直接转换成</span><span lang="EN-US">IUnknown*</span><span style="font-family: 宋体;">是不明确的。因为存在两个基类接口，需要指明是转换向哪一个接口的</span><span lang="EN-US">IUnknown</span><span style="font-family: 宋体;">。</span></p>
<p class="MsoNormal" style="text-indent: 21.75pt;"><span lang="EN-US">Static_cast&lt;IUnknown*&gt;
(static_cast&lt;IX *&gt;(this))</span></p>
<p class="MsoNormal" style="text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: &quot;times new roman&quot;,&quot;serif&quot;;" lang="EN-US"><!--[if gte vml 1]><v:shapetype id="_x0000_t75"
coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe"
filled="f" stroked="f">
<v:stroke joinstyle="miter"/>
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0"/>
<v:f eqn="sum @0 1 0"/>
<v:f eqn="sum 0 0 @1"/>
<v:f eqn="prod @2 1 2"/>
<v:f eqn="prod @3 21600 pixelWidth"/>
<v:f eqn="prod @3 21600 pixelHeight"/>
<v:f eqn="sum @0 0 1"/>
<v:f eqn="prod @6 1 2"/>
<v:f eqn="prod @7 21600 pixelWidth"/>
<v:f eqn="sum @8 21600 0"/>
<v:f eqn="prod @7 21600 pixelHeight"/>
<v:f eqn="sum @10 21600 0"/>
</v:formulas>
<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
<o:lock v:ext="edit" aspectratio="t"/>
</v:shapetype><v:shape id="_x0000_i1025" type="#_x0000_t75" style="'width:414.75pt;
height:235.5pt'">
<v:imagedata src="file:///C:\DOCUME~1\LEYANG~1.ETH\LOCALS~1\Temp\msohtmlclip1\01\clip_image001.png"
o:title=""/>
</v:shape><![endif]--><!--[if !vml]--><img  src="file:///C:/DOCUME~1/LEYANG~1.ETH/LOCALS~1/Temp/msohtmlclip1/01/clip_image002.jpg" v:shapes="_x0000_i1025" height="314" width="553"><!--[endif]--></span></p>
<p class="MsoNormal" style="text-indent: 21.75pt;"><span style="font-family: 宋体;">在类型转换时，</span><span lang="EN-US">CA</span><span style="font-family: 宋体;">按照顺序存放它的基类接口及其实现，其</span><span lang="EN-US">this</span><span style="font-family: 宋体;">指针可以用</span><span lang="EN-US">IX</span><span style="font-family: 宋体;">代替（地址值相同）。</span></p>
<p class="MsoNormal" style="text-indent: 21.75pt;"><span style="font-family: 宋体;">而</span><span lang="EN-US">IY</span><span style="font-family: 宋体;">则需要</span><span lang="EN-US">CA</span><span style="font-family: 宋体;">的基址加上偏移址。</span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p><img src ="http://www.cppblog.com/yearner/aggbug/56882.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yearner/" target="_blank">(Leyn)顽主</a> 2008-07-22 18:50 <a href="http://www.cppblog.com/yearner/archive/2008/07/22/56882.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>微软面试经历</title><link>http://www.cppblog.com/yearner/archive/2008/05/29/51515.html</link><dc:creator>(Leyn)顽主</dc:creator><author>(Leyn)顽主</author><pubDate>Thu, 29 May 2008 12:36:00 GMT</pubDate><guid>http://www.cppblog.com/yearner/archive/2008/05/29/51515.html</guid><wfw:comment>http://www.cppblog.com/yearner/comments/51515.html</wfw:comment><comments>http://www.cppblog.com/yearner/archive/2008/05/29/51515.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/yearner/comments/commentRss/51515.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yearner/services/trackbacks/51515.html</trackback:ping><description><![CDATA[大概12点多到了西格玛，提前十分钟到了4楼前台，纳闷前台怎么都是男保安呢，可能看惯了前台美女的原因吧。之后一个面试官领着去了个休息间，还很客气的让我随便享用柜台上的水果，感觉比较舒服。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 接着面试官给我发了一沓纸，其中一张是试题，三张钉在一起的是参考资料，主要是范式的说明，其他都是草纸。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 题目不多，总共五道，但都比较典型。前三题是c++基础，4题要求写范式，5题数据库。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 第一题：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 编写字符串转换int型的函数，int atoi(char* str) ，例如输入字符"123"输出int 型数据。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.&nbsp;要求不能使用库函数2.尽可能多地考虑特殊情况<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这道题主要考察了对各种情况考虑是否全面，考虑正负号，非法字符，空格的处理，小数点的处理。尽量一次循环搞定。其中小数点后的非法字符按直接略掉处理。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 第二题：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;编写函数完成字符串的反转 node * reverse(node * head)<br>&nbsp;&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;&nbsp;完成函数 char * strtok(char *s ,char delim) 把字符串从delim处split.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;也比较简单<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;第四题<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; write Regulation expression according to the reference.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1, get all the url from the "<a href="http://www.adomid.com/">www.adomid.com</a>"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. write regulation expression for the following url:&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.microsoft.com/production/id=123&amp;reviewOid=1985&amp;custom=257">http://www.microsoft.com/production/id=123&amp;reviewOid=1985&amp;custom=257</a><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="http://www.microsoft.com/production/id=5343&amp;reviewOid=1431&amp;custom=222"><u><font color="#0000ff">http://www.microsoft.com/production/id=5343&amp;reviewOid=1431</font></u></a><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.microsoft.com/production/id=6576&amp;reviewOid=31614&amp;custom=412">http://www.microsoft.com/production/id=6576&amp;reviewOid=31614&amp;custom=412</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="http://www.microsoft.com/production/id=234&amp;reviewOid=43134&amp;custom=22"><u><font color="#0000ff">http://www.microsoft.com/production/id=234&amp;reviewOid=43134&amp;custom=22</font></u></a><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2write regulation expression&nbsp;for the email address.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这道题有参考，所有的范式表达式都有reference,只需读懂了材料比较简单。<br>&nbsp;&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; design a database for user to borrow or return books from the library.the database should function as follow:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1)the user can borrow several copies of the same&nbsp;book<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2)when the book&nbsp;borrowed&nbsp;, the time should be recorded.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3)the user should register in the system to get the authority for the logining in.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; write sql sentence for the follow question:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1) insert a new record when a book borrowed/returned.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2) get all the&nbsp;users ,which&nbsp;does not return book.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3) get all the books ,which are never borrowed.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3) get the books which have been borrowed for more than 10 times.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;题目就是这样。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;大概作了一个小时，来了个男面试官，收走试卷，让我等。旁边有俩哥们是同来面试的，聊了两句，他俩竟是微软别的部门推来面试的，属于赋闲等待再就业的。正暗自比较与这俩哥们的差距，面试官来了，让我留下，竟把那俩哥们直接拒了，有些庆幸，调整心态。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这个面试官主要针对所答的试题面试，不断指正我试卷上的错误和遗漏点，并且给我时间改正。讨论了一会，其间也问我问题。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 然后他走后，接待我的那个女面试官抱着笔记本过来。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我俩先聊了一下，我借机问了几个问题。然后我就给她讲我的一些经历。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 她给我一份资料，是关于人工对网页进行分类的说明，告诉我看过后可以问问题，然后打开笔记本让我对指定的网页分类。大概是按照网页的功能分成了五类，<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 最后的面试官比较年轻，问了个关于Hash 表的问题，然后看了我的简历，问了个ajax的问题。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 那个hash table&nbsp;问题不是直接问的：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 文件里存在字典列表，找出字母正好相反的单词，比如 dog ,god&nbsp;;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br><br><br><br><br><br><br><br><br><br><img src ="http://www.cppblog.com/yearner/aggbug/51515.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yearner/" target="_blank">(Leyn)顽主</a> 2008-05-29 20:36 <a href="http://www.cppblog.com/yearner/archive/2008/05/29/51515.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 数据结构与算法学习记录：快速排序 (转)</title><link>http://www.cppblog.com/yearner/archive/2008/05/28/51404.html</link><dc:creator>(Leyn)顽主</dc:creator><author>(Leyn)顽主</author><pubDate>Wed, 28 May 2008 08:52:00 GMT</pubDate><guid>http://www.cppblog.com/yearner/archive/2008/05/28/51404.html</guid><wfw:comment>http://www.cppblog.com/yearner/comments/51404.html</wfw:comment><comments>http://www.cppblog.com/yearner/archive/2008/05/28/51404.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/yearner/comments/commentRss/51404.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yearner/services/trackbacks/51404.html</trackback:ping><description><![CDATA[<div class="postTitle">
<a  href="http://www.cnblogs.com/kwklover/archive/2007/02/15/651128.html" id="AjaxHolder_ctl01_TitleUrl" class="postTitle2">数据结构与算法学习记录：快速排序</a>
</div>
<font size="2"><strong>快速排序的基本思想：</strong><br>分治法，即，分解，求解，组合 .<br><br><strong>分解：</strong><br>在
无序区R[low..high]中任选一个记录作为基准(通常选第一个记录，并记为Pivot,其下标为pivotpos),以此为基准划分成两个较小的
子区间R[low,pivotpos - 1]和R[pivotpos + 1 ,
high],并使左边子区间的所有记录均小于等于基准记录,右边子区间的所有记录均大于等于基准记录,基准记录无需参加后续的排序。而划分的关键是要求出
基准记录所在的位置pivotpos.<br><br></font><font size="2"><strong>求解：<br></strong>通过递归调用快速排序对左、右子区间R[low..pivotpos-1]和R[pivotpos+1..high]快速排序<br><br></font><font size="2"><strong>组合：<br></strong>当"求解"步骤中的两个递归调用结束时，其左、右两个子区间已有序。对快速排序而言，"组合"步骤无须做什么，可看作是空操作。<br><br><strong>具体过程：</strong><br>设序列为R[low,high]，从其中选第一个为基准，设为pivot,然后设两个指针i和j,分别指向序列R[low,high]的起始和结束位置上：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1），将i逐渐增大，直到找到大于pivot的关键字为止；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2），将j逐渐减少，直到找到小于等于pivot的关键字为止；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3），如果i&lt;j，即R[i,j]的元素数大于1，则交换R[i]和R[j]；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4），将基准记录pivot放到合适的位置上，即i和j同时指向的位置,则此位置为新的pivotpos。<br><br></font><font size="2"><strong>备注：<br></strong><font style="background-color: #ff0000;">快速排序是不稳定排序</font>,即相同的关键字排序后，相对位置是不确定的。<br><br></font><strong><font size="2">示例代码：<br></font></strong>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><font size="2"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" style="display: none;" id="Code_Closed_Image_141002" onclick="this.style.display='none'; code_closed_text_141002.style.display="'none';" code_open_image_141002.style.display="'inline';" code_open_text_141002.style.display="'inline';"" align="top" height="16" width="11"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" id="Code_Open_Image_141002" style="display: inline;" onclick="this.style.display='none'; code_open_text_141002.style.display="'none';" code_closed_image_141002.style.display="'inline';" code_closed_text_141002.style.display="'inline';"" align="top" height="16" width="11"><span id="Code_Closed_Text_141002" style="border: 1px solid #808080; background-color: #ffffff; display: none;">快速排序代码C#</span></font><span id="Code_Open_Text_141002" style="display: inline;"><br><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><font size="2"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span></font><font size="2"><span style="color: #000000;">&nbsp;DataStructure_QuickSort<br><img  src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" id="Codehighlighter1_45_1589_Open_Image" onclick="this.style.display='none'; codehighlighter1_45_1589_open_text.style.display="'none';" codehighlighter1_45_1589_closed_image.style.display="'inline';" codehighlighter1_45_1589_closed_text.style.display="'inline';"" align="top"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" id="Codehighlighter1_45_1589_Closed_Image" style="display: none;" onclick="this.style.display='none'; codehighlighter1_45_1589_closed_text.style.display="'none';" codehighlighter1_45_1589_open_image.style.display="'inline';" codehighlighter1_45_1589_open_text.style.display="'inline';"" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_45_1589_Closed_Text" style="border: 1px solid #808080; display: none; background-color: #ffffff;"><img  src="http://www.cnblogs.com/Images/dot.gif"></span></font><span id="Codehighlighter1_45_1589_Open_Text"><font size="2"><span style="color: #000000;">{<br><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">划分子区间,计算基准位置</span></font><span style="color: #008000;"><br><font size="2"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"></font></span><font size="2"><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;Partition(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">[]&nbsp;arr&nbsp;,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;nLower&nbsp;,</span><span style="color: #0000ff;">int</span></font><font size="2"><span style="color: #000000;">&nbsp;nUpper)<br><img  src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" style="display: inline;" id="Codehighlighter1_136_1158_Open_Image" onclick="this.style.display='none'; codehighlighter1_136_1158_open_text.style.display="'none';" codehighlighter1_136_1158_closed_image.style.display="'inline';" codehighlighter1_136_1158_closed_text.style.display="'inline';"" align="top"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" id="Codehighlighter1_136_1158_Closed_Image" style="display: none;" onclick="this.style.display='none'; codehighlighter1_136_1158_closed_text.style.display="'none';" codehighlighter1_136_1158_open_image.style.display="'inline';" codehighlighter1_136_1158_open_text.style.display="'inline';"" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_136_1158_Closed_Text" style="border: 1px solid #808080; display: none; background-color: #ffffff;"><img  src="http://www.cnblogs.com/Images/dot.gif"></span></font><span style="display: inline;" id="Codehighlighter1_136_1158_Open_Text"><font size="2"><span style="color: #000000;">{<br><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;pivot&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;arr[nLower]&nbsp;;</span><span style="color: #008000;">//</span><span style="color: #008000;">取第一个记录为基准记录</span></font><span style="color: #008000;"><br><font size="2"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"></font></span><font size="2"><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;nLeft&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;nLower&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">加1，pivot无需和自身做比较</span></font><span style="color: #008000;"><br><font size="2"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"></font></span><font size="2"><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;nRight&nbsp;</span><span style="color: #000000;">=</span></font><font size="2"><span style="color: #000000;">&nbsp;nUpper&nbsp;;<br><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span></font><font size="2"><span style="color: #000000;">&nbsp;temp&nbsp;;<br><img  src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" id="Codehighlighter1_317_912_Open_Image" onclick="this.style.display='none'; codehighlighter1_317_912_open_text.style.display="'none';" codehighlighter1_317_912_closed_image.style.display="'inline';" codehighlighter1_317_912_closed_text.style.display="'inline';"" align="top"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" id="Codehighlighter1_317_912_Closed_Image" style="display: none;" onclick="this.style.display='none'; codehighlighter1_317_912_closed_text.style.display="'none';" codehighlighter1_317_912_open_image.style.display="'inline';" codehighlighter1_317_912_open_text.style.display="'inline';"" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">do</span><span id="Codehighlighter1_317_912_Closed_Text" style="border: 1px solid #808080; display: none; background-color: #ffffff;"><img  src="http://www.cnblogs.com/Images/dot.gif"></span></font><span id="Codehighlighter1_317_912_Open_Text"><font size="2"><span style="color: #000000;">{<br><img  src="http://www.cnblogs.com/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: #0000ff;">while</span><span style="color: #000000;">&nbsp;(nLeft&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;nRight&nbsp;</span><span style="color: #000000;">&amp;&amp;</span><span style="color: #000000;">&nbsp;arr[nLeft]&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;pivot)&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">将nLeft逐渐增大，直到找到大于pivot的下标为止</span></font><span style="color: #008000;"><br><font size="2"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"></font></span><font size="2"><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nLeft</span><span style="color: #000000;">++</span></font><font size="2"><span style="color: #000000;">&nbsp;;<br><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img  src="http://www.cnblogs.com/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: #0000ff;">while</span><span style="color: #000000;">&nbsp;(nLeft&nbsp;</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">&nbsp;nRight&nbsp;</span><span style="color: #000000;">&amp;&amp;</span><span style="color: #000000;">&nbsp;arr[nRight]&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;pivot)&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">从nRight逐渐减少，直到找到小于等于pivot的下标为止</span></font><span style="color: #008000;"><br><font size="2"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"></font></span><font size="2"><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nRight</span><span style="color: #000000;">--</span></font><font size="2"><span style="color: #000000;">&nbsp;;<br><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img  src="http://www.cnblogs.com/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: #008000;">//</span><span style="color: #008000;">R[nLeft,nRight]区间的长度(元素数)大于1时，交换R[nLeft]和R[nRight]</span></font><span style="color: #008000;"><br><font size="2"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"></font></span><font size="2"><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(nLeft&nbsp;</span><span style="color: #000000;">&lt;</span></font><font size="2"><span style="color: #000000;">&nbsp;nRight)<br><img  src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" id="Codehighlighter1_692_898_Open_Image" onclick="this.style.display='none'; codehighlighter1_692_898_open_text.style.display="'none';" codehighlighter1_692_898_closed_image.style.display="'inline';" codehighlighter1_692_898_closed_text.style.display="'inline';"" align="top"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" id="Codehighlighter1_692_898_Closed_Image" style="display: none;" onclick="this.style.display='none'; codehighlighter1_692_898_closed_text.style.display="'none';" codehighlighter1_692_898_open_image.style.display="'inline';" codehighlighter1_692_898_open_text.style.display="'inline';"" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_692_898_Closed_Text" style="border: 1px solid #808080; display: none; background-color: #ffffff;"><img  src="http://www.cnblogs.com/Images/dot.gif"></span></font><span id="Codehighlighter1_692_898_Open_Text"><font size="2"><span style="color: #000000;">{<br><img  src="http://www.cnblogs.com/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;temp&nbsp;</span><span style="color: #000000;">=</span></font><font size="2"><span style="color: #000000;">&nbsp;arr[nLeft]&nbsp;;<br><img  src="http://www.cnblogs.com/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;arr[nLeft]&nbsp;</span><span style="color: #000000;">=</span></font><font size="2"><span style="color: #000000;">&nbsp;arr[nRight]&nbsp;;<br><img  src="http://www.cnblogs.com/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;arr[nRight]&nbsp;</span><span style="color: #000000;">=</span></font><font size="2"><span style="color: #000000;">&nbsp;temp&nbsp;;<br><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img  src="http://www.cnblogs.com/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;nLeft</span><span style="color: #000000;">++</span></font><font size="2"><span style="color: #000000;">;<br><img  src="http://www.cnblogs.com/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;nRight</span><span style="color: #000000;">--</span></font><span style="color: #000000;"><font size="2">;<br><img  src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</font></span></span><span style="color: #000000;"><br><font size="2"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</font></span></span><font size="2"><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;(nLeft&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;nRight);&nbsp;</span><span style="color: #008000;">//</span></font><font size="2"><span style="color: #008000;">当nLeft&nbsp;==&nbsp;nRight的时候停止循环<br><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">把基准记录pivot放到正确位置，即nLeft和nRight同时指向的位置</span></font><span style="color: #008000;"><br><font size="2"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"></font></span><font size="2"><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp&nbsp;</span><span style="color: #000000;">=</span></font><font size="2"><span style="color: #000000;">&nbsp;arr[nLower];<br><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arr[nLower]&nbsp;</span><span style="color: #000000;">=</span></font><font size="2"><span style="color: #000000;">&nbsp;arr[nRight];<br><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arr[nRight]&nbsp;</span><span style="color: #000000;">=</span></font><font size="2"><span style="color: #000000;">&nbsp;temp&nbsp;;<br><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span></font><span style="color: #000000;"><font size="2">&nbsp;nRight&nbsp;;<br><img  src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</font></span></span><span style="color: #000000;"><br><font size="2"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"><br><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font></span><font size="2"><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;QuickSort(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">[]&nbsp;arr,&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;nLower,&nbsp;</span><span style="color: #0000ff;">int</span></font><font size="2"><span style="color: #000000;">&nbsp;nUpper)<br><img  src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" id="Codehighlighter1_1234_1583_Open_Image" onclick="this.style.display='none'; codehighlighter1_1234_1583_open_text.style.display="'none';" codehighlighter1_1234_1583_closed_image.style.display="'inline';" codehighlighter1_1234_1583_closed_text.style.display="'inline';"" align="top"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" id="Codehighlighter1_1234_1583_Closed_Image" style="display: none;" onclick="this.style.display='none'; codehighlighter1_1234_1583_closed_text.style.display="'none';" codehighlighter1_1234_1583_open_image.style.display="'inline';" codehighlighter1_1234_1583_open_text.style.display="'inline';"" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_1234_1583_Closed_Text" style="border: 1px solid #808080; display: none; background-color: #ffffff;"><img  src="http://www.cnblogs.com/Images/dot.gif"></span></font><span id="Codehighlighter1_1234_1583_Open_Text"><font size="2"><span style="color: #000000;">{<br><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;pivotpos;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">基准下标</span></font><span style="color: #008000;"><br><font size="2"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"></font></span><font size="2"><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(nLower&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;nUpper)&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">仅当区间范围长度大于1时才须排序</span></font><span style="color: #008000;"><br><font size="2"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" id="Codehighlighter1_1333_1573_Open_Image" onclick="this.style.display='none'; codehighlighter1_1333_1573_open_text.style.display="'none';" codehighlighter1_1333_1573_closed_image.style.display="'inline';" codehighlighter1_1333_1573_closed_text.style.display="'inline';"" align="top"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" id="Codehighlighter1_1333_1573_Closed_Image" style="display: none;" onclick="this.style.display='none'; codehighlighter1_1333_1573_closed_text.style.display="'none';" codehighlighter1_1333_1573_open_image.style.display="'inline';" codehighlighter1_1333_1573_open_text.style.display="'inline';"" align="top"></font></span><font size="2"><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_1333_1573_Closed_Text" style="border: 1px solid #808080; display: none; background-color: #ffffff;"><img  src="http://www.cnblogs.com/Images/dot.gif"></span></font><span id="Codehighlighter1_1333_1573_Open_Text"><font size="2"><span style="color: #000000;">{<br><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pivotpos&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Partition(arr,&nbsp;nLower,&nbsp;nUpper);</span><span style="color: #008000;">//</span><span style="color: #008000;">划分子区间,知道基准下标(QuickSort的关键)</span></font><span style="color: #008000;"><br><font size="2"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"></font></span><font size="2"><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;QuickSort(arr,&nbsp;nLower,&nbsp;pivotpos&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">对左区间递归排序&nbsp;</span></font><span style="color: #008000;"><br><font size="2"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"></font></span><font size="2"><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;QuickSort(arr,&nbsp;pivotpos&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">,&nbsp;nUpper);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">对右区间递归排序</span></font><span style="color: #008000;"><br><font size="2"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"></font></span><span style="color: #000000;"><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</font></span></span><span style="color: #000000;"><br><font size="2"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</font></span></span><span style="color: #000000;"><br><font size="2"><img  src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;}</font></span></span></span></div><img src ="http://www.cppblog.com/yearner/aggbug/51404.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yearner/" target="_blank">(Leyn)顽主</a> 2008-05-28 16:52 <a href="http://www.cppblog.com/yearner/archive/2008/05/28/51404.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ 学习（二 ）多态性（积累中）</title><link>http://www.cppblog.com/yearner/archive/2008/05/20/50591.html</link><dc:creator>(Leyn)顽主</dc:creator><author>(Leyn)顽主</author><pubDate>Tue, 20 May 2008 15:37:00 GMT</pubDate><guid>http://www.cppblog.com/yearner/archive/2008/05/20/50591.html</guid><wfw:comment>http://www.cppblog.com/yearner/comments/50591.html</wfw:comment><comments>http://www.cppblog.com/yearner/archive/2008/05/20/50591.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/yearner/comments/commentRss/50591.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yearner/services/trackbacks/50591.html</trackback:ping><description><![CDATA[　　多态性，在ｃ＋＋中指具有不同功能的函数可以用同一个函数名，即可以用同一个函数名调用不同内容的函数。向不同的对象发送用一个消息，不同的对象在接收同样的消息，会产生不同的行为（方法）。<br>　　从系统实现角度来看。多态性分为两类：静态多态性和动态多态性。<br>　　静态多态性：在程序编译时系统就能决定调用哪个函数，因此静态函数有称编译时的多态性(实质上是通过函数的重载实现)。例如：函数的重载和运算符重载实现.<br>　　动态多态性：运行过程中才动态地确定操作指针所指的对象。主要通过虚函数和重写来实现。<br> <img src ="http://www.cppblog.com/yearner/aggbug/50591.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yearner/" target="_blank">(Leyn)顽主</a> 2008-05-20 23:37 <a href="http://www.cppblog.com/yearner/archive/2008/05/20/50591.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++ 学习（一）类型转换</title><link>http://www.cppblog.com/yearner/archive/2008/05/20/50457.html</link><dc:creator>(Leyn)顽主</dc:creator><author>(Leyn)顽主</author><pubDate>Tue, 20 May 2008 11:12:00 GMT</pubDate><guid>http://www.cppblog.com/yearner/archive/2008/05/20/50457.html</guid><wfw:comment>http://www.cppblog.com/yearner/comments/50457.html</wfw:comment><comments>http://www.cppblog.com/yearner/archive/2008/05/20/50457.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/yearner/comments/commentRss/50457.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yearner/services/trackbacks/50457.html</trackback:ping><description><![CDATA[1.类型转换按方式分为隐式转换和显式转换。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 隐式转换：由编译器自动完成，无需用户干预。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 显式转换：采用一定的形式进行转换：类型名（数据） / C中（类型名）数据<br>2.关于转换构造函数<br>&nbsp; &nbsp; &nbsp; &nbsp; 构造函数的一种，主要用于类型转换，格式严格规定为单参数构造函数。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 例：Complex类<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Complex(double r){Real=r;imag=0;}&nbsp; int(double r);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Complex a;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a=2.4; 相当于a=Complex(2.4);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 编译器如果发现语法有问题，会检查是否存在转换构造函数，有，则隐式转换。<br>&nbsp;3.关于类型转换函数<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 转换构造函数是将一种数据类型转换成类对象。如果编译器发现需要将类转换成某种数据类型，那该怎么办？<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 类型转换函数的一般形式：operator 类型名（）{转换函数的实现}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 没有函数类型，没有参数。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 例：<br>&nbsp;&nbsp;&nbsp;&nbsp; #include&lt;iostream&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp; using namespace std;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class Complex<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public :<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Complex(){real=0;imag=0;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Complex(double r,double i){real=r;imag=i;}<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; operator double(){return real;}<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; private:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; double real;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; double imag; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int main()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Complex c1(3,4),c2(5,-10),c3;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; double d;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d=2.5+c1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout&lt;&lt;d&lt;&lt;end1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return0;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp; d=2.5+c1;<br>&nbsp;&nbsp;&nbsp;&nbsp; 由于类成员没有对运算符+重载，所以2.5与c1无法直接向加。编译器发现存在类型转换函数，故将 隐式调用double(), c1转换为 double 型3，并将该结果存放在临时变量里。运算d=2.5+3得到结果。<br>　若主函数中有c3=2.5+c1;如果没有运算符＋的重载，编译器会出错。当　运算符重载函数作为类成员出现时，编译器会理解为c3=2.5.operator +(c1);由于2.5非complex类，这种解析编译器也会出错。对于c3=c1+2.5的格式，编译器会正确处理。<br>　这种情况使用户不能方便的使用交换率，为了改变这一不便，需要将重载函数作为友元函数而不是类成员函数。(双目运算符的重载一般都采用友元函数的方式)<br>　friend Complex operator +(Complex c1,complex c2);<br>&nbsp;&nbsp;&nbsp; 在函数体外定义：<br>　Complex operator +(Complex c1,complex c2);<br>　　{return Complex (c1.real +c2.real,c1.imag+c2.imag);}<br>这样，对于c3=2.5+c1;（需要增加转换构造函数）编译器在遇到＋号时，会搜索＋两端的数据并引用友元的运算符重载函数，其形式变为：c3=operator+(2.5,c1); 而参数定义都是Complex对象，因此，隐式调用转换构造函数，形式变为：c3=operator+(Complex (2.5),c1); <br>&nbsp;&nbsp;&nbsp;&nbsp;  <br><br>&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br><br>  <img src ="http://www.cppblog.com/yearner/aggbug/50457.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yearner/" target="_blank">(Leyn)顽主</a> 2008-05-20 19:12 <a href="http://www.cppblog.com/yearner/archive/2008/05/20/50457.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>有关内存的思考题(积累中）</title><link>http://www.cppblog.com/yearner/archive/2008/05/16/50112.html</link><dc:creator>(Leyn)顽主</dc:creator><author>(Leyn)顽主</author><pubDate>Fri, 16 May 2008 15:59:00 GMT</pubDate><guid>http://www.cppblog.com/yearner/archive/2008/05/16/50112.html</guid><wfw:comment>http://www.cppblog.com/yearner/comments/50112.html</wfw:comment><comments>http://www.cppblog.com/yearner/archive/2008/05/16/50112.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/yearner/comments/commentRss/50112.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yearner/services/trackbacks/50112.html</trackback:ping><description><![CDATA[<p style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;"></span><span style="font-family: 宋体;"><br></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">void GetMemory(char *p)</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">{</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">p = (char *)malloc(100);</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">}</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">void Test(void)</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">{</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">char *str = NULL;</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">GetMemory(str);</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">strcpy(str, "hello world");</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">printf(str);</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">}</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;">请问运行</span><span lang="EN-US"><font face="Times New Roman">Test </font></span><span style="font-family: 宋体;">函数会有什么样的结果？</span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;">答：程序崩溃。</span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;">因为</span><span lang="EN-US"><font face="Times New Roman">GetMemory </font></span><span style="font-family: 宋体;">并不能传递动态内存，</span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">Test </font></span><span style="font-family: 宋体;">函数中的</span><span lang="EN-US"><font face="Times New Roman"> str </font></span><span style="font-family: 宋体;">一直都是</span><span lang="EN-US"><font face="Times New Roman"> NULL</font></span><span style="font-family: 宋体;">。</span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">strcpy(str, "hello world");</font></span><span style="font-family: 宋体;">将使程序崩</span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;">溃。</span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">char *GetMemory(void)</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">{</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">char p[] = "hello world";</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">return p;</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">}</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">void Test(void)</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">{</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">char *str = NULL;</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">str = GetMemory();</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">printf(str);</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">}</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;">请问运行</span><span lang="EN-US"><font face="Times New Roman">Test </font></span><span style="font-family: 宋体;">函数会有什么样的结果？</span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;">答：可能是乱码。</span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;">因为</span><span lang="EN-US"><font face="Times New Roman">GetMemory </font></span><span style="font-family: 宋体;">返回的是指向&#8220;栈内存&#8221;</span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;">的指针，该指针的地址不是</span><span lang="EN-US"><font face="Times New Roman"> NULL</font></span><span style="font-family: 宋体;">，但其原</span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;">现的内容已经被清除，新内容不可知。</span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">void GetMemory2(char **p, int num)</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">{</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">*p = (char *)malloc(num);</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">}</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">void Test(void)</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">{</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">char *str = NULL;</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">GetMemory(&amp;str, 100);</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">strcpy(str, "hello");</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">printf(str);</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">}</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;">请问运行</span><span lang="EN-US"><font face="Times New Roman">Test </font></span><span style="font-family: 宋体;">函数会有什么样的结果？</span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;">答：</span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;">（</span><span lang="EN-US"><font face="Times New Roman">1</font></span><span style="font-family: 宋体;">）能够输出</span><span lang="EN-US"><font face="Times New Roman">hello</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;">（</span><span lang="EN-US"><font face="Times New Roman">2</font></span><span style="font-family: 宋体;">）内存泄漏</span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">void Test(void)</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">{</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">char *str = (char *) malloc(100);</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">strcpy(str, &#8220;hello&#8221;);</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">free(str);</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">if(str != NULL)</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">{</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">strcpy(str, &#8220;world&#8221;);</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">printf(str);</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">}</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">}</font></span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;">请问运行</span><span lang="EN-US"><font face="Times New Roman">Test </font></span><span style="font-family: 宋体;">函数会有什么样的结果？</span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;">答：篡改动态内存区的内容，后果难以预</span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;">料，非常危险。</span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;">因为</span><span lang="EN-US"><font face="Times New Roman">free(str);</font></span><span style="font-family: 宋体;">之后，</span><span lang="EN-US"><font face="Times New Roman">str </font></span><span style="font-family: 宋体;">成为野指针，</span></p>
<p style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><font face="Times New Roman">if(str != NULL)</font></span><span style="font-family: 宋体;">语句不起作用。</span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;">2.关于内存泄露</span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;">&nbsp; </span>在计算机科学中，内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并非指内存在物理上的消失，而是应用程序分配某段内存后，
由于设计错误，失去了对该段内存的控制，因而造成了内存的浪费。内存泄漏与许多其他问题有着相似的症状，并且通常情况下只能由那些可以获得程序源代码的程
序员才可以分析出来。然而，有不少人习惯于把任何不需要的内存使用的增加描述为内存泄漏，即使严格意义上来说这是不准确的。<br>
&nbsp; &nbsp;&nbsp; &nbsp;
一般我们常说的内存泄漏是指堆内存的泄漏。堆内存是指程序从堆中分配的，大小任意的（内存块的大小可以在程序运行期决定），使用完后必须显示释放的内存。
应用程序一般使用malloc，realloc，new等函数从堆中分配到一块内存，使用完后，程序必须负责相应的调用free或delete释放该内存
块，否则，这块内存就不能被再次使用，我们就说这块内存泄漏了。</p><img src ="http://www.cppblog.com/yearner/aggbug/50112.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yearner/" target="_blank">(Leyn)顽主</a> 2008-05-16 23:59 <a href="http://www.cppblog.com/yearner/archive/2008/05/16/50112.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据类型转换：static_cast,const_cast等用法(转载）</title><link>http://www.cppblog.com/yearner/archive/2008/05/16/50077.html</link><dc:creator>(Leyn)顽主</dc:creator><author>(Leyn)顽主</author><pubDate>Fri, 16 May 2008 11:01:00 GMT</pubDate><guid>http://www.cppblog.com/yearner/archive/2008/05/16/50077.html</guid><wfw:comment>http://www.cppblog.com/yearner/comments/50077.html</wfw:comment><comments>http://www.cppblog.com/yearner/archive/2008/05/16/50077.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/yearner/comments/commentRss/50077.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yearner/services/trackbacks/50077.html</trackback:ping><description><![CDATA[<div class="postTitle"><a  href="http://www.cnblogs.com/gunboat/archive/2007/04/13/711813.html" class="postTitle2" id="viewpost1_TitleUrl"><font color="#000000"><br></font></a> </div>
* C++提供了四种新的类型强制： <br><br>static_cast <br>const_cast <br>reinterpret_cast <br>dynamic_cast <br><br>1)staic_cast静态强制； <br><br>不能在无关的指针之间进行static类型强制 <br>class CAnimal <br>{ <br>//... <br>public: <br>CAnimal(){} <br>}; <br><br>class CGiraffe:public CAnimal <br>{ <br>//... <br>public: <br>CGiraffe(){} <br>}; <br><br>int main(void) <br>{ <br>CAnimal an; <br>CGiraffe jean; <br><br>an = static_cast&lt;CAnimal&gt;(jean);//将对象jean强制成CAnimal类型 <br>return 0; <br>} <br><br>2、const_cast类型强制 <br><br>const_cast类型强制将一个const变量变成一个非const的等价形式 <br>int main() <br>{ <br>const int j = 99; <br>int * k; <br><br>k = const_cast&lt;int *&gt;(&amp;j);//解除const <br>return 0; <br>} <br><br>3、reinterpret_cast运算符 <br><br>reinterpret_cast运算符用来将一个类型指针转变为另一种类型的指针，也用在将整开型量转为指针，或将指针转为整型量上； <br>int main() <br>{ <br>int j = 10; <br>int * ptr = &amp;j; <br>char * cptr; <br><br>cptr = reinterpret_cast&lt;char *&gt;(ptr);//将int指针类型转变为char的指针类型 <br><br>return 0; <br>} <br><br>4、dynamic_cast运算符 <br><br>dynamic_cast的主要目的是： <br><br>1）它返回派生类对象的地址； <br>2）它测试基类指针是否指向下一尖括号&lt;&gt;中所指定类型的对象 <br><br>dynamic_cast是一个运行时类型信息，dynamic_cast运算符将指向派生对象的基类部分的基类指针转变为指向派生对象的派生类指针，dynamic_cast必须严格地指定与派生对象相同的类，或者它返回NULL指针; <br>class CAnimal <br>{ <br>//... <br>}; <br>class CGiraffe:public CAnimal <br>{ <br>//... <br>}; <br>class CGoat:public CAnimal <br>{ <br>//... <br>}; <br><br>int main() <br>{ <br>CGiraffe gene; <br>CAnimal * aptr = &amp;gene; <br>CGiraffe * ptr1,* ptr2; <br><br>ptr1 = dynamic_cast&lt;CGiraffe *&gt;(aptr); <br>ptr2 = dynamic_cast&lt;CGoat *&gt;(aptr); //return NULL <br><br>return 0; <br>}&nbsp; <br><img src ="http://www.cppblog.com/yearner/aggbug/50077.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yearner/" target="_blank">(Leyn)顽主</a> 2008-05-16 19:01 <a href="http://www.cppblog.com/yearner/archive/2008/05/16/50077.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++面试题</title><link>http://www.cppblog.com/yearner/archive/2006/09/10/12208.html</link><dc:creator>(Leyn)顽主</dc:creator><author>(Leyn)顽主</author><pubDate>Sun, 10 Sep 2006 01:11:00 GMT</pubDate><guid>http://www.cppblog.com/yearner/archive/2006/09/10/12208.html</guid><wfw:comment>http://www.cppblog.com/yearner/comments/12208.html</wfw:comment><comments>http://www.cppblog.com/yearner/archive/2006/09/10/12208.html#Feedback</comments><slash:comments>17</slash:comments><wfw:commentRss>http://www.cppblog.com/yearner/comments/commentRss/12208.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/yearner/services/trackbacks/12208.html</trackback:ping><description><![CDATA[<p id="fp">1.是不是一个父类写了一个virtual&nbsp;函数，如果子类覆盖它的函数不加virtual&nbsp;,也能实现多态?<br><br>&nbsp;<br><br>virtual修饰符会被隐形继承的。<br><br>private&nbsp;也被集成，只事派生类没有访问权限而已<br><br>virtual可加可不加<br><br>子类的空间里有父类的所有变量(static除外)<br><br>同一个函数只存在一个实体(inline除外)<br><br>子类覆盖它的函数不加virtual&nbsp;,也能实现多态。<br><br>在子类的空间里，有父类的私有变量。私有变量不能直接访问。<br><br><br>--------------------------------------------------------------------------<br>2.输入一个字符串，将其逆序后输出。（使用C++，不建议用伪码）<br><br>#include&nbsp;&lt;iostream&gt;<br>using&nbsp;namespace&nbsp;std;<br><br><br>void&nbsp;main()<br>{<br>&nbsp;&nbsp;char&nbsp;a[50];memset(a,0,sizeof(a));<br>&nbsp;&nbsp;int&nbsp;i=0,j;<br>&nbsp;&nbsp;char&nbsp;t;<br>&nbsp;&nbsp;cin.getline(a,50,'\n');<br>&nbsp;&nbsp;for(i=0,j=strlen(a)-1;i&lt;strlen(a)/2;i++,j--)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;t=a[i];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a[i]=a[j];<br>&nbsp;&nbsp;&nbsp;a[j]=t;<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;cout&lt;&lt;a&lt;&lt;endl;&nbsp;&nbsp;<br>}<br><br>//第二种<br><br>string&nbsp;str;<br>cin&gt;&gt;str;<br>str.replace;<br>cout&lt;&lt;str;<br><br><br>--------------------------------------------------------------------------<br>3.请简单描述Windows内存管理的方法。<br><br>内存管理是操作系统中的重要部分，两三句话恐怕谁也说不清楚吧～～<br>我先说个大概，希望能够抛砖引玉吧<br><br>当程序运行时需要从内存中读出这段程序的代码。代码的位置必须在物理内存中才能被运行，由于现在的操作系统中有非常多的程序运行着，内存中不能够完全放下，所以引出了虚拟内存的概念。把哪些不常用的程序片断就放入虚拟内存，当需要用到它的时候在load入主存（物理内存）中。这个就是内存管理所要做的事。内存管理还有另外一件事需要做：计算程序片段在主存中的物理位置，以便CPU调度。<br><br>内存管理有块式管理，页式管理，段式和段页式管理。现在常用段页式管理<br><br>块式管理：把主存分为一大块、一大块的，当所需的程序片断不在主存时就分配一块主存空间，把程&nbsp;序片断load入主存，就算所需的程序片度只有几个字节也只能把这一块分配给它。这样会造成很大的浪费，平均浪费了50％的内存空间，但时易于管理。<br><br>页式管理：把主存分为一页一页的，每一页的空间要比一块一块的空间小很多，显然这种方法的空间利用率要比块式管理高很多。<br><br>段式管理：把主存分为一段一段的，每一段的空间又要比一页一页的空间小很多，这种方法在空间利用率上又比页式管理高很多，但是也有另外一个缺点。一个程序片断可能会被分为几十段，这样很多时间就会被浪费在计算每一段的物理地址上（计算机最耗时间的大家都知道是I/O吧）。<br><br>段页式管理：结合了段式管理和页式管理的优点。把主存分为若干页，每一页又分为若干段。好处就很明显，不用我多说了吧。<br><br>各种内存管理都有它自己的方法来计算出程序片断在主存中的物理地址，其实都很相似。<br><br>这只是一个大概而已，不足以说明内存管理的皮毛。无论哪一本操作系统书上都有详细的讲解<br><br><br>--------------------------------------------------------------------------<br>4.<br>#include&nbsp;"stdafx.h"<br>#define&nbsp;SQR(X)&nbsp;X*X<br><br>int&nbsp;main(int&nbsp;argc,&nbsp;char*&nbsp;argv[])<br>{<br>&nbsp;int&nbsp;a&nbsp;=&nbsp;10;<br>&nbsp;int&nbsp;k&nbsp;=&nbsp;2;<br>&nbsp;int&nbsp;m&nbsp;=&nbsp;1;<br><br>&nbsp;a&nbsp;/=&nbsp;SQR(k+m)/SQR(k+m);&nbsp;<br>&nbsp;printf("%d\n",a);&nbsp;<br><br>&nbsp;return&nbsp;0;<br>}<br>这道题目的结果是什么啊?<br><br>define&nbsp;只是定义而已，在编择时只是简单代换X*X而已，并不经过算术法则的<br><br>a&nbsp;/=&nbsp;(k+m)*(k+m)/(k+m)*(k+m);</p>
<p id="fp">a/=k+m*k+m/k+m*k+m<br>=&gt;a&nbsp;/= 2+1*2+1/2+1*2+1<br>=&gt;a&nbsp;=&nbsp;a/7;<br>=&gt;a&nbsp;= 1;<br><br>--------------------------------------------------------------------------<br>5.<br>const&nbsp;符号常量；<br>(1)const&nbsp;char&nbsp;*p<br>(2)char&nbsp;const&nbsp;*p<br>(3)char&nbsp;*&nbsp;const&nbsp;p<br>说明上面三种描述的区别；<br><br><br>如果const位于星号的左侧，则const就是用来修饰指针所指向的变量，即指针指向为常量；<br>如果const位于星号的右侧，const就是修饰指针本身，即指针本身是常量。<br><br>(1)const&nbsp;char&nbsp;*p<br><br>一个指向char类型的const对象指针，p不是常量,我们可以修改p的值，使其指向不同的char，但是不能改变它指向非char对象，如：<br>const&nbsp;char&nbsp;*p;<br>char&nbsp;c1='a';<br>char&nbsp;c2='b';<br>p=&amp;c1;//ok<br>p=&amp;c2;//ok<br>*p=c1;//error<br><br>(2)char&nbsp;const&nbsp;*p<br>(3)char&nbsp;*&nbsp;const&nbsp;p<br><br>这两个好象是一样的，此时*p可以修改，而p不能修改。<br><br>(4)const&nbsp;char&nbsp;*&nbsp;const&nbsp;p<br>这种是地址及指向对象都不能修改。<br><br>--------------------------------------------------------------------------<br>6.下面是C语言中两种if语句判断方式。请问哪种写法更好？为什么？<br>&nbsp;int&nbsp;n;<br>&nbsp;if&nbsp;(n&nbsp;==&nbsp;10)&nbsp;//&nbsp;第一种判断方式<br>&nbsp;if&nbsp;(10&nbsp;==&nbsp;n)&nbsp;//&nbsp;第二种判断方式<br><br>如果少了个=号,编译时就会报错,减少了出错的可能行,可以检测出是否少了=<br><br>--------------------------------------------------------------------------<br>7.下面的代码有什么问题？<br>void&nbsp;DoSomeThing(...)<br>{<br>&nbsp;char*&nbsp;p;<br>&nbsp;...<br>&nbsp;p&nbsp;=&nbsp;malloc(1024);&nbsp;&nbsp;//&nbsp;分配1K的空间<br>&nbsp;if&nbsp;(NULL&nbsp;==&nbsp;p)<br>&nbsp;&nbsp;return;<br>&nbsp;...<br>&nbsp;p&nbsp;=&nbsp;realloc(p,&nbsp;2048);&nbsp;//&nbsp;空间不够，重新分配到2K<br>&nbsp;if&nbsp;(NULL&nbsp;==&nbsp;p)<br>&nbsp;&nbsp;return;<br>&nbsp;...<br>}<br><br>A:<br>p&nbsp;=&nbsp;malloc(1024);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;应该写成：&nbsp;p&nbsp;=&nbsp;(char&nbsp;*)&nbsp;malloc(1024);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;没有释放p的空间，造成内存泄漏。<br><br><br>--------------------------------------------------------------------------<br>8.下面的代码有什么问题？并请给出正确的写法。<br>void&nbsp;DoSomeThing(char*&nbsp;p)<br>{<br>&nbsp;char&nbsp;str[16];<br>&nbsp;int&nbsp;n;<br>&nbsp;assert(NULL&nbsp;!=&nbsp;p);<br>&nbsp;sscanf(p,&nbsp;"%s%d",&nbsp;str,&nbsp;n);<br>&nbsp;if&nbsp;(0&nbsp;==&nbsp;strcmp(str,&nbsp;"something"))<br>&nbsp;{<br>&nbsp;&nbsp;...<br>&nbsp;}<br>}<br><br>A:<br>sscanf(p,&nbsp;"%s%d",&nbsp;str,&nbsp;n);&nbsp;&nbsp;&nbsp;这句该写成：&nbsp;sscanf(p,&nbsp;"%s%d",&nbsp;str,&nbsp;&amp;n);<br><br>--------------------------------------------------------------------------<br>9.下面代码有什么错误?<br>Void&nbsp;test1()&nbsp;<br>{&nbsp;<br>&nbsp;char&nbsp;string[10];&nbsp;<br>&nbsp;char&nbsp;*str1="0123456789";<br>&nbsp;strcpy(string,&nbsp;str1);&nbsp;<br>}&nbsp;<br><br>数组越界<br><br>--------------------------------------------------------------------------<br>10.下面代码有什么问题?<br>Void&nbsp;test2()&nbsp;<br>{&nbsp;<br>&nbsp;&nbsp;char&nbsp;string[10],&nbsp;str1[10];&nbsp;<br>&nbsp;&nbsp;for(i=0;&nbsp;i&lt;10;i++)&nbsp;<br>&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str1[i]&nbsp;='a';&nbsp;<br>&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;strcpy(string,&nbsp;str1);&nbsp;<br>}&nbsp;<br><br>数组越界<br><br>--------------------------------------------------------------------------<br>11.下面代码有什么问题?<br>Void&nbsp;test3(char*&nbsp;str1)&nbsp;<br>{&nbsp;<br>&nbsp;&nbsp;char&nbsp;string[10];&nbsp;<br>&nbsp;&nbsp;if(strlen(str1)&lt;=10)&nbsp;<br>&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;strcpy(string,&nbsp;str1);&nbsp;<br>&nbsp;&nbsp;}&nbsp;<br>}&nbsp;<br><br>==数组越界<br>==strcpy拷贝的结束标志是查找字符串中的\0&nbsp;因此如果字符串中没有遇到\0的话&nbsp;会一直复制，直到遇到\0,上面的123都因此产生越界的情况<br>&nbsp;<br>建议使用&nbsp;strncpy&nbsp;和&nbsp;memcpy<br><br>--------------------------------------------------------------------------<br>12.下面代码有什么问题?<br><br>#define&nbsp;MAX_SRM&nbsp;256&nbsp;<br><br>DSN&nbsp;get_SRM_no()&nbsp;<br>{&nbsp;<br>&nbsp;&nbsp;static&nbsp;int&nbsp;SRM_no;&nbsp;//是不是这里没赋初值？<br>&nbsp;&nbsp;int&nbsp;I;&nbsp;<br>&nbsp;&nbsp;for(I=0;I&lt;MAX_SRM;I++,SRM_no++)&nbsp;<br>&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;SRM_no&nbsp;%=&nbsp;MAX_SRM;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;if(MY_SRM.state==IDLE)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;}&nbsp;<br>&nbsp;&nbsp;if(I&gt;=MAX_SRM)&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;(NULL_SRM);&nbsp;<br>&nbsp;&nbsp;else&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;SRM_no;&nbsp;<br>}&nbsp;<br><br>系统会初始化static&nbsp;int变量为0,但该值会一直保存,所谓的不可重入...<br><br>--------------------------------------------------------------------------<br>13.写出运行结果:<br>{//&nbsp;test1<br>&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;str[]&nbsp;=&nbsp;"world";&nbsp;cout&nbsp;&lt;&lt;&nbsp;sizeof(str)&nbsp;&lt;&lt;&nbsp;":&nbsp;";<br>&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;*p&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;str;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;&lt;&lt;&nbsp;sizeof(p)&nbsp;&lt;&lt;&nbsp;":&nbsp;";<br>&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;i&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&nbsp;10;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&nbsp;&lt;&lt;&nbsp;sizeof(i)&nbsp;&lt;&lt;&nbsp;":&nbsp;";<br>&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;*pp&nbsp;&nbsp;&nbsp;=&nbsp;malloc(10);&nbsp;&nbsp;cout&nbsp;&lt;&lt;&nbsp;sizeof(p)&nbsp;&lt;&lt;&nbsp;endl;<br>}<br><br>6：4：1：4<br><br>--------------------------------------------------------------------------<br>14.写出运行结果:<br>{//&nbsp;test2<br>&nbsp;&nbsp;&nbsp;&nbsp;union&nbsp;V&nbsp;{<br>&nbsp;struct&nbsp;X&nbsp;{<br>&nbsp;&nbsp;unsigned&nbsp;char&nbsp;s1:2;<br>&nbsp;&nbsp;unsigned&nbsp;char&nbsp;s2:3;<br>&nbsp;&nbsp;unsigned&nbsp;char&nbsp;s3:3;<br>&nbsp;}&nbsp;x;<br><br>&nbsp;unsigned&nbsp;char&nbsp;c;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;v;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;v.c&nbsp;=&nbsp;100;<br>&nbsp;&nbsp;&nbsp;&nbsp;printf("%d",&nbsp;v.x.s3);&nbsp;<br><br>}<br><br>3<br><br>--------------------------------------------------------------------------<br>15.用C++写个程序，如何判断一个操作系统是16位还是32位的？不能用sizeof()函数<br><br>A1:<br>16位的系统下，<br>int&nbsp;i&nbsp;=&nbsp;65536;<br>cout&nbsp;&lt;&lt;&nbsp;i;&nbsp;//&nbsp;输出0；<br>int&nbsp;i&nbsp;=&nbsp;65535;<br>cout&nbsp;&lt;&lt;&nbsp;i;&nbsp;//&nbsp;输出-1；<br><br>32位的系统下，<br>int&nbsp;i&nbsp;=&nbsp;65536;<br>cout&nbsp;&lt;&lt;&nbsp;i;&nbsp;//&nbsp;输出65536；<br>int&nbsp;i&nbsp;=&nbsp;65535;<br>cout&nbsp;&lt;&lt;&nbsp;i;&nbsp;//&nbsp;输出65535；<br><br>A2:<br><br>int&nbsp;a&nbsp;=&nbsp;~0;<br>if(&nbsp;a&gt;65536&nbsp;)&nbsp;<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;"32&nbsp;bit"&lt;&lt;endl;<br>}<br>else<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;"16&nbsp;bit"&lt;&lt;endl;<br>}<br><br><br>--------------------------------------------------------------------------<br>16.C和C++有什么不同?<br><br>从机制上：c是面向过程的（但c也可以编写面向对象的程序）；c++是面向对象的，提供了类。但是，<br>c++编写面向对象的程序比c容易<br><br>从适用的方向：c适合要求代码体积小的，效率高的场合，如嵌入式；c++适合更上层的，复杂的；&nbsp;&nbsp;llinux核心大部分是c写的，因为它是系统软件，效率要求极高。<br><br>从名称上也可以看出，c++比c多了+，说明c++是c的超集；那为什么不叫c+而叫c++呢，是因为c++比<br>c来说扩充的东西太多了，所以就在c后面放上两个+；于是就成了c++<br><br>C语言是结构化编程语言，C++是面向对象编程语言。<br>C++侧重于对象而不是过程，侧重于类的设计而不是逻辑的设计。<br><br>--------------------------------------------------------------------------<br>17.在不用第三方参数的情况下，交换两个参数的值<br>#include&nbsp;&lt;stdio.h&gt;<br><br>void&nbsp;main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;i=60;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;j=50;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i=i+j;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j=i-j;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i=i-j;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("i=%d\n",i);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("j=%d\n",j);<br>}<br><br>方法二：<br>i^=j;<br>j^=i;<br>i^=j;<br><br>方法三：<br>//&nbsp;用加减实现，而且不会溢出<br>a&nbsp;=&nbsp;a+b-(b=a)<br><br>--------------------------------------------------------------------------<br>18.有关位域的面试题（为什么输出的是一个奇怪的字符）<br><br>a.t&nbsp;=&nbsp;'b';效果相当于&nbsp;a.t=&nbsp;'b'&nbsp;&amp;&nbsp;0xf;<br><br>'b'&nbsp;--&gt;&nbsp;01100010<br>'b'&nbsp;&amp;&nbsp;0xf&nbsp;--&gt;&gt;00000010<br>所以输出Ascii码为2的特殊字符<br><br><br>char&nbsp;t:4;就是4bit的字符变量，同样<br>unsigned&nbsp;short&nbsp;i:8;就是8bit的无符号短整形变量<br><br>--------------------------------------------------------------------------<br>19.int&nbsp;i=10,&nbsp;j=10,&nbsp;k=3;&nbsp;k*=i+j;&nbsp;k最后的值是?<br><br>60<br><br>--------------------------------------------------------------------------<br>20.进程间通信的方式有?<br><br>进程间通信的方式有&nbsp;共享内存，&nbsp;管道&nbsp;，Socket&nbsp;，消息队列&nbsp;,&nbsp;DDE等<br><br>--------------------------------------------------------------------------<br>21.<br>struct&nbsp;A&nbsp;<br>{&nbsp;<br>char&nbsp;t:4;&nbsp;<br>char&nbsp;k:4;&nbsp;<br>unsigned&nbsp;short&nbsp;i:8;&nbsp;<br>unsigned&nbsp;long&nbsp;m;&nbsp;<br>}&nbsp;<br>sizeof(A)=?（不考虑边界对齐）<br><br>7<br><br>struct&nbsp;CELL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Declare&nbsp;CELL&nbsp;bit&nbsp;field<br>{<br>&nbsp;&nbsp;&nbsp;unsigned&nbsp;character&nbsp;&nbsp;:&nbsp;8;&nbsp;&nbsp;//&nbsp;00000000&nbsp;????????<br>&nbsp;&nbsp;&nbsp;unsigned&nbsp;foreground&nbsp;:&nbsp;3;&nbsp;&nbsp;//&nbsp;00000???&nbsp;00000000<br>&nbsp;&nbsp;&nbsp;unsigned&nbsp;intensity&nbsp;&nbsp;:&nbsp;1;&nbsp;&nbsp;//&nbsp;0000?000&nbsp;00000000<br>&nbsp;&nbsp;&nbsp;unsigned&nbsp;background&nbsp;:&nbsp;3;&nbsp;&nbsp;//&nbsp;0???0000&nbsp;00000000<br>&nbsp;&nbsp;&nbsp;unsigned&nbsp;blink&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;1;&nbsp;&nbsp;//&nbsp;?0000000&nbsp;00000000<br>}&nbsp;screen[25][80];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Array&nbsp;of&nbsp;bit&nbsp;fields<br>二、位结构&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;位结构是一种特殊的结构,&nbsp;在需按位访问一个字节或字的多个位时,&nbsp;位结构&nbsp;<br>比按位运算符更加方便。&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;位结构定义的一般形式为:&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct位结构名{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;数据类型&nbsp;变量名:&nbsp;整型常数;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;数据类型&nbsp;变量名:&nbsp;整型常数;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;位结构变量;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;其中:&nbsp;数据类型必须是int(unsigned或signed)。&nbsp;整型常数必须是非负的整&nbsp;<br>数,&nbsp;范围是0~15,&nbsp;表示二进制位的个数,&nbsp;即表示有多少位。&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;变量名是选择项,&nbsp;可以不命名,&nbsp;这样规定是为了排列需要。&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;例如:&nbsp;下面定义了一个位结构。&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;incon:&nbsp;8;&nbsp;&nbsp;/*incon占用低字节的0~7共8位*/&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;txcolor:&nbsp;4;/*txcolor占用高字节的0~3位共4位*/&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;bgcolor:&nbsp;3;/*bgcolor占用高字节的4~6位共3位*/&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;blink:&nbsp;1;&nbsp;&nbsp;/*blink占用高字节的第7位*/&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}ch;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;位结构成员的访问与结构成员的访问相同。&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;例如:&nbsp;访问上例位结构中的bgcolor成员可写成:&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ch.bgcolor&nbsp;<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;注意:&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;1.&nbsp;位结构中的成员可以定义为unsigned,&nbsp;也可定义为signed,&nbsp;&nbsp;但当成员长&nbsp;<br>度为1时,&nbsp;会被认为是unsigned类型。因为单个位不可能具有符号。&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;2.&nbsp;位结构中的成员不能使用数组和指针,&nbsp;但位结构变量可以是数组和指针,&nbsp;<br>如果是指针,&nbsp;其成员访问方式同结构指针。&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;3.&nbsp;位结构总长度(位数),&nbsp;是各个位成员定义的位数之和,&nbsp;&nbsp;可以超过两个字&nbsp;<br>节。&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;4.&nbsp;位结构成员可以与其它结构成员一起使用。&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;例如:&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;info{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;name[8];&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;age;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;addr&nbsp;address;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;float&nbsp;pay;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;state:&nbsp;1;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;pay:&nbsp;1;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}workers;<br>&nbsp;&nbsp;&nbsp;&nbsp;上例的结构定义了关于一个工人的信息。其中有两个位结构成员,&nbsp;每个位结&nbsp;<br>构成员只有一位,&nbsp;因此只占一个字节但保存了两个信息,&nbsp;该字节中第一位表示工&nbsp;<br>人的状态,&nbsp;第二位表示工资是否已发放。由此可见使用位结构可以节省存贮空间。<br><br><br>--------------------------------------------------------------------------<br>22.下面的函数实现在一个固定的数上加上一个数，有什么错误，改正&nbsp;<br>int&nbsp;add_n(int&nbsp;n)&nbsp;<br>{&nbsp;<br>&nbsp;&nbsp;static&nbsp;int&nbsp;i=100;&nbsp;<br>&nbsp;&nbsp;i+=n;&nbsp;<br>&nbsp;&nbsp;return&nbsp;i;&nbsp;<br>}&nbsp;<br><br>答:<br>因为static使得i的值会保留上次的值。<br>去掉static就可了<br><br>--------------------------------------------------------------------------<br>23.下面的代码有什么问题?<br>class&nbsp;A&nbsp;<br>{&nbsp;<br>public:&nbsp;<br>&nbsp;&nbsp;A()&nbsp;{&nbsp;p=this;&nbsp;}&nbsp;<br>&nbsp;&nbsp;~A()&nbsp;{&nbsp;if(p!=NULL)&nbsp;{&nbsp;delete&nbsp;p;&nbsp;p=NULL;&nbsp;}&nbsp;}&nbsp;<br><br>&nbsp;&nbsp;A*&nbsp;p;&nbsp;<br>};<br><br>答:<br>会引起无限递归<br><br>--------------------------------------------------------------------------<br>24.<br>union&nbsp;a&nbsp;{<br>&nbsp;int&nbsp;a_int1;<br>&nbsp;double&nbsp;a_double;<br>&nbsp;int&nbsp;a_int2;<br>};<br><br>typedef&nbsp;struct<br>{<br>&nbsp;a&nbsp;a1;<br>&nbsp;char&nbsp;y;<br>}&nbsp;b;<br><br>class&nbsp;c<br>{<br>&nbsp;double&nbsp;c_double;<br>&nbsp;b&nbsp;b1;<br>&nbsp;a&nbsp;a2;<br><br>};<br><br>输出cout&lt;&lt;sizeof(c)&lt;&lt;endl;的结果?<br><br>答:<br>VC6环境下得出的结果是32<br><br>另:<br>我(sun)在VC6.0+win2k下做过试验:<br>short&nbsp;-&nbsp;2<br>int-4<br>float-4<br>double-8<br>指针-4<br><br>sizeof(union)，以结构里面size最大的为union的size<br><br>解析C语言中的sizeof<br><br>一、sizeof的概念　&nbsp;<br>　　sizeof是C语言的一种单目操作符，如C语言的其他操作符++、--等。它并不是函数。sizeof操作符以字节形式给出了其操作数的存储大小。操作数可以是一个表达式或括在括号内的类型名。操作数的存储大小由操作数的类型决定。　&nbsp;<br><br>二、sizeof的使用方法　&nbsp;<br>　　1、用于数据类型　&nbsp;<br><br>　　sizeof使用形式：sizeof（type）　&nbsp;<br><br>　　数据类型必须用括号括住。如sizeof（int）。　&nbsp;<br><br>　　2、用于变量　&nbsp;<br><br>　　sizeof使用形式：sizeof（var_name）或sizeof　var_name　&nbsp;<br><br>　　变量名可以不用括号括住。如sizeof　(var_name)，sizeof　var_name等都是正确形式。带括号的用法更普遍，大多数程序员采用这种形式。　&nbsp;<br><br>　　注意：sizeof操作符不能用于函数类型，不完全类型或位字段。不完全类型指具有未知存储大小的数据类型，如未知存储大小的数组类型、未知内容的结构或联合类型、void类型等。　&nbsp;<br><br>　　如sizeof(max)若此时变量max定义为int　max(),sizeof(char_v)　若此时char_v定义为char　char_v　[MAX]且MAX未知，sizeof(void)都不是正确形式。　&nbsp;<br><br>三、sizeof的结果　&nbsp;<br>　　sizeof操作符的结果类型是size_t，它在头文件<br><br>中typedef为unsigned　int类型。该类型保证能容纳实现所建立的最大对象的字节大小。　&nbsp;<br><br>　　1、若操作数具有类型char、unsigned　char或signed　char，其结果等于1。　&nbsp;<br><br>　　ANSI　C正式规定字符类型为1字节。　&nbsp;<br><br>　　2、int、unsigned　int　、short　int、unsigned　short　、long　int　、unsigned　long　、&nbsp;float、double、long　double类型的sizeof　在ANSI　C中没有具体规定，大小依赖于实现，一般可能分别为2、2、2、2、&nbsp;4、4、4、8、10。　&nbsp;<br><br>　　3、当操作数是指针时，sizeof依赖于编译器。例如Microsoft　C/C++7.0中，near类指针字节数为2，far、huge类指针字节数为4。一般Unix的指针字节数为4。　&nbsp;<br><br>　　4、当操作数具有数组类型时，其结果是数组的总字节数。　&nbsp;<br><br>　　5、联合类型操作数的sizeof是其最大字节成员的字节数。结构类型操作数的sizeof是这种类型对象的总字节数，包括任何垫补在内。　&nbsp;<br><br>　　让我们看如下结构：　&nbsp;<br><br>　　struct　{char　b;　double　x;}　a;　&nbsp;<br><br>　　在某些机器上sizeof（a）=12，而一般sizeof（char）+　sizeof（double）=9。　&nbsp;<br><br>　　这是因为编译器在考虑对齐问题时，在结构中插入空位以控制各成员对象的地址对齐。如double类型的结构成员x要放在被4整除的地址。　&nbsp;<br><br>　　6、如果操作数是函数中的数组形参或函数类型的形参，sizeof给出其指针的大小。　&nbsp;<br><br>四、sizeof与其他操作符的关系　&nbsp;<br>　　sizeof的优先级为2级，比/、%等3级运算符优先级高。它可以与其他操作符一起组成表达式。如i*sizeof（int）；其中i为int类型变量。　&nbsp;<br><br>五、sizeof的主要用途　&nbsp;<br>　　1、sizeof操作符的一个主要用途是与存储分配和I/O系统那样的例程进行通信。例如：　&nbsp;<br><br>　　void　*malloc（size_t　size）,　&nbsp;<br><br>　　size_t　fread(void　*　ptr,size_t　size,size_t　nmemb,FILE　*　stream)。　&nbsp;<br><br>　　2、sizeof的另一个的主要用途是计算数组中元素的个数。例如：　&nbsp;<br><br>　　void　*　memset（void　*　s,int　c,sizeof(s)）。　&nbsp;<br><br>六、建议　&nbsp;<br>　　由于操作数的字节数在实现时可能出现变化，建议在涉及到操作数字节大小时用sizeof来代替常量计算。<br><br><br>=============================================================<br>本文主要包括二个部分，第一部分重点介绍在VC中，怎么样采用sizeof来求结构的大小，以及容易出现的问题，并给出解决问题的方法，第二部分总结出VC中sizeof的主要用法。&nbsp;<br><br>1、&nbsp;sizeof应用在结构上的情况&nbsp;<br><br>请看下面的结构：&nbsp;<br><br>struct&nbsp;MyStruct&nbsp;<br><br>{&nbsp;<br><br>double&nbsp;dda1;&nbsp;<br><br>char&nbsp;dda;&nbsp;<br><br>int&nbsp;type&nbsp;<br><br>};&nbsp;<br><br>对结构MyStruct采用sizeof会出现什么结果呢？sizeof(MyStruct)为多少呢？也许你会这样求：&nbsp;<br><br>sizeof(MyStruct)=sizeof(double)+sizeof(char)+sizeof(int)=13&nbsp;<br><br>但是当在VC中测试上面结构的大小时，你会发现sizeof(MyStruct)为16。你知道为什么在VC中会得出这样一个结果吗？&nbsp;<br><br>其实，这是VC对变量存储的一个特殊处理。为了提高CPU的存储速度，VC对一些变量的起始地址做了"对齐"处理。在默认情况下，VC规定各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量的类型所占用的字节数的倍数。下面列出常用类型的对齐方式(vc6.0,32位系统)。&nbsp;<br><br>类型&nbsp;<br>对齐方式（变量存放的起始地址相对于结构的起始地址的偏移量）&nbsp;<br><br>Char&nbsp;<br>偏移量必须为sizeof(char)即1的倍数&nbsp;<br><br>int&nbsp;<br>偏移量必须为sizeof(int)即4的倍数&nbsp;<br><br>float&nbsp;<br>偏移量必须为sizeof(float)即4的倍数&nbsp;<br><br>double&nbsp;<br>偏移量必须为sizeof(double)即8的倍数&nbsp;<br><br>Short&nbsp;<br>偏移量必须为sizeof(short)即2的倍数&nbsp;<br><br><br>各成员变量在存放的时候根据在结构中出现的顺序依次申请空间，同时按照上面的对齐方式调整位置，空缺的字节VC会自动填充。同时VC为了确保结构的大小为结构的字节边界数（即该结构中占用最大空间的类型所占用的字节数）的倍数，所以在为最后一个成员变量申请空间后，还会根据需要自动填充空缺的字节。&nbsp;<br><br>下面用前面的例子来说明VC到底怎么样来存放结构的。&nbsp;<br><br>struct&nbsp;MyStruct&nbsp;<br><br>{&nbsp;<br><br>double&nbsp;dda1;&nbsp;<br><br>char&nbsp;dda;&nbsp;<br><br>int&nbsp;type&nbsp;<br><br>}；&nbsp;<br><br>为上面的结构分配空间的时候，VC根据成员变量出现的顺序和对齐方式，先为第一个成员dda1分配空间，其起始地址跟结构的起始地址相同（刚好偏移量0刚好为sizeof(double)的倍数），该成员变量占用sizeof(double)=8个字节；接下来为第二个成员dda分配空间，这时下一个可以分配的地址对于结构的起始地址的偏移量为8，是sizeof(char)的倍数，所以把dda存放在偏移量为8的地方满足对齐方式，该成员变量占用&nbsp;sizeof(char)=1个字节；接下来为第三个成员type分配空间，这时下一个可以分配的地址对于结构的起始地址的偏移量为9，不是sizeof&nbsp;(int)=4的倍数，为了满足对齐方式对偏移量的约束问题，VC自动填充3个字节（这三个字节没有放什么东西），这时下一个可以分配的地址对于结构的起始地址的偏移量为12，刚好是sizeof(int)=4的倍数，所以把type存放在偏移量为12的地方，该成员变量占用sizeof(int)=4个字节；这时整个结构的成员变量已经都分配了空间，总的占用的空间大小为：8+1+3+4=16，刚好为结构的字节边界数（即结构中占用最大空间的类型所占用的字节数sizeof(double)=8）的倍数，所以没有空缺的字节需要填充。所以整个结构的大小为：sizeof(MyStruct)=8+1+&nbsp;3+4=16，其中有3个字节是VC自动填充的，没有放任何有意义的东西。&nbsp;<br><br>下面再举个例子，交换一下上面的MyStruct的成员变量的位置，使它变成下面的情况：&nbsp;<br><br>struct&nbsp;MyStruct&nbsp;<br><br>{&nbsp;<br><br>char&nbsp;dda;&nbsp;<br><br>double&nbsp;dda1;&nbsp;&nbsp;&nbsp;<br><br>int&nbsp;type&nbsp;<br><br>}；&nbsp;<br><br>这个结构占用的空间为多大呢？在VC6.0环境下，可以得到sizeof(MyStruc)为24。结合上面提到的分配空间的一些原则，分析下VC怎么样为上面的结构分配空间的。（简单说明）&nbsp;<br><br>struct&nbsp;MyStruct&nbsp;<br><br>{&nbsp;<br><br>&nbsp;&nbsp;char&nbsp;dda;//偏移量为0，满足对齐方式，dda占用1个字节；&nbsp;<br><br>double&nbsp;dda1;//下一个可用的地址的偏移量为1，不是sizeof(double)=8&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//的倍数，需要补足7个字节才能使偏移量变为8（满足对齐&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//方式），因此VC自动填充7个字节，dda1存放在偏移量为8&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//的地址上，它占用8个字节。&nbsp;<br><br>int&nbsp;type；//下一个可用的地址的偏移量为16，是sizeof(int)=4的倍&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//数，满足int的对齐方式，所以不需要VC自动填充，type存&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//放在偏移量为16的地址上，它占用4个字节。&nbsp;<br><br>}；//所有成员变量都分配了空间，空间总的大小为1+7+8+4=20，不是结构&nbsp;<br><br>&nbsp;&nbsp;&nbsp;//的节边界数（即结构中占用最大空间的类型所占用的字节数sizeof&nbsp;<br><br>&nbsp;&nbsp;&nbsp;//(double)=8）的倍数，所以需要填充4个字节，以满足结构的大小为&nbsp;<br><br>&nbsp;&nbsp;&nbsp;//sizeof(double)=8的倍数。&nbsp;<br><br><br>所以该结构总的大小为：sizeof(MyStruc)为1+7+8+4+4=24。其中总的有7+4=11个字节是VC自动填充的，没有放任何有意义的东西。&nbsp;<br><br><br>VC对结构的存储的特殊处理确实提高CPU存储变量的速度，但是有时候也带来了一些麻烦，我们也屏蔽掉变量默认的对齐方式，自己可以设定变量的对齐方式。&nbsp;<br><br>VC&nbsp;中提供了#pragma&nbsp;pack(n)来设定变量以n字节对齐方式。n字节对齐就是说变量存放的起始地址的偏移量有两种情况：第一、如果n大于等于该变量所占用的字节数，那么偏移量必须满足默认的对齐方式，第二、如果n小于该变量的类型所占用的字节数，那么偏移量为n的倍数，不用满足默认的对齐方式。结构的总大小也有个约束条件，分下面两种情况：如果n大于所有成员变量类型所占用的字节数，那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数；&nbsp;&nbsp;<br><br>否则必须为n的倍数。下面举例说明其用法。&nbsp;<br><br>#pragma&nbsp;pack(push)&nbsp;//保存对齐状态&nbsp;<br><br>#pragma&nbsp;pack(4)//设定为4字节对齐&nbsp;<br><br>struct&nbsp;test&nbsp;<br><br>{&nbsp;<br><br>&nbsp;&nbsp;char&nbsp;m1;&nbsp;<br><br>&nbsp;&nbsp;double&nbsp;m4;&nbsp;<br><br>&nbsp;&nbsp;int&nbsp;&nbsp;m3;&nbsp;<br><br>};&nbsp;<br><br>#pragma&nbsp;pack(pop)//恢复对齐状态&nbsp;<br><br>以上结构的大小为16，下面分析其存储情况，首先为m1分配空间，其偏移量为0，满足我们自己设定的对齐方式（4字节对齐），m1占用1个字节。接着开始为&nbsp;m4分配空间，这时其偏移量为1，需要补足3个字节，这样使偏移量满足为n=4的倍数（因为sizeof(double)大于n）,m4占用8个字节。接着为m3分配空间，这时其偏移量为12，满足为4的倍数，m3占用4个字节。这时已经为所有成员变量分配了空间，共分配了16个字节，满足为n的倍数。如果把上面的#pragma&nbsp;pack(4)改为#pragma&nbsp;pack(16)，那么我们可以得到结构的大小为24。（请读者自己分析）&nbsp;<br><br>2、&nbsp;sizeof用法总结&nbsp;<br><br>在VC中，sizeof有着许多的用法，而且很容易引起一些错误。下面根据sizeof后面的参数对sizeof的用法做个总结。&nbsp;<br><br>A．&nbsp;&nbsp;参数为数据类型或者为一般变量。例如sizeof(int),sizeof(long)等等。这种情况要注意的是不同系统系统或者不同编译器得到的结果可能是不同的。例如int类型在16位系统中占2个字节，在32位系统中占4个字节。&nbsp;<br><br>B．&nbsp;&nbsp;参数为数组或指针。下面举例说明.&nbsp;<br><br>int&nbsp;a[50];&nbsp;&nbsp;//sizeof(a)=4*50=200;&nbsp;求数组所占的空间大小&nbsp;<br><br>int&nbsp;*a=new&nbsp;int[50];//&nbsp;sizeof(a)=4;&nbsp;a为一个指针，sizeof(a)是求指针&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//的大小,在32位系统中，当然是占4个字节。&nbsp;<br><br>C．&nbsp;&nbsp;参数为结构或类。Sizeof应用在类和结构的处理情况是相同的。但有两点需要注意，第一、结构或者类中的静态成员不对结构或者类的大小产生影响，因为静态变量的存储位置与结构或者类的实例地址无关。&nbsp;<br><br>第二、没有成员变量的结构或类的大小为1，因为必须保证结构或类的每一&nbsp;<br><br>个实例在内存中都有唯一的地址。&nbsp;<br><br>下面举例说明，&nbsp;<br><br>Class&nbsp;Test{int&nbsp;a;static&nbsp;double&nbsp;c};//sizeof(Test)=4.&nbsp;<br><br>Test&nbsp;*s;//sizeof(s)=4,s为一个指针。&nbsp;<br><br>Class&nbsp;test1{&nbsp;};//sizeof(test1)=1;&nbsp;<br><br>D．&nbsp;&nbsp;参数为其他。下面举例说明。&nbsp;<br><br>&nbsp;&nbsp;&nbsp;int&nbsp;func(char&nbsp;s[5]);&nbsp;<br><br>&nbsp;&nbsp;&nbsp;{&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;sizeof(s);//这里将输出4，本来s为一个数组，但由于做为函&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;//以sizeof(s)实际上为求指针的大小。&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;1;&nbsp;<br><br>}&nbsp;<br><br>sizeof(func("1234"))=4//因为func的返回类型为int，所以相当于&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//求sizeof(int).&nbsp;<br><br><br>以上为sizeof的基本用法，在实际的使用中要注意分析VC的分配变量的分配策略，这样的话可以避免一些错误。&nbsp;<br><br><br>--------------------------------------------------------------------------<br>25.i最后等于多少?<br>int&nbsp;i&nbsp;=&nbsp;1;<br>int&nbsp;j&nbsp;=&nbsp;i++;<br>if((i&gt;j++)&nbsp;&amp;&amp;&nbsp;(i++&nbsp;==&nbsp;j))&nbsp;i+=j;<br><br>答:<br>i&nbsp;=&nbsp;5<br><br>--------------------------------------------------------------------------<br>26.<br>unsigned&nbsp;short&nbsp;array[]={1,2,3,4,5,6,7};<br>int&nbsp;i&nbsp;=&nbsp;3;<br>*(array&nbsp;+&nbsp;i)&nbsp;=&nbsp;?<br><br>答:<br>4<br><br>--------------------------------------------------------------------------<br>27.<br>class&nbsp;A<br>{<br>&nbsp;&nbsp;virtual&nbsp;void&nbsp;func1()；<br>&nbsp;&nbsp;void&nbsp;func2();<br>}<br>Class&nbsp;B:&nbsp;class&nbsp;A<br>{<br>&nbsp;&nbsp;void&nbsp;func1(){cout&nbsp;&lt;&lt;&nbsp;"fun1&nbsp;in&nbsp;class&nbsp;B"&nbsp;&lt;&lt;&nbsp;endl;}<br>&nbsp;&nbsp;virtual&nbsp;void&nbsp;func2(){cout&nbsp;&lt;&lt;&nbsp;"fun2&nbsp;in&nbsp;class&nbsp;B"&nbsp;&lt;&lt;&nbsp;endl;}<br>}&nbsp;<br>A,&nbsp;A中的func1和B中的func2都是虚函数.<br>B,&nbsp;A中的func1和B中的func2都不是虚函数.<br>C,&nbsp;A中的func2是虚函数.，B中的func1不是虚函数.<br>D,&nbsp;A中的func2不是虚函数，B中的func1是虚函数.<br><br>答:<br>A<br><br>--------------------------------------------------------------------------<br>28.<br>数据库：抽出部门，平均工资，要求按部门的字符串顺序排序，不能含有"human&nbsp;resource"部门，<br><br>employee结构如下：employee_id,&nbsp;employee_name,&nbsp;depart_id,depart_name,wage<br><br>答:<br>select&nbsp;depart_name,&nbsp;avg(wage)<br>from&nbsp;employee<br>where&nbsp;depart_name&nbsp;&lt;&gt;&nbsp;'human&nbsp;resource'<br>group&nbsp;by&nbsp;depart_name<br>order&nbsp;by&nbsp;depart_name<br><br>--------------------------------------------------------------------------<br>29.<br>给定如下SQL数据库：Test(num&nbsp;INT(4))&nbsp;请用一条SQL语句返回num的最小值，但不许使用统计功能，如MIN，MAX等<br><br>答:<br>select&nbsp;top&nbsp;1&nbsp;num<br>from&nbsp;Test<br>order&nbsp;by&nbsp;num&nbsp;desc<br><br>--------------------------------------------------------------------------<br>30.<br>输出下面程序结果。&nbsp;<br><br>#include&nbsp;&lt;iostream.h&gt;&nbsp;<br><br>class&nbsp;A&nbsp;<br>{&nbsp;<br>public:<br>&nbsp;virtual&nbsp;void&nbsp;print(void)&nbsp;<br>&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;"A::print()"&lt;&lt;endl;&nbsp;<br>&nbsp;}&nbsp;<br>};<br>class&nbsp;B:public&nbsp;A&nbsp;<br>{&nbsp;<br>public:<br>&nbsp;virtual&nbsp;void&nbsp;print(void)&nbsp;<br>&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;cout&lt;&lt;"B::print()"&lt;&lt;endl;<br>&nbsp;};&nbsp;<br>};&nbsp;<br>class&nbsp;C:public&nbsp;B<br>{<br>public:<br>&nbsp;virtual&nbsp;void&nbsp;print(void)<br>&nbsp;{<br>&nbsp;&nbsp;cout&lt;&lt;"C::print()"&lt;&lt;endl;<br>&nbsp;}<br>};<br>void&nbsp;print(A&nbsp;a)&nbsp;<br>{&nbsp;<br>&nbsp;&nbsp;&nbsp;a.print();&nbsp;<br>}&nbsp;<br>void&nbsp;main(void)&nbsp;<br>{&nbsp;<br>&nbsp;&nbsp;&nbsp;A&nbsp;a,&nbsp;*pa,*pb,*pc;&nbsp;<br>&nbsp;&nbsp;&nbsp;B&nbsp;b;&nbsp;<br>&nbsp;&nbsp;&nbsp;C&nbsp;c;&nbsp;<br>&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;pa=&amp;a;&nbsp;<br>&nbsp;&nbsp;&nbsp;pb=&amp;b;&nbsp;<br>&nbsp;&nbsp;&nbsp;pc=&amp;c;&nbsp;<br>&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;a.print();&nbsp;<br>&nbsp;&nbsp;&nbsp;b.print();&nbsp;<br>&nbsp;&nbsp;&nbsp;c.print();&nbsp;<br>&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;pa-&gt;print();&nbsp;<br>&nbsp;&nbsp;&nbsp;pb-&gt;print();&nbsp;<br>&nbsp;&nbsp;&nbsp;pc-&gt;print();&nbsp;<br>&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;print(a);&nbsp;<br>&nbsp;&nbsp;&nbsp;print(b);&nbsp;<br>&nbsp;&nbsp;&nbsp;print(c);&nbsp;<br>}<br><br>A:<br>A::print()<br>B::print()<br>C::print()<br>A::print()<br>B::print()<br>C::print()<br>A::print()<br>A::print()<br>A::print()<br><br>--------------------------------------------------------------------------<br>31.<br>试编写函数判断计算机的字节存储顺序是开序(little&nbsp;endian)还是降序(bigendian)<br><br>答:<br>bool&nbsp;IsBigendian()<br>{<br>&nbsp;unsigned&nbsp;short&nbsp;usData&nbsp;=&nbsp;0x1122;<br>&nbsp;unsigned&nbsp;char&nbsp;&nbsp;*pucData&nbsp;=&nbsp;(unsigned&nbsp;char*)&amp;usData;<br><br>&nbsp;return&nbsp;(*pucData&nbsp;==&nbsp;0x22);<br>}<br><br>--------------------------------------------------------------------------<br>32.简述Critical&nbsp;Section和Mutex的不同点<br><br>答:<br>对几种同步对象的总结<br>1.Critical&nbsp;Section<br>A.速度快<br>B.不能用于不同进程<br>C.不能进行资源统计(每次只可以有一个线程对共享资源进行存取)<br><br>2.Mutex<br>A.速度慢<br>B.可用于不同进程<br>C.不能进行资源统计<br><br>3.Semaphore<br>A.速度慢<br>B.可用于不同进程<br>C.可进行资源统计(可以让一个或超过一个线程对共享资源进行存取)<br><br>4.Event<br>A.速度慢<br>B.可用于不同进程<br>C.可进行资源统计<br><br><br>--------------------------------------------------------------------------<br>33.一个数据库中有两个表:<br>一张表为Customer，含字段ID,Name;<br>一张表为Order，含字段ID,CustomerID（连向Customer中ID的外键）,Revenue；<br>写出求每个Customer的Revenue总和的SQL语句。<br><br>建表<br>create&nbsp;table&nbsp;customer<br>(<br>ID&nbsp;int&nbsp;primary&nbsp;key,Name&nbsp;char(10)<br>)<br><br>go<br><br>create&nbsp;table&nbsp;[order]<br>(<br>ID&nbsp;int&nbsp;primary&nbsp;key,CustomerID&nbsp;&nbsp;int&nbsp;foreign&nbsp;key&nbsp;references&nbsp;customer(id)&nbsp;,&nbsp;Revenue&nbsp;float<br>)<br><br>go<br><br>--查询<br>select&nbsp;Customer.ID,&nbsp;sum(&nbsp;isnull([Order].Revenue,0)&nbsp;)<br>from&nbsp;customer&nbsp;full&nbsp;join&nbsp;[order]&nbsp;<br>on(&nbsp;[order].customerid=customer.id&nbsp;)<br>group&nbsp;by&nbsp;customer.id<br><br>--------------------------------------------------------------------------<br>34.请指出下列程序中的错误并且修改<br>void&nbsp;GetMemory(char&nbsp;*p){<br>&nbsp;&nbsp;p=(char&nbsp;*)malloc(100);<br>}<br>void&nbsp;Test(void){<br>&nbsp;&nbsp;char&nbsp;*str=NULL;<br>&nbsp;&nbsp;GetMemory=(str);<br>&nbsp;&nbsp;strcpy(str,"hello&nbsp;world");<br>&nbsp;&nbsp;printf(str);<br>}<br><br>A:错误--参数的值改变后，不会传回<br>GetMemory并不能传递动态内存，Test函数中的&nbsp;str一直都是&nbsp;NULL。<br>strcpy(str,&nbsp;"hello&nbsp;world");将使程序崩溃。<br><br>修改如下:<br>char&nbsp;*GetMemory(){<br>&nbsp;&nbsp;char&nbsp;*p=(char&nbsp;*)malloc(100);<br>&nbsp;&nbsp;return&nbsp;p;<br>}<br>void&nbsp;Test(void){<br>&nbsp;&nbsp;char&nbsp;*str=NULL;<br>&nbsp;&nbsp;str=GetMemory(){<br>&nbsp;&nbsp;strcpy(str,"hello&nbsp;world");<br>&nbsp;&nbsp;printf(str);<br>}<br><br>方法二:void&nbsp;GetMemory2(char&nbsp;**p)变为二级指针.<br>void&nbsp;GetMemory2(char&nbsp;**p,&nbsp;int&nbsp;num)<br>{<br>&nbsp;*p&nbsp;=&nbsp;(char&nbsp;*)malloc(sizeof(char)&nbsp;*&nbsp;num);<br>}<br><br>--------------------------------------------------------------------------<br>35.程序改错<br>class&nbsp;mml<br>{<br>&nbsp;&nbsp;private:<br>&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;unsigned&nbsp;int&nbsp;x;<br>&nbsp;&nbsp;public:<br>&nbsp;&nbsp;&nbsp;&nbsp;mml(){&nbsp;x++;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;mml(static&nbsp;unsigned&nbsp;int&nbsp;&amp;)&nbsp;{x++;}<br>&nbsp;&nbsp;&nbsp;&nbsp;~mml{x--;}<br>&nbsp;&nbsp;pulic:<br>&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;mon()&nbsp;{}&nbsp;=&nbsp;0;<br>&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;unsigned&nbsp;int&nbsp;mmc(){return&nbsp;x;}<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;<br>&nbsp;<br>};<br>class&nbsp;nnl:public&nbsp;mml<br>{<br>&nbsp;&nbsp;private:<br>&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;unsigned&nbsp;int&nbsp;y;<br>&nbsp;&nbsp;public:<br>&nbsp;&nbsp;&nbsp;&nbsp;nnl(){&nbsp;x++;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;nnl(static&nbsp;unsigned&nbsp;int&nbsp;&amp;)&nbsp;{x++;}<br>&nbsp;&nbsp;&nbsp;&nbsp;~nnl{x--;}<br>&nbsp;&nbsp;public:<br>&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;mon()&nbsp;{};<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;unsigned&nbsp;int&nbsp;nnc(){return&nbsp;y;}<br>&nbsp;&nbsp;&nbsp;&nbsp;......&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>};<br><br>代码片断:<br>mml*&nbsp;pp&nbsp;=&nbsp;new&nbsp;nnl;<br>..........<br>delete&nbsp;pp;<br><br><br>A:<br>基类的析构函数应该为虚函数<br>virtual&nbsp;~mml{x--;}<br><br>--------------------------------------------------------------------------<br>36.101个硬币100真、1假，真假区别在于重量。请用无砝码天平称两次给出真币重还是假币重的结论。<br><br>答:<br>101个先取出2堆,<br>33,33<br>第一次称,如果不相等,说明有一堆重或轻<br>那么把重的那堆拿下来,再放另外35个中的33<br>如果相等,说明假的重,如果不相等,新放上去的还是重的话,说明假的轻(不可能新放上去的轻)<br><br>第一次称,如果相等的话，这66个肯定都是真的,从这66个中取出35个来,与剩下的没称过的35个比<br>下面就不用说了<br><br>方法二:<br>第3题也可以拿A(50),B(50)比一下，一样的话拿剩下的一个和真的比一下。<br>如果不一样，就拿其中的一堆。比如A(50)再分成两堆25比一下，一样的话就在<br>B(50)中，不一样就在A(50)中，结合第一次的结果就知道了。<br><br>--------------------------------------------------------------------------<br>37.static变量和static&nbsp;函数各有什么特点？<br><br>答:<br>static变量：在程序运行期内一直有效，如果定义在函数外，则在编译单元内可见，如果在函数内，在在定义的block内可见；<br>static函数：在编译单元内可见；<br><br>--------------------------------------------------------------------------<br>38.用C&nbsp;写一个输入的整数,倒着输出整数的函数,要求用递归方法&nbsp;;<br><br>答:<br>void&nbsp;fun(&nbsp;int&nbsp;a&nbsp;)<br>{<br>&nbsp;printf(&nbsp;"%d",&nbsp;a%10&nbsp;);<br>&nbsp;a&nbsp;/=&nbsp;10;<br>&nbsp;if(&nbsp;a&nbsp;&lt;=0&nbsp;)return;<br><br>&nbsp;fun(&nbsp;a&nbsp;);<br>}<br><br>--------------------------------------------------------------------------<br>39.写出程序结果:<br>void&nbsp;Func(char&nbsp;str[100])<br>{<br>&nbsp;&nbsp;printf("%d\n",&nbsp;sizeof(str));<br>}<br><br>答:<br>4<br>分析:<br>指针长度<br><br>--------------------------------------------------------------------------<br>40.int&nbsp;id[sizeof(unsigned&nbsp;long)];<br>&nbsp;&nbsp;&nbsp;&nbsp;这个对吗？为什么??<br><br>答:<br>对<br>这个&nbsp;sizeof是编译时运算符，编译时就确定了<br>可以看成和机器有关的常量。<br><br><br>本文主要包括二个部分，第一部分重点介绍在VC中，怎么样采用sizeof来求结构的大小，以及容易出现的问题，并给出解决问题的方法，第二部分总结出VC中sizeof的主要用法。&nbsp;<br><br>1、&nbsp;sizeof应用在结构上的情况&nbsp;<br><br>请看下面的结构：&nbsp;<br><br>struct&nbsp;MyStruct&nbsp;<br><br>{&nbsp;<br><br>double&nbsp;dda1;&nbsp;<br><br>char&nbsp;dda;&nbsp;<br><br>int&nbsp;type&nbsp;<br><br>};&nbsp;<br><br>对结构MyStruct采用sizeof会出现什么结果呢？sizeof(MyStruct)为多少呢？也许你会这样求：&nbsp;<br><br>sizeof(MyStruct)=sizeof(double)+sizeof(char)+sizeof(int)=13&nbsp;<br><br>但是当在VC中测试上面结构的大小时，你会发现sizeof(MyStruct)为16。你知道为什么在VC中会得出这样一个结果吗？&nbsp;<br><br>其实，这是VC对变量存储的一个特殊处理。为了提高CPU的存储速度，VC对一些变量的起始地址做了"对齐"处理。在默认情况下，VC规定各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量的类型所占用的字节数的倍数。下面列出常用类型的对齐方式(vc6.0,32位系统)。&nbsp;<br><br>类型&nbsp;<br>对齐方式（变量存放的起始地址相对于结构的起始地址的偏移量）&nbsp;<br><br>Char&nbsp;<br>偏移量必须为sizeof(char)即1的倍数&nbsp;<br><br>int&nbsp;<br>偏移量必须为sizeof(int)即4的倍数&nbsp;<br><br>float&nbsp;<br>偏移量必须为sizeof(float)即4的倍数&nbsp;<br><br>double&nbsp;<br>偏移量必须为sizeof(double)即8的倍数&nbsp;<br><br>Short&nbsp;<br>偏移量必须为sizeof(short)即2的倍数&nbsp;<br><br><br>各成员变量在存放的时候根据在结构中出现的顺序依次申请空间，同时按照上面的对齐方式调整位置，空缺的字节VC会自动填充。同时VC为了确保结构的大小为结构的字节边界数（即该结构中占用最大空间的类型所占用的字节数）的倍?/textarea&gt;</p><img src ="http://www.cppblog.com/yearner/aggbug/12208.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/yearner/" target="_blank">(Leyn)顽主</a> 2006-09-10 09:11 <a href="http://www.cppblog.com/yearner/archive/2006/09/10/12208.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>