﻿<?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++博客-My C++-随笔分类-C/C++</title><link>http://www.cppblog.com/finehai/category/11209.html</link><description>当时只道是寻常~</description><language>zh-cn</language><lastBuildDate>Tue, 24 Apr 2012 17:03:13 GMT</lastBuildDate><pubDate>Tue, 24 Apr 2012 17:03:13 GMT</pubDate><ttl>60</ttl><item><title>【转】C++ 虚函数表解析 </title><link>http://www.cppblog.com/finehai/archive/2012/04/24/172574.html</link><dc:creator>Bluesea</dc:creator><author>Bluesea</author><pubDate>Tue, 24 Apr 2012 03:44:00 GMT</pubDate><guid>http://www.cppblog.com/finehai/archive/2012/04/24/172574.html</guid><wfw:comment>http://www.cppblog.com/finehai/comments/172574.html</wfw:comment><comments>http://www.cppblog.com/finehai/archive/2012/04/24/172574.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/finehai/comments/commentRss/172574.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/finehai/services/trackbacks/172574.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: C++中的虚函数的作用主要是实现了多态的机制。关于多态，简而言之就是用父类型别的指针指向其子类的实例，然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”，这是一种泛型技术。所谓泛型技术，说白了就是试图使用不变的代码来实现可变的算法。比如：模板技术，RTTI技术，虚函数技术，要么是试图做到在编译时决议，要么试图做到运行时决议。&nbsp;&nbsp;<a href='http://www.cppblog.com/finehai/archive/2012/04/24/172574.html'>阅读全文</a><img src ="http://www.cppblog.com/finehai/aggbug/172574.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/finehai/" target="_blank">Bluesea</a> 2012-04-24 11:44 <a href="http://www.cppblog.com/finehai/archive/2012/04/24/172574.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>STL中map用法详解</title><link>http://www.cppblog.com/finehai/archive/2009/10/22/99175.html</link><dc:creator>Bluesea</dc:creator><author>Bluesea</author><pubDate>Thu, 22 Oct 2009 02:55:00 GMT</pubDate><guid>http://www.cppblog.com/finehai/archive/2009/10/22/99175.html</guid><wfw:comment>http://www.cppblog.com/finehai/comments/99175.html</wfw:comment><comments>http://www.cppblog.com/finehai/archive/2009/10/22/99175.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/finehai/comments/commentRss/99175.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/finehai/services/trackbacks/99175.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Map是STL的一个关联容器，它提供一对一（其中第一个可以称为关键字，每个关键字只能在map中出现一次，第二个可能称为该关键字的值）的数据处理能力，由于这个特性，它完成有可能在我们处理一对一数据的时候，在编程上提供快速通道。这里说下map内部数据的组织，map内部自建一颗红黑树(一种非严格意义上的平衡二叉树)，这颗树具有对数据自动排序的功能，所以在map内部所有的数据都是有序的，后边我们会见识到有...&nbsp;&nbsp;<a href='http://www.cppblog.com/finehai/archive/2009/10/22/99175.html'>阅读全文</a><img src ="http://www.cppblog.com/finehai/aggbug/99175.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/finehai/" target="_blank">Bluesea</a> 2009-10-22 10:55 <a href="http://www.cppblog.com/finehai/archive/2009/10/22/99175.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多媒体定时器</title><link>http://www.cppblog.com/finehai/archive/2009/09/12/95998.html</link><dc:creator>Bluesea</dc:creator><author>Bluesea</author><pubDate>Sat, 12 Sep 2009 05:53:00 GMT</pubDate><guid>http://www.cppblog.com/finehai/archive/2009/09/12/95998.html</guid><wfw:comment>http://www.cppblog.com/finehai/comments/95998.html</wfw:comment><comments>http://www.cppblog.com/finehai/archive/2009/09/12/95998.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/finehai/comments/commentRss/95998.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/finehai/services/trackbacks/95998.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;虽然Win95下可视化开发工具如VC、Delphi、C＋＋ &nbsp; Builder等都有专用的定时器控件Timer，而且使用很方便，可以实现一定的定时功能，但最小计时精度仅为55ms，且定时器消息在多任务操作系统中的优先级很低，不能得到及时响应，往往不能满足实时控制环境下的应用。不过Microsoft公司在Win32 &nbsp; API函数库中已经为用户提供了一组用于高精度计时的底层函数，如果用户使用得当，<span style="COLOR: red">计时精度可到1ms</span>。这个计时精度、对于一般的实时系统控制完全可以满足要求。现将由C＋＋ &nbsp; Builder &nbsp; 4.0提供的重新封装后的一组与时间相关的主要接口函数（函数名、参数、功能与Win32 &nbsp; API基本相同）说明如下：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;1．DWORD &nbsp; timeGetTime(void) &nbsp; &nbsp; <br>&nbsp; 　 返回从Windows启动开始经过的毫秒数。最大值为232，约49.71天。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><br>&nbsp;2．MMRESULT &nbsp; timeSetEvent( &nbsp; &nbsp; <br>&nbsp; 　　UINT &nbsp; uDelay, &nbsp; &nbsp; <br>&nbsp; 　　UINT &nbsp; uResolution, &nbsp; &nbsp; <br>&nbsp; 　　LPTIMECALLBACK &nbsp; lpTimeProc, &nbsp; &nbsp; <br>&nbsp; 　　DWORD &nbsp; dwUser, &nbsp; &nbsp; <br>&nbsp; 　　UINT &nbsp; fuEvent) &nbsp; &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; 　 该函数设置一个定时回调事件，此事件可以是一个一次性事件或周期性事件。事件一旦被激活，便调用指定的回调函数，成功后返回事件的标识符代码，否则返回NULL。参数说明如下： &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; 　　uDelay：以毫秒指定事件的周期。 &nbsp; &nbsp; <br>&nbsp; 　　UResolution：以毫秒指定延时的精度，数值越小定时器事件分辨率越高。缺省值为1ms。 &nbsp; &nbsp; <br>&nbsp; 　　LpTimeProc：指向一个回调函数。 &nbsp; &nbsp; <br>&nbsp; 　　DwUser：存放用户提供的回调数据。 &nbsp; &nbsp; <br>&nbsp; 　　FuEvent：指定定时器事件类型： &nbsp; &nbsp; <br>&nbsp; 　　TIME_ONESHOT：uDelay毫秒后只产生一次事件 &nbsp; &nbsp; <br>&nbsp; 　　TIME_PERIODIC &nbsp; ：每隔uDelay毫秒周期性地产生事件。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;3．MMRESULT &nbsp; timeKillEvent(UINT &nbsp; uTimerID) &nbsp; &nbsp; <br>&nbsp; 　 该函数取消一个指定的定时器回调事件。uTimerID标识要取消的事件（由timeSetEvent函数返回的标识符）。如果成功则返回TIMERR_NOERROR，如果定时器时间不存在则返回MMSYSERR_INVALPARAM。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><br>4．回调函数<br>&nbsp; 　　void &nbsp; CALLBACK &nbsp; TimeProc( &nbsp; &nbsp; <br>&nbsp; 　　UINT &nbsp; uID, &nbsp; &nbsp; <br>&nbsp; 　　UINT &nbsp; uMsg, &nbsp; &nbsp; <br>&nbsp; 　　DWORD &nbsp; dwUser, &nbsp; &nbsp; <br>&nbsp; 　　DWORD &nbsp; dw1, &nbsp; &nbsp; <br>&nbsp; 　　DWORD &nbsp; dw2); &nbsp; &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; 　　该函数是一个应用程序定义的回调函数，出现定时器事件时该函数被调用。TimeProc是应用程序定义的函数名的占位符。使用该函数 &nbsp; <br>&nbsp; 时要注意的是，它只能调用以下有限的几组API函数：PostMessage，timeGetSystemTime， &nbsp; timeGetTime， &nbsp; timeSetEvent，timeKillEvent &nbsp; <br>&nbsp; ，midiOutShortMsg, &nbsp; midiOutLongMsg，OutputDebugString。同时也不要使用完成时间很长的API函数，程序尽可能简短。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp; 　　使用以上一组函数就可以完成毫秒级精度的计时和控制（在C++Builder中使用时要将头文件mmsystem.h加到程序中）。由于将定时控 &nbsp; <br>&nbsp; 制精确到几毫秒，定时器事件将占用大量的CPU时间和系统资源，所以在满足控制要求的前提下，应尽量将参数uResolution的数值增大。而 &nbsp; <br>&nbsp; 且定时器实时控制功能完成后要尽快释放。&nbsp;&nbsp; <br><br><span style="COLOR: red">注意以下几点问题：<br>一、回调函数的参数不能有误，否则可能引起程序崩掉；<br>二、事件调用周期uDelay不能小于事件处理时间，否则会引起程序崩溃；<br>三、通过dwUser给回调函数传递参数</span><br><br>例程如下：<br><br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>MMRESULT&nbsp;g_wTimerID = 0;<br><br><span style="COLOR: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//</span><span style="COLOR: #008000">回调函数，参数不能有错</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;2</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;CALLBACK&nbsp;CDsisiiDlg::SendFun(UINT&nbsp;wTimerID,&nbsp;UINT&nbsp;msg,&nbsp;DWORD&nbsp;dwUser,&nbsp;DWORD&nbsp;dwl,&nbsp;DWORD&nbsp;dw2)<br></span><span style="COLOR: #008080">&nbsp;3</span><span style="COLOR: #000000"><img id=Codehighlighter1_100_102_Open_Image onclick="this.style.display='none'; Codehighlighter1_100_102_Open_Text.style.display='none'; Codehighlighter1_100_102_Closed_Image.style.display='inline'; Codehighlighter1_100_102_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_100_102_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_100_102_Closed_Text.style.display='none'; Codehighlighter1_100_102_Open_Image.style.display='inline'; Codehighlighter1_100_102_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_100_102_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_100_102_Open_Text><span style="COLOR: #000000">{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CDsisiiDlg* pdcpackerdlg = (CDsisiiDlg*)dwUser;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...<br></span><span style="COLOR: #008080">&nbsp;4</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;5</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">&nbsp;6</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">bool</span><span style="COLOR: #000000">&nbsp; CDsisiiDlg::CreateTimer()<br></span><span style="COLOR: #008080">&nbsp;7</span><span style="COLOR: #000000"><img id=Codehighlighter1_124_636_Open_Image onclick="this.style.display='none'; Codehighlighter1_124_636_Open_Text.style.display='none'; Codehighlighter1_124_636_Closed_Image.style.display='inline'; Codehighlighter1_124_636_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_124_636_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_124_636_Closed_Text.style.display='none'; Codehighlighter1_124_636_Open_Image.style.display='inline'; Codehighlighter1_124_636_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_124_636_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_124_636_Open_Text><span style="COLOR: #000000">{&nbsp;<br></span><span style="COLOR: #008080">&nbsp;8</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;TIMECAPS&nbsp;&nbsp;&nbsp;tc;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;9</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;UINT&nbsp;wTimerRes;&nbsp;<br></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">设置多媒体定时器&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">12</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(timeGetDevCaps(</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">tc,</span><span style="COLOR: #0000ff">sizeof</span><span style="COLOR: #000000">(TIMECAPS))</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">TIMERR_NOERROR)</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">向机器申请一个多媒体定时器&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">13</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">14</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">15</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">获得机器允许的时间间隔（一般可达到1毫秒）&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">16</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;wTimerRes</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">min(max(tc.wPeriodMin,</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">),tc.wPeriodMax);&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">17</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">18</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">定时器开始工作&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">19</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;timeBeginPeriod(wTimerRes);&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">20</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">21</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">每过6毫秒调用回调函数timerback(),wTimerID为定时器ID.TIME_PERIODIC表周期性调用，TIME_ONESHOT表只产生一次事件&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">22</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;g_wTimerID&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;timeSetEvent(</span><span style="COLOR: #000000">6</span><span style="COLOR: #000000">,&nbsp;&nbsp;wTimerRes,&nbsp;(LPTIMECALLBACK)SendFun,&nbsp; (DWORD)this,&nbsp;TIME_PERIODIC);&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">23</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(g_wTimerID&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br></span><span style="COLOR: #008080">24</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">25</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br></span><span style="COLOR: #008080">26</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">27</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">28</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br></span><span style="COLOR: #008080">29</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">删除定时器</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">30</span><span style="COLOR: #008000"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;CDsisiiDlg::DestroyTimer()<br></span><span style="COLOR: #008080">31</span><span style="COLOR: #000000"><img id=Codehighlighter1_667_748_Open_Image onclick="this.style.display='none'; Codehighlighter1_667_748_Open_Text.style.display='none'; Codehighlighter1_667_748_Closed_Image.style.display='inline'; Codehighlighter1_667_748_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_667_748_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_667_748_Closed_Text.style.display='none'; Codehighlighter1_667_748_Open_Image.style.display='inline'; Codehighlighter1_667_748_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_667_748_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_667_748_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">32</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(g_wTimerID)<br></span><span style="COLOR: #008080">33</span><span style="COLOR: #000000"><img id=Codehighlighter1_693_746_Open_Image onclick="this.style.display='none'; Codehighlighter1_693_746_Open_Text.style.display='none'; Codehighlighter1_693_746_Closed_Image.style.display='inline'; Codehighlighter1_693_746_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_693_746_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_693_746_Closed_Text.style.display='none'; Codehighlighter1_693_746_Open_Image.style.display='inline'; Codehighlighter1_693_746_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_693_746_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_693_746_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">34</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeKillEvent(g_wTimerID);<br></span><span style="COLOR: #008080">35</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g_wTimerID&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br></span><span style="COLOR: #008080">36</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">37</span><span style="COLOR: #000000"><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<img src ="http://www.cppblog.com/finehai/aggbug/95998.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/finehai/" target="_blank">Bluesea</a> 2009-09-12 13:53 <a href="http://www.cppblog.com/finehai/archive/2009/09/12/95998.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>非静态函数，非静态变量与静态函数，静态变量</title><link>http://www.cppblog.com/finehai/archive/2009/08/29/94767.html</link><dc:creator>Bluesea</dc:creator><author>Bluesea</author><pubDate>Sat, 29 Aug 2009 08:04:00 GMT</pubDate><guid>http://www.cppblog.com/finehai/archive/2009/08/29/94767.html</guid><wfw:comment>http://www.cppblog.com/finehai/comments/94767.html</wfw:comment><comments>http://www.cppblog.com/finehai/archive/2009/08/29/94767.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/finehai/comments/commentRss/94767.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/finehai/services/trackbacks/94767.html</trackback:ping><description><![CDATA[<p><strong>一、函数<br></strong><br>函数的引入可以减少程序的目标代码，实现程序代码的共享。但是，函数调用也需要一些时间和空间方面的开销，因为调用函数实际上将程序执行流程转移到被调函数中，被调函数的程序代码执行完后，再返回到调用的地方。这种调用操作要求调用前保护现场并记忆执行的地址，返回后恢复现场，并按原来保存的地址继续执行。对于较长的函数这种开销可以忽略不计，但是对于一些函数体代码很短，但又被频繁地调用的函数，就不能忽视这种开销。引入内联函数和宏函数正是为了解决这个问题，提高程序的运行效率。 　　<br><br>在程序编译时，编译器将程序中出现的内联函数(宏函数)的调用表达式用内联函数(宏函数)的函数体来进行替换。由于在编译时将函数体中的代码替代到程序中，因此会增加目标程序代码量，进而增加空间开销，而在时间开销上不象函数调用时那么大，可见它是以目标代码的增加为代价来换取时间的节省。<br>在类静态数据成员不同于非静态的数据成员，一个类的静态数据成员仅创建和初始化一次，且在程序开始执行的时候创建，然后被该类的所有对象共享；而非静态的数据成员则随着对象的创建而多次创建和初始化; static成员是放在静态存储区的，它并不受访问控制符的限制，而其它的成员变量则是放在栈中的。<br><br><strong>二、使用方面</strong><br><br>1：windows的回调函数使用静态函数：<br><br>在类中，static型的成员函数，由于是类所拥有的，而不是具体对象所有的，这一点对于windows的回调机制非常有用。因为对于回调函数而言，windows不会借助任何对象去调用它，也就不会传递this指针，那么对于一般成员函数作为回调函数的后果，就是堆栈中有一个随机的变量会成为this指针，这当然会引发程序的崩溃。而static函数，由于是整个类的，屏蔽了this指针。因此，如果成员函数作为回调函数，就应该用static去修饰它。<br><br>2：线程控制函数常使用静态函数<br>静态函数有特定的地址空间，这样可以避免在运行时system对内存调整带来的问题。<br><br>3：Windows系统API，也常使用静态函数<br><br>调用方面，不用在调用前实例化。<br><br><strong>三、实例代码<br></strong></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">stdafx.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">stdio.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">string</span><span style="COLOR: #000000">.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Directory<br><img id=Codehighlighter1_96_437_Open_Image onclick="this.style.display='none'; Codehighlighter1_96_437_Open_Text.style.display='none'; Codehighlighter1_96_437_Closed_Image.style.display='inline'; Codehighlighter1_96_437_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_96_437_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_96_437_Closed_Text.style.display='none'; Codehighlighter1_96_437_Open_Image.style.display='inline'; Codehighlighter1_96_437_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_96_437_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_96_437_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;静态公有的函数</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Directory()<br><img id=Codehighlighter1_147_206_Open_Image onclick="this.style.display='none'; Codehighlighter1_147_206_Open_Text.style.display='none'; Codehighlighter1_147_206_Closed_Image.style.display='inline'; Codehighlighter1_147_206_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_147_206_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_147_206_Closed_Text.style.display='none'; Codehighlighter1_147_206_Open_Image.style.display='inline'; Codehighlighter1_147_206_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_147_206_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_147_206_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strcpy(strTemp,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/测试</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">15</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;setpath(</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">newpath);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;setname(&nbsp;Directory&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">dir);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;getpath(</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">oldpath);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;strTemp&nbsp;[</span><span style="COLOR: #000000">50</span><span style="COLOR: #000000">];<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">静态字符串</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;path&nbsp;[];<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">静态数据成员的初始化</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;Directory::path&nbsp;[</span><span style="COLOR: #000000">199</span><span style="COLOR: #000000">]&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/开始测试</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;静态函数访问静态变量</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Directory::setpath(</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">newpath)<br><img id=Codehighlighter1_554_657_Open_Image onclick="this.style.display='none'; Codehighlighter1_554_657_Open_Text.style.display='none'; Codehighlighter1_554_657_Closed_Image.style.display='inline'; Codehighlighter1_554_657_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_554_657_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_554_657_Closed_Text.style.display='none'; Codehighlighter1_554_657_Open_Image.style.display='inline'; Codehighlighter1_554_657_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_554_657_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_554_657_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">path=%s\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,path);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strncpy(path,&nbsp;newpath,&nbsp;</span><span style="COLOR: #000000">199</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">path=%s\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,path);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">静态函数访问非静态变量</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Directory::setname(Directory&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">dir)<br><img id=Codehighlighter1_714_797_Open_Image onclick="this.style.display='none'; Codehighlighter1_714_797_Open_Text.style.display='none'; Codehighlighter1_714_797_Closed_Image.style.display='inline'; Codehighlighter1_714_797_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_714_797_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_714_797_Closed_Text.style.display='none'; Codehighlighter1_714_797_Open_Image.style.display='inline'; Codehighlighter1_714_797_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_714_797_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_714_797_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dir</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">getpath(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/静态函数访问非静态函数</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;dir</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">strTemp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">静态函数访问非静态变量</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;非静态函数访问静态变量</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;Directory::getpath(</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">oldpath)<br><img id=Codehighlighter1_853_958_Open_Image onclick="this.style.display='none'; Codehighlighter1_853_958_Open_Text.style.display='none'; Codehighlighter1_853_958_Closed_Image.style.display='inline'; Codehighlighter1_853_958_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_853_958_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_853_958_Closed_Text.style.display='none'; Codehighlighter1_853_958_Open_Image.style.display='inline'; Codehighlighter1_853_958_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_853_958_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_853_958_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strncpy(Directory::path,oldpath,&nbsp;</span><span style="COLOR: #000000">199</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Directory::path=%s\n</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,Directory::path);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000">&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;使用实例</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;main()<br><img id=Codehighlighter1_983_1244_Open_Image onclick="this.style.display='none'; Codehighlighter1_983_1244_Open_Text.style.display='none'; Codehighlighter1_983_1244_Closed_Image.style.display='inline'; Codehighlighter1_983_1244_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_983_1244_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_983_1244_Closed_Text.style.display='none'; Codehighlighter1_983_1244_Open_Image.style.display='inline'; Codehighlighter1_983_1244_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_983_1244_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_983_1244_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;通过类名调用setpath()成员函数<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">Directory::setpath("/通过类名调用静态成员函数");<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">通过对象调用setpath()成员函数</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Directory&nbsp;dir;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dir.setpath(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/静态函数访问静态变量</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dir.getpath(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">/非静态函数访问静态变量</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Directory&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">dira;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dir.setname(dira);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br></span></div>
<p><br>本文来自CSDN博客，转载请标明出处：<a href="http://blog.csdn.net/shuigsls/archive/2008/07/13/2645918.aspx">http://blog.csdn.net/shuigsls/archive/2008/07/13/2645918.aspx</a></p>
<img src ="http://www.cppblog.com/finehai/aggbug/94767.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/finehai/" target="_blank">Bluesea</a> 2009-08-29 16:04 <a href="http://www.cppblog.com/finehai/archive/2009/08/29/94767.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何实现类的成员函数作为回调函数</title><link>http://www.cppblog.com/finehai/archive/2009/08/29/94766.html</link><dc:creator>Bluesea</dc:creator><author>Bluesea</author><pubDate>Sat, 29 Aug 2009 07:45:00 GMT</pubDate><guid>http://www.cppblog.com/finehai/archive/2009/08/29/94766.html</guid><wfw:comment>http://www.cppblog.com/finehai/comments/94766.html</wfw:comment><comments>http://www.cppblog.com/finehai/archive/2009/08/29/94766.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/finehai/comments/commentRss/94766.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/finehai/services/trackbacks/94766.html</trackback:ping><description><![CDATA[<p>回调函数(Callback&nbsp;&nbsp; function)大量用于Windows的系统服务，通过它，程序员可以安装设备驱动程序和消息过滤系统，以控制Windows的有效使用。许多程序员都发现，利用MFC或者其它的C++应用编写回调函数是非常麻烦的，其根本原因是回调函数是基于C编程的Windows&nbsp;&nbsp; SDK的技术，不是针对C++的，程序员可以将一个C函数直接作为回调函数，但是如果试图直接使用C++的成员函数作为回调函数将发生错误，甚至编译就不能通过。通过查询资料发现，其错误是普通的C++成员函数都隐含了一个传递函数作为参数，亦即&#8220;this&#8221;指针，C++通过传递一个指向自身的指针给其成员函数从而实现程序函数可以访问C++的数据成员。这也可以理解为什么C++类的多个实例可以共享成员函数但是确有不同的数据成员。由于this指针的作用，使得将一个CALLBACK型的成员函数作为回调函数安装时就会因为隐含的this指针使得函数参数个数不匹配，从而导致回调函数安装失败。要解决这一问题的关键就是不让this指针起作用，通过采用以下两种典型技术可以解决在C++中使用回调函数所遇到的问题。这种方法具有通用性，适合于任何C++。&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp; 　　1).&nbsp;&nbsp; 不使用成员函数，直接使用普通C函数，为了实现在C函数中可以访问类的成员变量，可以使用友元操作符(friend)，在C++中将该C函数说明为类的友元即可。这种处理机制与普通的C编程中使用回调函数一样。&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp; 　　2).&nbsp;&nbsp; 使用静态成员函数，静态成员函数不使用this指针作为隐含参数，这样就可以作为回调函数了。静态成员函数具有两大特点：其一，可以在没有类实例的情况下使用；其二，只能访问静态成员变量和静态成员函数，不能访问非静态成员变量和非静态成员函数。由于在C++中使用类成员函数作为回调函数的目的就是为了访问所有的成员变量和成员函数，如果作不到这一点将不具有实际意义。解决的办法也很简单，就是使用一个静态类指针作为类成员，通过在类创建时初始化该静态指针，如pThis=this，然后在回调函数中通过该静态指针就可以访问所有成员变量和成员函数了。这种处理办法适用于只有一个类实例的情况，因为多个类实例将共享静态类成员和静态成员函数，这就导致静态指针指向最后创建的类实例。为了避免这种情况，可以使用回调函数的一个参数来传递this指针，从而实现数据成员共享。<a href="http://www.diybl.com/course/3_program/c++/cppjs/2008411/110115.html"></a></p>
<img src ="http://www.cppblog.com/finehai/aggbug/94766.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/finehai/" target="_blank">Bluesea</a> 2009-08-29 15:45 <a href="http://www.cppblog.com/finehai/archive/2009/08/29/94766.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]临界区,互斥,信号量</title><link>http://www.cppblog.com/finehai/archive/2009/08/19/93770.html</link><dc:creator>Bluesea</dc:creator><author>Bluesea</author><pubDate>Wed, 19 Aug 2009 01:37:00 GMT</pubDate><guid>http://www.cppblog.com/finehai/archive/2009/08/19/93770.html</guid><wfw:comment>http://www.cppblog.com/finehai/comments/93770.html</wfw:comment><comments>http://www.cppblog.com/finehai/archive/2009/08/19/93770.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/finehai/comments/commentRss/93770.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/finehai/services/trackbacks/93770.html</trackback:ping><description><![CDATA[<p><strong><span style="COLOR: #cc99ff">临界区（criticalSection）</span></strong> <br><br>又称阻塞，它能够使一段代码只由一个线程来执行，其它线程被挡在这段代码之外，直到第一个线程执行完代码。临界区的使用主要涉及如下API函数： <br>initializeCriticalSection(), 在临界区首次使用之前，用此函数进行初始化。 <br>deleteCreticalSection(), 在临界区不再使用之前，用此函数释放临界区。 <br>enterCriticalSection(), 在初始化之后，用此函数进入阻塞。 <br>leaveCriticalSection(), 在代码执行完之后，用此函数解除阻塞。 </p>
<p><strong><span style="COLOR: #cc99ff">互斥（mutex）</span> <br></strong><br>互斥比较类似阻塞，关键在于互斥可以跨进程的线程同步，很多只允许应用程序运行一次的实例就是用互斥方法来实现的。互斥用到以下的API函数： <br>createMutex(), 创建互斥对象。 <br>releaseMutex(), 解除互斥关系。 </p>
<p>互斥的一般使用流程： <br>首先createMutex创建互斥对象，然后waitForSingleObject进入互斥环境，当用到同步的代码执行完成后，用releaseMutex解除互斥关系，当所有线程访问完后，调用 <br>closeHandle方法释放互斥对象。 </p>
<p>waitForSingleObject()函数来防止其它线程进入同步区域的代码。 <br>function waitforsingleobject(hHandle: Thandle; dwMilliseconds: DWORD):&nbsp;&nbsp; DWORD; stdcall; <br>这个函数可以使当前线程在dwmilliseconds指定的时间内睡眠，直到hHandle参数指定的对象进入发信号状态为止。一个互斥对象不再被线程拥有时，它就进入发信号状态 <br>当一个进程要终止时，它就进入发信号状态。dwmilliseconds参数可以设为0，这意味着只检查hhandle参数指定的对象是否处理发信号状态，而后立即返回。dwmilliseconds参数设为INFINITE，表示如果信号不出现将一直等下去。 </p>
<p>waitForSingeObject()使用的返回值及其含义： <br>WAIT ABANDONED <br>指定的对象是互斥对象，并且拥有这个互斥对象的线程在没有释放此对象之前就已终止。此时就称互斥对象被抛弃。这种情况下，这个互斥对象归当前线程所有，并把它设为不发信号状态。 <br>WAIT OBJECT 0 <br>指定的对象处于发信号状态 <br>WAIT TIMEOUT <br>等待的时间已过，对象仍然是非发信号状态 </p>
<p>当一个互斥对象不再被一个线程所拥有，它就处于发信号状态。此时首先调用waitForsingleobject()的线程就成为该互斥对象的拥有者，此互斥对象设为不发信号状态。当线程调用releaseMutex()并传递一个互斥对象的句柄作为参数时，这种拥有关系就被解除，互斥对象重新进入发信号状态。除waitforsingleobject()外，还可以使用waitformultipleobject()和msgwaitformultipleobject()，它们可以等待几个对象变为发信号状态。 <br></p>
<p><span style="COLOR: #cc99ff">信号量（semaphore）</span> </p>
<p>另一种使线程同步的技术是使用信号量对象。它是在互斥的基础上建立的。但信号量增加了资源计数的功能，预定数目的线程允许同时进入要同步的代码。用<br>createSemaphore()来创建一个信号量对象，其声明如下： <br><br>function createsemaphore(lpSemaphoreAttributes: pSecurityAttributes; </p>
<p>lInitalCount, lMaximunCount: longint; lpName: pchar): Thandle; stdcall; <br><br>和createmutex()一样，createsemaphore()的第一个参数也是一个指向TsecurityAttributes记录的指针，此参数的缺少值可以设为nil。lInitialcount参数用来指定个信号量的初始计数<br>值，这个值必须在0和lMaximumcount之间。此参数大于0 ，就表示信号量处于发信号状态。当调用waitforsingleobject()时，此计数值就减1。当调用releasesemaphore()时，此计数值加1。参数lMaximumcount指定计数值的最大值。如果这个信号量代表某种资源，那么这个值代表可用资源总数。参数lpName用于给出信号量对象的名称。类似于createmutex()的lpName参数。 <br><br>releaseSemaphore()的声明： <br><br>function releaseSemaphore(hsemaphore: Thandle; lreleasecount: longint; <br>lppreviouscount: pointer): bool; stdcall; <br><br>ireleasecount参数用于指定每次使计数值加多少。如果参数lppreviouscount不为nil，原有的计数值将存储在lppreviouscount里。信号量对象并不属于某个线程。记住，最后一定要调用colsehandle()来释放由createsemaphore()创建的信号量对象的句柄。</p>
<img src ="http://www.cppblog.com/finehai/aggbug/93770.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/finehai/" target="_blank">Bluesea</a> 2009-08-19 09:37 <a href="http://www.cppblog.com/finehai/archive/2009/08/19/93770.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[c++]heap corruption detected</title><link>http://www.cppblog.com/finehai/archive/2009/08/05/92296.html</link><dc:creator>Bluesea</dc:creator><author>Bluesea</author><pubDate>Wed, 05 Aug 2009 08:04:00 GMT</pubDate><guid>http://www.cppblog.com/finehai/archive/2009/08/05/92296.html</guid><wfw:comment>http://www.cppblog.com/finehai/comments/92296.html</wfw:comment><comments>http://www.cppblog.com/finehai/archive/2009/08/05/92296.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/finehai/comments/commentRss/92296.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/finehai/services/trackbacks/92296.html</trackback:ping><description><![CDATA[<p>最近在引用别人提供的一个类时，<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">CSTI</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;ocsti&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;CSTI();<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>delete&nbsp;ocsti;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">程序崩掉</span></div>
<p><br>出现如下错误：<br><br><img style="WIDTH: 522px; HEIGHT: 216px" height=216 alt="" src="http://www.cppblog.com/images/cppblog_com/finehai/memory.jpg" width=522 border=0></p>
<br>经查找，发现这是典型的内存溢出错误,常在内存的delete处发生,而且一般在debug版本中可能出现,release版本中可能并不报错.
<p>出现这个错误的原因一般都是操作new申请的内存溢出,因为在c++中,如果用new分配一段内存,操作的时候改变了该部分的大小,在delete时就会出错.比如说如下部分:<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;p</span><span style="COLOR: #000000">=</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">char</span><span style="COLOR: #000000">[</span><span style="COLOR: #000000">5</span><span style="COLOR: #000000">];<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>strcpy(p,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">aaaaa</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>delete[]&nbsp;p;</span></div>
<p><br>这段代码就会出错,因为申请了一个size为5的内存,但是strcpy过去了一个size为6的字符串,因此破坏了这个指针,运行debug版本的时候 就会出现先前的错误,但是在release版本中,溢出一个字节的内存很有可能是没有错误的,然后潜在的隐患是肯定存在的,因此,我们在debug遇到这样的错误时候一定要仔细检查对new出的指针的操作.<br><br>而我并未对申请的内存做任何操作就报内存溢出的错误，那么可能就是因为new时申请的内存太小，最后经验证发现是因为用的旧的头文件引起的错误，后来换新的头文件后就不在报错了。我试着把新、旧头文件申请的内存大小打出来比较，发现新的头文件果然比旧的内存要大。<br><br>这是在用别人提供的库时遇到的问题，所以在提供别人库时要看看头文件是否也有更新。</p>
<img src ="http://www.cppblog.com/finehai/aggbug/92296.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/finehai/" target="_blank">Bluesea</a> 2009-08-05 16:04 <a href="http://www.cppblog.com/finehai/archive/2009/08/05/92296.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++中静态成员函数访问非静态成员变量</title><link>http://www.cppblog.com/finehai/archive/2009/07/23/90887.html</link><dc:creator>Bluesea</dc:creator><author>Bluesea</author><pubDate>Thu, 23 Jul 2009 01:40:00 GMT</pubDate><guid>http://www.cppblog.com/finehai/archive/2009/07/23/90887.html</guid><wfw:comment>http://www.cppblog.com/finehai/comments/90887.html</wfw:comment><comments>http://www.cppblog.com/finehai/archive/2009/07/23/90887.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/finehai/comments/commentRss/90887.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/finehai/services/trackbacks/90887.html</trackback:ping><description><![CDATA[先看一个class <br><br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;a<br><img id=Codehighlighter1_8_88_Open_Image onclick="this.style.display='none'; Codehighlighter1_8_88_Open_Text.style.display='none'; Codehighlighter1_8_88_Closed_Image.style.display='inline'; Codehighlighter1_8_88_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_8_88_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_8_88_Closed_Text.style.display='none'; Codehighlighter1_8_88_Open_Image.style.display='inline'; Codehighlighter1_8_88_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_8_88_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_8_88_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;FunctionA()<br><img id=Codehighlighter1_41_62_Open_Image onclick="this.style.display='none'; Codehighlighter1_41_62_Open_Text.style.display='none'; Codehighlighter1_41_62_Closed_Image.style.display='inline'; Codehighlighter1_41_62_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_41_62_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_41_62_Closed_Text.style.display='none'; Codehighlighter1_41_62_Open_Image.style.display='inline'; Codehighlighter1_41_62_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;</span><span id=Codehighlighter1_41_62_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_41_62_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;menber&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;menber;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>
<p>编译上述代码，出错。原因很简单大家都知道，静态成员函数不能访问非静态成员，这是因为静态函数属于类而不是属于整个对象，静态函数中的 member可能都没有分配内存。静态成员函数没有隐含的this自变量。所以，它就无法访问自己类的非静态成员。（看过一篇很好的文章<a href="http://blog.csdn.net/starlee/archive/2008/01/24/2062586.aspx"><font color=#000000>《浅析C++中的this指针》</font></a>介绍这个方面的详细内容）</p>
<p>那要想访问怎么办呢？地球人都知道只要将：<br><br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;menber;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">change&nbsp;the&nbsp;line&nbsp;above&nbsp;to:</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;menber;</span></div>
<br>但是这个方法让我们不得不将static function内用到的成员变量都变成static的了，而且static的成员还要显式初始化，有没有更好的方法？答案是肯定的。如下：<br><br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;a<br><img id=Codehighlighter1_8_96_Open_Image onclick="this.style.display='none'; Codehighlighter1_8_96_Open_Text.style.display='none'; Codehighlighter1_8_96_Closed_Image.style.display='inline'; Codehighlighter1_8_96_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_8_96_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_8_96_Closed_Text.style.display='none'; Codehighlighter1_8_96_Open_Image.style.display='inline'; Codehighlighter1_8_96_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_8_96_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_8_96_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;FunctionA(a</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;_a)<br><img id=Codehighlighter1_46_70_Open_Image onclick="this.style.display='none'; Codehighlighter1_46_70_Open_Text.style.display='none'; Codehighlighter1_46_70_Closed_Image.style.display='inline'; Codehighlighter1_46_70_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_46_70_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_46_70_Closed_Text.style.display='none'; Codehighlighter1_46_70_Open_Image.style.display='inline'; Codehighlighter1_46_70_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;</span><span id=Codehighlighter1_46_70_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_46_70_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;a</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">&nbsp;menber&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;menber;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>前提是这个类要分配了内存空间。其实这里我做的就是将一个对象指针作为静态成员函数的&#8220;this&#8221;指针，意在模仿传递非静态成员函数里this变量。
<img src ="http://www.cppblog.com/finehai/aggbug/90887.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/finehai/" target="_blank">Bluesea</a> 2009-07-23 09:40 <a href="http://www.cppblog.com/finehai/archive/2009/07/23/90887.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CreateMutex利用互斥对象实现线程同步实例 </title><link>http://www.cppblog.com/finehai/archive/2009/07/21/90746.html</link><dc:creator>Bluesea</dc:creator><author>Bluesea</author><pubDate>Tue, 21 Jul 2009 09:06:00 GMT</pubDate><guid>http://www.cppblog.com/finehai/archive/2009/07/21/90746.html</guid><wfw:comment>http://www.cppblog.com/finehai/comments/90746.html</wfw:comment><comments>http://www.cppblog.com/finehai/archive/2009/07/21/90746.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/finehai/comments/commentRss/90746.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/finehai/services/trackbacks/90746.html</trackback:ping><description><![CDATA[<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">windows.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>#include&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">iostream.h</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>DWORD&nbsp;WINAPI&nbsp;Fun1Proc(LPVOID&nbsp;lpParameter);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>DWORD&nbsp;WINAPI&nbsp;Fun2Proc(LPVOID&nbsp;lpParameter);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;index</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;tickets</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>HANDLE&nbsp;hMutex;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;main()<br><img id=Codehighlighter1_188_527_Open_Image onclick="this.style.display='none'; Codehighlighter1_188_527_Open_Text.style.display='none'; Codehighlighter1_188_527_Closed_Image.style.display='inline'; Codehighlighter1_188_527_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_188_527_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_188_527_Closed_Text.style.display='none'; Codehighlighter1_188_527_Open_Image.style.display='inline'; Codehighlighter1_188_527_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_188_527_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_188_527_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;HANDLE&nbsp;hThread1,hThread2;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;hThread1</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">CreateThread(NULL,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,Fun1Proc,NULL,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,NULL);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;hThread2</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">CreateThread(NULL,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,Fun2Proc,NULL,</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">,NULL);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;CloseHandle(hThread1);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;CloseHandle(hThread2);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;hMutex</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">CreateMutex(NULL,FALSE,NULL);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">TRUE代表主线程拥有互斥对象&nbsp;但是主线程没有释放该对象&nbsp;&nbsp;互斥对象谁拥有&nbsp;谁释放<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">FLASE代表当前没有线程拥有这个互斥对象</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Sleep(</span><span style="COLOR: #000000">4000</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>DWORD&nbsp;WINAPI&nbsp;Fun1Proc(LPVOID&nbsp;lpParameter)<br><img id=Codehighlighter1_572_841_Open_Image onclick="this.style.display='none'; Codehighlighter1_572_841_Open_Text.style.display='none'; Codehighlighter1_572_841_Closed_Image.style.display='inline'; Codehighlighter1_572_841_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_572_841_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_572_841_Closed_Text.style.display='none'; Codehighlighter1_572_841_Open_Image.style.display='inline'; Codehighlighter1_572_841_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_572_841_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_572_841_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_595_824_Open_Image onclick="this.style.display='none'; Codehighlighter1_595_824_Open_Text.style.display='none'; Codehighlighter1_595_824_Closed_Image.style.display='inline'; Codehighlighter1_595_824_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_595_824_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_595_824_Closed_Text.style.display='none'; Codehighlighter1_595_824_Open_Image.style.display='inline'; Codehighlighter1_595_824_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_595_824_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_595_824_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WaitForSingleObject(hMutex,INFINITE);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(tickets</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_674_736_Open_Image onclick="this.style.display='none'; Codehighlighter1_674_736_Open_Text.style.display='none'; Codehighlighter1_674_736_Closed_Image.style.display='inline'; Codehighlighter1_674_736_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_674_736_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_674_736_Closed_Text.style.display='none'; Codehighlighter1_674_736_Open_Image.style.display='inline'; Codehighlighter1_674_736_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_674_736_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_674_736_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">t1:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">tickets</span><span style="COLOR: #000000">--&lt;&lt;</span><span style="COLOR: #000000">endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br><img id=Codehighlighter1_759_788_Open_Image onclick="this.style.display='none'; Codehighlighter1_759_788_Open_Text.style.display='none'; Codehighlighter1_759_788_Closed_Image.style.display='inline'; Codehighlighter1_759_788_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_759_788_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_759_788_Closed_Text.style.display='none'; Codehighlighter1_759_788_Open_Image.style.display='inline'; Codehighlighter1_759_788_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_759_788_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_759_788_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ReleaseMutex(hMutex);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>DWORD&nbsp;WINAPI&nbsp;Fun2Proc(LPVOID&nbsp;lpParameter)<br><img id=Codehighlighter1_886_1146_Open_Image onclick="this.style.display='none'; Codehighlighter1_886_1146_Open_Text.style.display='none'; Codehighlighter1_886_1146_Closed_Image.style.display='inline'; Codehighlighter1_886_1146_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_886_1146_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_886_1146_Closed_Text.style.display='none'; Codehighlighter1_886_1146_Open_Image.style.display='inline'; Codehighlighter1_886_1146_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_886_1146_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_886_1146_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000">&nbsp;(</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_909_1129_Open_Image onclick="this.style.display='none'; Codehighlighter1_909_1129_Open_Text.style.display='none'; Codehighlighter1_909_1129_Closed_Image.style.display='inline'; Codehighlighter1_909_1129_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_909_1129_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_909_1129_Closed_Text.style.display='none'; Codehighlighter1_909_1129_Open_Image.style.display='inline'; Codehighlighter1_909_1129_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_909_1129_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_909_1129_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WaitForSingleObject(hMutex,INFINITE);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(tickets</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br><img id=Codehighlighter1_988_1041_Open_Image onclick="this.style.display='none'; Codehighlighter1_988_1041_Open_Text.style.display='none'; Codehighlighter1_988_1041_Closed_Image.style.display='inline'; Codehighlighter1_988_1041_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_988_1041_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_988_1041_Closed_Text.style.display='none'; Codehighlighter1_988_1041_Open_Image.style.display='inline'; Codehighlighter1_988_1041_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_988_1041_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_988_1041_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">t2:&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&lt;&lt;</span><span style="COLOR: #000000">tickets</span><span style="COLOR: #000000">--&lt;&lt;</span><span style="COLOR: #000000">endl;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br><img id=Codehighlighter1_1064_1093_Open_Image onclick="this.style.display='none'; Codehighlighter1_1064_1093_Open_Text.style.display='none'; Codehighlighter1_1064_1093_Closed_Image.style.display='inline'; Codehighlighter1_1064_1093_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1064_1093_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1064_1093_Closed_Text.style.display='none'; Codehighlighter1_1064_1093_Open_Image.style.display='inline'; Codehighlighter1_1064_1093_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_1064_1093_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_1064_1093_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">break</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ReleaseMutex(hMutex);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<img src ="http://www.cppblog.com/finehai/aggbug/90746.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/finehai/" target="_blank">Bluesea</a> 2009-07-21 17:06 <a href="http://www.cppblog.com/finehai/archive/2009/07/21/90746.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>防止程序启动两次的方法CreateMutex() </title><link>http://www.cppblog.com/finehai/archive/2009/07/21/90745.html</link><dc:creator>Bluesea</dc:creator><author>Bluesea</author><pubDate>Tue, 21 Jul 2009 09:05:00 GMT</pubDate><guid>http://www.cppblog.com/finehai/archive/2009/07/21/90745.html</guid><wfw:comment>http://www.cppblog.com/finehai/comments/90745.html</wfw:comment><comments>http://www.cppblog.com/finehai/archive/2009/07/21/90745.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/finehai/comments/commentRss/90745.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/finehai/services/trackbacks/90745.html</trackback:ping><description><![CDATA[在工程文件中, WinMain函数里加上以下代码(此代码在BCB6.0下运行):<br><br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">HANDLE&nbsp;hMutex&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;CreateMutex(NULL,&nbsp;</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Process</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(GetLastError()&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;ERROR_ALREADY_EXISTS)<br><img id=Codehighlighter1_115_313_Open_Image onclick="this.style.display='none'; Codehighlighter1_115_313_Open_Text.style.display='none'; Codehighlighter1_115_313_Closed_Image.style.display='inline'; Codehighlighter1_115_313_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_115_313_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_115_313_Closed_Text.style.display='none'; Codehighlighter1_115_313_Open_Image.style.display='inline'; Codehighlighter1_115_313_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_115_313_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_115_313_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CloseHandle(hMutex);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MessageBox(Application</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">Handle,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">程序已经在运行中，不能重复启动！</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">提示</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;MB_OK&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">MB_ICONWARNING);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Application</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">Terminate();<br><img src="http://www.cppblog.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><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Application</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">CreateForm(__classid(TForm1),&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">Form1);</span></div>
<br>主要使用到CreateMutex()函数和GetLastError()以及一个常量ERROR_ALREADY_EXISTS.<br><br>当然, 你的程序有窗体的话, 还可以使用FindWindow(). <br><br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">handle&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;FindWindow(NULL,&nbsp;WindowName.c_str());&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(handle</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">NULL)<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span></div>
<p><br>进程的互斥运行</p>
<p>　　正常情况下，一个进程的运行一般是不会影响到其他正在运行的进程的。但是对于某些有特殊要求的如以独占方式使用串行口等硬件设备的程序就要求在其进程运行期间不允许其他试图使用此端口设备的程序运行的，而且此类程序通常也不允许运行同一个程序的多个实例。这就引出了进程互斥的问题。</p>
<p>　　实现进程互斥的核心思想比较简单：进程在启动时首先检查当前系统是否已经存在有此进程的实例，如果没有，进程将成功创建并设置标识实例已经存在的标记。此后再创建进程时将会通过该标记而知晓其实例已经存在，从而保证进程在系统中只能存在一个实例。具体可以采取内存映射文件、有名事件量、有名互斥量以及全局共享变量等多种方法来实现。下面就分别对其中具有代表性的有名互斥量和全局共享变量这两种方法进行介绍：<br><br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;创建互斥量</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">HANDLE&nbsp;m_hMutex&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;CreateMutex(NULL,&nbsp;FALSE,&nbsp;</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Sample07</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;检查错误代码</span><span style="COLOR: #008000"><br><img id=Codehighlighter1_119_212_Open_Image onclick="this.style.display='none'; Codehighlighter1_119_212_Open_Text.style.display='none'; Codehighlighter1_119_212_Closed_Image.style.display='inline'; Codehighlighter1_119_212_Closed_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_119_212_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_119_212_Closed_Text.style.display='none'; Codehighlighter1_119_212_Open_Image.style.display='inline'; Codehighlighter1_119_212_Open_Text.style.display='inline';" src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(GetLastError()&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;ERROR_ALREADY_EXISTS)&nbsp;</span><span id=Codehighlighter1_119_212_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.cppblog.com/Images/dot.gif"></span><span id=Codehighlighter1_119_212_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;如果已有互斥量存在则释放句柄并复位互斥量</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">　CloseHandle(m_hMutex);<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　m_hMutex&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;NULL;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top>　</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;程序退出</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">　</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;FALSE;<br><img src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<p><br>上面这段代码演示了有名互斥量在进程互斥中的用法。代码的核心是CreateMutex（）对有名互斥量的创建。CreateMutex（）函数可用来创建一个有名或无名的互斥量对象，其函数原型为：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">HANDLE&nbsp;CreateMutex(<br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top>　LPSECURITY_ATTRIBUTES&nbsp;lpMutexAttributes,&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;指向安全属性的指针</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">　BOOL&nbsp;bInitialOwner,&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;初始化互斥对象的所有者</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">　LPCTSTR&nbsp;lpName&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;指向互斥对象名的指针</span><span style="COLOR: #008000"><br><img src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #000000">);</span></div>
<p><br>如果函数成功执行，将返回一个互斥量对象的句柄。如果在CreateMutex（）执行前已经存在有相同名字的互斥量，函数将返回这个已经存在互斥量的句柄，并且可以通过GetLastError（）得到错误代码ERROR_ALREADY_EXIST。可见，通过对错误代码ERROR_ALREADY_EXIST的检测可以实现CreateMutex（）对进程的互斥。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 建立互斥体，用来同步。如果一个线程获取了互斥体，则要获取该互斥体的第二个线程将被挂起，直到第一个线程释放该互斥体。 </p>
<p>参数 <br>lpMutexAttributes <br>指向一个SECURITY_ATTRIBUTES结构的指针，这个结构决定互斥体句柄是否被子进程继承。&nbsp;&nbsp;&nbsp;&nbsp; <br>bInitialOwner <br>布尔类型，决定互斥体的创建者是否为拥有者 <br>lpName <br>指向互斥体名字字符串的指针。互斥体可以有名字。 <br>互斥体的好处是可以在进程间共享</p>
<p>心得体会：<br>&nbsp;&nbsp;&nbsp; CreateMutex() 用于有独占要求的程序 (在其进程运行期间不允许其他使用此端口设备的程序运行，或不允许同名程序运行)。如有同名程序运行，则通过 GetLastError（）得到错误代码 ERROR_ALREADY_EXIST。</p>
<p>刚才又执行了下得出的结果（程序名samp）<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一般情况下：一进入调试阶段，进程管理器中就出现了samp进程，执行到CreateMutex时返回进程句柄，执行到if(GetLastError() == ERROR_ALREADY_EXISTS ) 进行判断时，跳过不执行if中的内容，所以表示没有互斥。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 调试之前先运行debug中的samp.exe再调试：一进入调试阶段，进程管理器中就出现了两个samp进程，执行到CreateMutex时返回进程句柄，执行到if(GetLastError() == ERROR_ALREADY_EXISTS ) 进行判断时，执行if中的内容，表示有互斥。</p>
<img src ="http://www.cppblog.com/finehai/aggbug/90745.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/finehai/" target="_blank">Bluesea</a> 2009-07-21 17:05 <a href="http://www.cppblog.com/finehai/archive/2009/07/21/90745.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>常用的排序算法总结</title><link>http://www.cppblog.com/finehai/archive/2009/07/18/90460.html</link><dc:creator>Bluesea</dc:creator><author>Bluesea</author><pubDate>Sat, 18 Jul 2009 12:53:00 GMT</pubDate><guid>http://www.cppblog.com/finehai/archive/2009/07/18/90460.html</guid><wfw:comment>http://www.cppblog.com/finehai/comments/90460.html</wfw:comment><comments>http://www.cppblog.com/finehai/archive/2009/07/18/90460.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/finehai/comments/commentRss/90460.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/finehai/services/trackbacks/90460.html</trackback:ping><description><![CDATA[<p style="FONT-SIZE: 14pt">实际应用中最常用的排序是快速排序和堆排序。所谓堆排序，就是将最小的一个值放到堆栈的顶部，这样就可以使最后出来的数完成排序。快速排序是不稳定的，堆排序是稳定的。所谓稳定，就是当两个值相等时，排序后两个值的顺序和排序前相同。以上两种排序使用的范围和情况是不同的，一般对于自然生成序列排序使用快速排序效率比较高，而对于已经有一定顺序的序列，使用堆排序比较合适，而且稳定的。<o:p></o:p></p>
<p style="FONT-SIZE: 14pt">这里主要总结常用的5种排序，分别是快速排序，冒泡排序（也叫交换排序），选择排序，shell排序，插入排序。<o:p></o:p></p>
<p style="FONT-SIZE: 14pt">下边分别介绍：<o:p></o:p></p>
<p style="FONT-SIZE: 14pt">1快速排序，就是从一个序列中随意取一个数，然后对剩下的数进行分类，小的放到左边，大的放到右边。如此进行下去知道最后。N(n-1)/2.空间复杂度是o（n）.<o:p></o:p></p>
<p style="FONT-SIZE: 14pt">2冒泡排序，就是从第一个数开始和后一个数比较，然后依情况交换，然后再用第二个和第三个比较交换，如此反复，直到最后一个。一直进行n轮就可以完成排序。<o:p></o:p></p>
<p style="FONT-SIZE: 14pt">3选择排序，就是将一个序列中的最小的放到第一个，然后再将剩下的数据用相同的方式分别放到后一位。它的空间复杂度是O(1).<o:p></o:p></p>
<p style="FONT-SIZE: 14pt">4shell排序，就是将有一定间隔的数进行排序，并且间隔变小，也就是开始是n/2,然后继续变小，一般都是以一半为标准，直到最后间隔只有1，也就完成了排序。需要的空间复杂度是O(1).<o:p></o:p></p>
<p style="FONT-SIZE: 14pt">5插入排序，就比如平时玩的扑克排，一般整理排的时候需要将排排序，当你拿到一张新排的时候，就要比较左边和右边，只有在左右中间的那个值的时候才说明排序成功。它需要的空间复杂度也是O(1).<o:p></o:p></p>
<p style="FONT-SIZE: 14pt">Ps:空间复杂度就是需要另外占用的空间。<o:p></o:p></p>
<p style="FONT-SIZE: 14pt">以上排序中，只有快速排序是O（n），其他都是O（1），因为只有快速排序需要另外再起存储空间，而其他都是在原来空间中增加一个空间就可以。<o:p></o:p></p>
<img src ="http://www.cppblog.com/finehai/aggbug/90460.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/finehai/" target="_blank">Bluesea</a> 2009-07-18 20:53 <a href="http://www.cppblog.com/finehai/archive/2009/07/18/90460.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>堆和栈的区别</title><link>http://www.cppblog.com/finehai/archive/2009/07/18/90459.html</link><dc:creator>Bluesea</dc:creator><author>Bluesea</author><pubDate>Sat, 18 Jul 2009 12:49:00 GMT</pubDate><guid>http://www.cppblog.com/finehai/archive/2009/07/18/90459.html</guid><wfw:comment>http://www.cppblog.com/finehai/comments/90459.html</wfw:comment><comments>http://www.cppblog.com/finehai/archive/2009/07/18/90459.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/finehai/comments/commentRss/90459.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/finehai/services/trackbacks/90459.html</trackback:ping><description><![CDATA[<p>相同：两者都是在内存中</p>
<p>区别：</p>
<p>1堆的容量比较大，栈的容量比较小。</p>
<p>2堆相当于一个全局变量，可以为各种函数使用，栈一般只是为函数内部使用。在建立了新的对象时，可以使用new，也可以直接classtype&nbsp;a；前者就是new，后者就是直接放到了栈中。</p>
<p>3 堆的变量可以动态分配和释放 不用了就放了 节约内存</p>
<p>栈的内存只有在函数结束后才释放。</p>
<img src ="http://www.cppblog.com/finehai/aggbug/90459.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/finehai/" target="_blank">Bluesea</a> 2009-07-18 20:49 <a href="http://www.cppblog.com/finehai/archive/2009/07/18/90459.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>虚函数总结</title><link>http://www.cppblog.com/finehai/archive/2009/07/18/90458.html</link><dc:creator>Bluesea</dc:creator><author>Bluesea</author><pubDate>Sat, 18 Jul 2009 12:44:00 GMT</pubDate><guid>http://www.cppblog.com/finehai/archive/2009/07/18/90458.html</guid><wfw:comment>http://www.cppblog.com/finehai/comments/90458.html</wfw:comment><comments>http://www.cppblog.com/finehai/archive/2009/07/18/90458.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/finehai/comments/commentRss/90458.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/finehai/services/trackbacks/90458.html</trackback:ping><description><![CDATA[<p>1 如果你估计派生类会重新定义一个成员函数，那么你就把基类中的这个函数写成virtual </p>
<p><br>2 通过单一指令调用不同函数，就是多态Polymorphism,"ability to asume many forms" 虚函数是c＋＋语言polymorphism性质以及动态联编的关键 </p>
<p><br>3 既然抽象类中的虚函数不打算被调用，那么就把它设置成纯虚函数。 </p>
<p><br>4 拥有纯虚函数者为抽象类。 </p>
<p><br>5 抽象类不能产生出对象实体，但是我们可以拥有指向抽象类的指针，以便于操作抽象类的各个派生类。 </p>
<p><br>6 虚函数派生下去仍是虚函数，可以不写virtual。 </p>
<img src ="http://www.cppblog.com/finehai/aggbug/90458.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/finehai/" target="_blank">Bluesea</a> 2009-07-18 20:44 <a href="http://www.cppblog.com/finehai/archive/2009/07/18/90458.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于回调函数</title><link>http://www.cppblog.com/finehai/archive/2009/07/18/90457.html</link><dc:creator>Bluesea</dc:creator><author>Bluesea</author><pubDate>Sat, 18 Jul 2009 12:41:00 GMT</pubDate><guid>http://www.cppblog.com/finehai/archive/2009/07/18/90457.html</guid><wfw:comment>http://www.cppblog.com/finehai/comments/90457.html</wfw:comment><comments>http://www.cppblog.com/finehai/archive/2009/07/18/90457.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/finehai/comments/commentRss/90457.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/finehai/services/trackbacks/90457.html</trackback:ping><description><![CDATA[<p>回调函数的应用情况，是为了整个项目中的程序各种不同的程序模块的调用。一般是对计数的情况进行必要的操作。 </p>
<p><br>举例函数模块A，函数模块B，如果函数模块B中的某个函数b要在固定时间n调用函数A中的某个函数a。 这里首先明白哪个是回调函数，这里的函数a就是回调函数。 </p>
<p>如果要完成这个任务，就要在函数模块B中增加一个函数，叫注册函数c，当时间满足了规定的n，就要调用A中的a， B中的注册函数c并不知道要执行什么操作，它只是负责在一定的时机调用函数a。 </p>
<p>c函数一般存放了函数a的指针，以便调用，还有就是定时的时间参数。</p>
<p>这里需要注意几点：</p>
<p>1函数模块A和函数模块B必须在同一个物理地址块中，如果是在不同的物理地址的程序模块是不可以使用的。</p>
<p>2一般应用到定时的调用某个模块的函数</p>
<p>3被调用的函数a可以没有实现</p>
<p>举个例子，就是，买米a，老板b不在，你留电话c，他见电话号码打给你。</p>
<img src ="http://www.cppblog.com/finehai/aggbug/90457.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/finehai/" target="_blank">Bluesea</a> 2009-07-18 20:41 <a href="http://www.cppblog.com/finehai/archive/2009/07/18/90457.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>送给正在学习C++朋友</title><link>http://www.cppblog.com/finehai/archive/2009/07/18/90456.html</link><dc:creator>Bluesea</dc:creator><author>Bluesea</author><pubDate>Sat, 18 Jul 2009 12:38:00 GMT</pubDate><guid>http://www.cppblog.com/finehai/archive/2009/07/18/90456.html</guid><wfw:comment>http://www.cppblog.com/finehai/comments/90456.html</wfw:comment><comments>http://www.cppblog.com/finehai/archive/2009/07/18/90456.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/finehai/comments/commentRss/90456.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/finehai/services/trackbacks/90456.html</trackback:ping><description><![CDATA[<div class=xspace-itemmessage id=xspace-showmessage>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.把C++当成一门新的语言学习（和C没啥关系！真的。）； <br><br>　　2.看《Thinking In C++》，不要看《C++变成死相》； <br><br>　　3.看《The C++ Programming Language》和《Inside The C++ Object Model》,不要因为他们很难而我们自己是初学者所以就不看； <br><br>　　4.不要被VC、BCB、BC、MC、TC等词汇所迷惑——他们都是集成开发环境，而我们要学的是一门语言； <br><br>　　5.不要放过任何一个看上去很简单的小编程问题——他们往往并不那么简单，或者可以引伸出很多知识点； <br><br>　　6.会用Visual C++，并不说明你会C++； <br><br>　　7.学class并不难，template、STL、generic programming也不过如此——难的是长期坚持实践和不遗余力的博览群书； <br><br>　　8.如果不是天才的话，想学编程就不要想玩游戏——你以为你做到了，其实你的C++水平并没有和你通关的能力一起变高——其实可以时刻记住：学C++是为了编游戏的； <br><br>　　9.看Visual C++的书，是学不了C++语言的； <br><br>　　10.浮躁的人容易说：XX语言不行了，应该学YY；——是你自己不行了吧！？ <br><br>　　11.浮躁的人容易问：我到底该学什么；——别问，学就对了； <br><br>　　12.浮躁的人容易问：XX有钱途吗；——建议你去抢银行； <br><br>　　13.浮躁的人容易说：我要中文版！我英文不行！——不行？学呀！ <br><br>　　14.浮躁的人容易问：XX和YY哪个好；——告诉你吧，都好——只要你学就行； <br><br>　　15.浮躁的人分两种：a)只观望而不学的人；b)只学而不坚持的人； <br><br>　　16.把时髦的技术挂在嘴边，还不如把过时的技术记在心里； <br>　　17.C++不仅仅是支持面向对象的程序设计语言； <br><br>　　18.学习编程最好的方法之一就是阅读源代码； <br><br>　　19.在任何时刻都不要认为自己手中的书已经足够了； <br><br>　　20.请阅读《The Standard C++ Bible》(中文版：标准C++宝典)，掌握C++标准； <br><br>　　21.看得懂的书，请仔细看；看不懂的书，请硬着头皮看； <br><br>　　22.别指望看第一遍书就能记住和掌握什么——请看第二遍、第三遍； <br><br>　　23.请看《Effective C++》和《More Effective C++》以及《Exceptional C++》； <br><br>　　24.不要停留在集成开发环境的摇篮上，要学会控制集成开发环境，还要学会用命令行方式处理程序； <br><br>　　25.和别人一起讨论有意义的C++知识点，而不是争吵XX行不行或者YY与ZZ哪个好； <br><br>　　26.请看《程序设计实践》，并严格的按照其要求去做； <br><br>　　27.不要因为C和C++中有一些语法和关键字看上去相同，就认为它们的意义和作用完全一样； <br><br>　28.C++绝不是所谓的C的&#8220;扩充&#8221;——如果C++一开始就起名叫Z语言，你一定不会把C和Z语言联系得那么紧密； <br><br>　　29.请不要认为学过XX语言再改学C++会有什么问题——你只不过又在学一门全新的语言而已； <br><br>　　30.读完了《Inside The C++ Object Model》以后再来认定自己是不是已经学会了C++； <br><br>　　31.学习编程的秘诀是：编程，编程，再编程； <br><br>　　32.请留意下列书籍：《C++面向对象高效编程（C++ Effective Object-Oriented Software Construction）》《面向对象软件构造(Object-Oriented Software Construction)》《设计模式（Design Patterns）》《The Art of Computer Programming》； <br>　　33.记住：面向对象技术不只是C++专有的； <br><br>　　34.请把书上的程序例子亲手输入到电脑上实践，即使配套光盘中有源代码； <br><br>　　35.把在书中看到的有意义的例子扩充； <br><br>　　36.请重视C++中的异常处理技术，并将其切实的运用到自己的程序中； <br><br>　　37.经常回顾自己以前写过的程序，并尝试重写，把自己学到的新知识运用进去； <br><br>　　38.不要漏掉书中任何一个练习题——请全部做完并记录下解题思路； <br><br>　　39.C++语言和C++的集成开发环境要同时学习和掌握； <br><br>　　40.既然决定了学C++,就请坚持学下去，因为学习程序设计语言的目的是掌握程序设计技术，而程序设计技术是跨语言的； <br><br>　　41.就让C++语言的各种平台和开发环境去激烈的竞争吧，我们要以学习C++语言本身为主； <br><br>　　42.当你写C++程序写到一半却发现自己用的方法很拙劣时，请不要马上停手；请尽快将余下的部分粗略的完成以保证这个设计的完整性，然后分析自己的错误并重新设计和编写（参见43）； <br><br>　　43.别心急，设计C++的class确实不容易；自己程序中的class和自己的class设计水平是在不断的编程实践中完善和发展的； <br><br>　　44.决不要因为程序&#8220;很小&#8221;就不遵循某些你不熟练的规则——好习惯是培养出来的，而不是一次记住的； <br><br>　　45.每学到一个C++难点的时候，尝试着对别人讲解这个知识点并让他理解——你能讲清楚才说明你真的理解了； <br><br>　　46.记录下在和别人交流时发现的自己忽视或不理解的知识点； <br><br>　　47.请不断的对自己写的程序提出更高的要求,哪怕你的程序版本号会变成Version 100.XX； <br><br>　　48.保存好你写过的所有的程序——那是你最好的积累之一； <br><br>　　49.请不要做浮躁的人； <br><br>　　50.请热爱C++! </div>
<img src ="http://www.cppblog.com/finehai/aggbug/90456.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/finehai/" target="_blank">Bluesea</a> 2009-07-18 20:38 <a href="http://www.cppblog.com/finehai/archive/2009/07/18/90456.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>内存分配方式</title><link>http://www.cppblog.com/finehai/archive/2009/07/18/90453.html</link><dc:creator>Bluesea</dc:creator><author>Bluesea</author><pubDate>Sat, 18 Jul 2009 12:08:00 GMT</pubDate><guid>http://www.cppblog.com/finehai/archive/2009/07/18/90453.html</guid><wfw:comment>http://www.cppblog.com/finehai/comments/90453.html</wfw:comment><comments>http://www.cppblog.com/finehai/archive/2009/07/18/90453.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/finehai/comments/commentRss/90453.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/finehai/services/trackbacks/90453.html</trackback:ping><description><![CDATA[<p><font face=宋体>内存分配方式<br>-------------------------------------------------------------------------</font></p>
<p>&#160;</p>
<p><font face=宋体>内存分配方式有三种：<br>（1） 从<font style="BACKGROUND-COLOR: #ff00ff">静态存储区</font>域分配。内存在程序编译的时候就已经分配好，这块内存在程序的整个运行期间都存在。 例如全局变量static变量。<br>（2） 在<font style="BACKGROUND-COLOR: #ff00ff">栈上</font>创建。在执行函数时，函数内局部变量的存储单元都可以在栈上创建，函数执行结束时这些存储 单元自动被释放。栈内存 分配运算内置于处理器的指令集中，<font style="BACKGROUND-COLOR: #00ff40">效率很高，但是分配的内存容量有限</font>。<br>（3） 从<font style="BACKGROUND-COLOR: #ff00ff">堆上</font>分配，亦称动态内存分配。程序在运行的时候用<font style="BACKGROUND-COLOR: #00ff40">malloc或new申请任意多少的内存</font>，程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定，使用非常灵活，但问题也最多。</font></p>
<p><font face=宋体>常见的内存错误及其对策<br></font></p>
<p><font face=宋体>-------------------------------------------------------------------------</font></p>
<p>&#160;</p>
<p><font face=宋体>发生内存错误是件非常麻烦的事情。编译器不能自动发现这些错误，通常是在程序运行时才能捕捉到。而这些错误大多没有明显的症状，时隐时现，增加了改错的难度。有时用户怒气冲冲地把你找来，程序却没有发生任何问题，你一走，错误又发作了。</font></p>
<p>&#160;</p>
<p><font face=宋体>常见的内存错误及其对策如下：</font></p>
<p><font face=宋体>
<table style="BORDER-RIGHT: #999 1px solid; BORDER-TOP: #999 1px solid; FONT-SIZE: 12px; BORDER-LEFT: #999 1px solid; WIDTH: 80%; BORDER-BOTTOM: #999 1px solid" align=center>
    <tbody>
        <tr>
            <td><font style="BACKGROUND-COLOR: #ffff80">1&gt;内存分配未成功，却使用了它。</font></td>
        </tr>
    </tbody>
</table>
<br>------------------------------------------<br>编程新手常犯这种错误，因为他们没有意识到内存分配会不成功。常用解决办法是，在使用内存之前检 指针是否为NULL。<font style="BACKGROUND-COLOR: #0080ff">如果指针p是函数的参数，那么在函数的入口处用assert(p!=NULL)进行检查。</font>如果 是用malloc或new来申请内存，应该用if(p==NULL) 或if(p=NULL)进行防错处理。</font></p>
<p>&#160;</p>
<p><font face=宋体>
<table style="BORDER-RIGHT: #999 1px solid; BORDER-TOP: #999 1px solid; FONT-SIZE: 12px; BORDER-LEFT: #999 1px solid; WIDTH: 80%; BORDER-BOTTOM: #999 1px solid" align=center>
    <tbody>
        <tr>
            <td><font style="BACKGROUND-COLOR: #ffff80">2&gt;内存分配虽然成功，但是尚未初始化就引用它</font></td>
        </tr>
    </tbody>
</table>
<br>------------------------------------------<br>犯这种错误主要有两个起因：一是没有初始化的观念；二是误以为内存的缺省初值全为零，导致引用初 错误（例如数组）。<br>内存的缺省初值究竟是什么并没有统一的标准，尽管有些时候为零值，我们宁可信其无不可信其有。<font style="BACKGROUND-COLOR: #0080ff">所 以无论用何种方式创建数组，都别忘了赋初值，即便是赋零值也不可省略，不要嫌麻烦。</font></font></p>
<p>&#160;</p>
<p><font face=宋体>
<table style="BORDER-RIGHT: #999 1px solid; BORDER-TOP: #999 1px solid; FONT-SIZE: 12px; BORDER-LEFT: #999 1px solid; WIDTH: 80%; BORDER-BOTTOM: #999 1px solid" align=center>
    <tbody>
        <tr>
            <td><font style="BACKGROUND-COLOR: #ffff80">3&gt;内存分配成功并且已经初始化，但操作越过了内存的边界。</font></td>
        </tr>
    </tbody>
</table>
<br>------------------------------------------<br>例如在使用数组时经常发生下标"多1"或者"少1"的操作。特别是在for循环语句中，循环次数很容易搞错，导致数组操作越界。</font></p>
<p>&#160;</p>
<p><font face=宋体>
<table style="BORDER-RIGHT: #999 1px solid; BORDER-TOP: #999 1px solid; FONT-SIZE: 12px; BORDER-LEFT: #999 1px solid; WIDTH: 80%; BORDER-BOTTOM: #999 1px solid" align=center>
    <tbody>
        <tr>
            <td><font style="BACKGROUND-COLOR: #ffff80">4&gt;忘记了释放内存，造成内存泄露。</font></td>
        </tr>
    </tbody>
</table>
------------------------------------------<br>含有这种错误的函数每被调用一次就丢失一块内存。刚开始时系统的内存充足，你看不到错误。终有一次程序突然死掉，系统出现提示：内存耗尽。动态内存的申请与释放必须配对，程序中malloc与free的使用次数一定要相同，否则肯定有错误（new/delete同理）。</font></p>
<p>&#160;</p>
<p><font face=宋体>
<table style="BORDER-RIGHT: #999 1px solid; BORDER-TOP: #999 1px solid; FONT-SIZE: 12px; BORDER-LEFT: #999 1px solid; WIDTH: 80%; BORDER-BOTTOM: #999 1px solid" align=center>
    <tbody>
        <tr>
            <td><font style="BACKGROUND-COLOR: #ffff80">5&gt;释放了内存却继续使用它。</font></td>
        </tr>
    </tbody>
</table>
<br>------------------------------------------<br>有三种情况：<br>（1）
<table style="BORDER-RIGHT: #999 1px solid; BORDER-TOP: #999 1px solid; FONT-SIZE: 12px; BORDER-LEFT: #999 1px solid; WIDTH: 80%; BORDER-BOTTOM: #999 1px solid" align=center>
    <tbody>
        <tr>
            <td>程序中的对象调用关系过于复杂，实在难以搞清楚某个对象究竟是否已经释放了内存，此时应该重新设计数据结构，从根本上解决对象管理的混乱局面。</td>
        </tr>
    </tbody>
</table>
<br>（2）
<table style="BORDER-RIGHT: #999 1px solid; BORDER-TOP: #999 1px solid; FONT-SIZE: 12px; BORDER-LEFT: #999 1px solid; WIDTH: 80%; BORDER-BOTTOM: #999 1px solid" align=center>
    <tbody>
        <tr>
            <td>函数的return语句写错了，注意不要返回指向"栈内存"的"指针"或者"引用"，因为该内存在函数体结束时被自动销毁。</td>
        </tr>
    </tbody>
</table>
<br>（3）
<table style="BORDER-RIGHT: #999 1px solid; BORDER-TOP: #999 1px solid; FONT-SIZE: 12px; BORDER-LEFT: #999 1px solid; WIDTH: 80%; BORDER-BOTTOM: #999 1px solid" align=center>
    <tbody>
        <tr>
            <td>使用free或delete释放了内存后，没有将指针设置为NULL。导致产生"野指针"。</td>
        </tr>
    </tbody>
</table>
</font>
<p>&#160;</p>
<font face=宋体>【规则1】用malloc或new申请内存之后，应该立即检查指针值是否为NULL。防止使用指针值为NULL的内存。<br>【规则2】<font style="BACKGROUND-COLOR: #0080ff">不要忘记为数组和动态内存赋初值</font>。防止将未被初始化的内存作为右值使用。<br>【规则3】避免数组或指针的下标越界，特别要当心发生"多1"或者"少1"操作。<br>【规则4】动态内存的申请与释放必须配对，防止内存泄漏。<br>【规则5】<font style="BACKGROUND-COLOR: #0080ff">用free或delete释放了内存之后，立即将指针设置为NULL，防止产生"野指针"。</font></font>
<p>&#160;</p>
<p>&#160;</p>
<p><font face=宋体>-------------------------------------------------------------------------</font></p>
<p>&#160;</p>
<p><font face=宋体>指针与数组的对比<br>C++/C程序中，指针和数组在不少地方可以相互替换着用，让人产生一种错觉，以为两者是等价的。<br>&nbsp;&nbsp;&nbsp;&nbsp;<br>数组<br>-------------<br>数组要么在<font style="BACKGROUND-COLOR: #ffff80">静态存储区被创建（如全局数组</font>），要么在<font style="BACKGROUND-COLOR: #ffff80">栈上被创建</font>。数组名对应着（而不是指向）一块内存，其<font style="BACKGROUND-COLOR: #ff0000">地址与容量</font>在生命期内<font style="BACKGROUND-COLOR: #ff0000">保持不变</font>，只有<font style="BACKGROUND-COLOR: #ff0000">数组的内容可以改变</font>。</font></p>
<p><font face=宋体>指针<br>--------------<br>指针可以随时指向任意类型的内存块，它的特征是"可变"，所以我们常用指针来操作动态内存。指针远比数组灵活，但也更危险。</font></p>
<p>&#160;</p>
<p><font face=宋体>下面以字符串为例比较指针与数组的特性。</font></p>
<p><font face=宋体>1.修改内容<br>------------------------------------------<br>示例1中，字符数组a的容量是6个字符，其内容为hello\0。a的内容可以改变，如a[0]= 'X'。<br>指针p指向常量字符串"world"（位于静态存储区，内容为world\0），<font style="BACKGROUND-COLOR: #ff0000">常量字符串的内容是不可以被修改的。<br></font>从语法上看，编译器并不觉得语句p[0]= &#8216;X'有什么不妥，但是该语句企图修改常量字符串的内容而导致运行错误。<br></font></p>
<p><font face=宋体>示例7-3-1 修改数组和指针的内容<br>&nbsp;&nbsp; ------------------------------<br>&nbsp;&nbsp; char a[] = "hello";<br>&nbsp;&nbsp; a[0] = 'X';<br>&nbsp;&nbsp; cout &lt;&lt; a &lt;&lt; endl;<br>&nbsp;&nbsp; char *p = "world"; // 注意p指向常量字符串&nbsp;&nbsp;<br>&nbsp;&nbsp; p[0] = 'X'; // 编译器不能发现该错误cout &lt;&lt; p &lt;&lt; endl;<br>&nbsp;&nbsp;</font></p>
<p><font face=宋体>2.内容复制与比较<br>------------------------------------------<br>数组复制<br>--------<br>不能对数组名进行直接复制与比较。示例2中，若想把数组a的内容复制给数组b，不能用语句 b = a ，否则将产生编译错误。应该用标准库函数<font style="BACKGROUND-COLOR: #0080ff">strcpy进行复制</font>。同理，比较b和a的内容是否相同，不能用if(b==a) 来判断，应该用<font style="BACKGROUND-COLOR: #0080ff">标准库函数strcmp</font>进行比较。</font></p>
<p><font face=宋体>指针复制<br>--------<br>语句p = a 并不能把a的内容复制指针p，而是把a的地址赋给了p。要想复制a的内容，<font style="BACKGROUND-COLOR: #0080ff">可以先用库函数malloc为p申请一块容量为strlen(a)+1个字符的内存，再用strcpy进行字符串复制</font>。同理，语句if(p==a) 比较的不是内容而是地址，应该用库函数strcmp来比较。</font></p>
<p><font face=宋体>示例2 数组和指针的内容复制与比较<br>-----------------------------------<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 数组...<br>char a[] = "hello";<br>char b[10];<br>strcpy(b, a); //不能用b = a;<br>if(strcmp(b, a) == 0) // 不能用 if (b == a)...<br>// 指针...<br>int len = strlen(a);<br>char *p = (char *)malloc(sizeof(char)*(len+1));&nbsp;&nbsp;<br>strcpy(p,a); // 不要用 p = a;<br>if(strcmp(p, a) == 0) // 不要用 if (p == a)...</font></p>
<p><font face=宋体></font></p>
<p><font face=宋体>3 计算内存容量<br>------------------------------------------<br>数组<br>----<br>用运算符sizeof可以计算出数组的容量（字节数）。<br>示例3中，sizeof(a)的值是12（注意别忘了'\0'）。</font></p>
<p><font face=宋体>指针<br>----<br><font style="BACKGROUND-COLOR: #0080ff">指针p指向a，但是sizeof(p)的值却是4</font>。这是因为sizeof(p)得到的是一个指针变量的字节数，<br>相当于sizeof(char*)，而不是p所指的内存容量。</font></p>
<p><font style="BACKGROUND-COLOR: #ff0000" face=宋体>C++/C语言没有办法知道指针所指的内存容量，除非在申请内存时记住它。</font></p>
<p><font face=宋体>注意<br>----<br><font style="BACKGROUND-COLOR: #ffff80">当数组作为函数的参数进行传递时，该数组自动退化为同类型的指针。</font><br>示例3中，不论数组a的容量是多少，sizeof(a)始终等于sizeof(char *)。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 示例3 计算数组和指针的内存容量<br>-----------------------------<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char a[] = "hello world";<br>char *p = a; cout&lt;&lt; sizeof(a) &lt;&lt; endl;// 12字节<br>cout&lt;&lt; sizeof(p) &lt;&lt; endl;// 4字节</font></p>
<p><font face=宋体>示例3（b） 数组退化为指针<br>-----------------------------<br>void Func(char a[100])<br>{<br>cout&lt;&lt; sizeof(a) &lt;&lt; endl;// 4字节而不是100字节<br>&nbsp;&nbsp; }</font></p>
<p><font face=宋体>4、指针参数是如何传递内存的？<br>------------------------------------------<br>如果函数的参数是一个指针，不要指望用该指针去申请动态内存。<br>示例4-1中，Test函数的语句GetMemory(str, 200)并没有使str获得期望的内存，str依旧是NULL，为什么？</font></p>
<p><font face=宋体>示例4-1 试图用指针参数申请动态内存<br>----------------------------------<br>void GetMemory(char *p, int num)<br>{<br>p = (char *)malloc(sizeof(char) * num);<br>}<br>void Test(void)<br>{<br>char *str = NULL;<br>GetMemory(str, 100);// str 仍然为 NULL<br>strcpy(str, "hello"); // 运行错误<br>}</font></p>
<p><font face=宋体>毛病出在函数GetMemory中。<font style="BACKGROUND-COLOR: #ff00ff">编译器总是要为函数的每个参数制作临时副本</font>，<br>指针参数p的副本是 _p，编译器使 _p = p。如果函数体内的程序修改了_p的内容，<br>就导致参数p的内容作相应的修改。这就是指针可以用作输出参数的原因。<br>在本例中，_p申请了新的内存，只是把_p所指的内存地址改变了，但是p丝毫未变。<br>所以函数GetMemory并不能输出任何东西。<br>事实上，每执行一次GetMemory就会泄露一块内存，因为没有用free释放内存。</font></p>
<p><font face=宋体>如果非得要用指针参数去申请内存，那么应该改用"指向指针的指针"，见示例4-2。</font></p>
<p><font face=宋体>示例4-2用指向指针的指针申请动态内存<br>------------------------------------<br>void GetMemory2(char **p, int num)<br>{<br>*p = (char *)malloc(sizeof(char) * num);<br>}<br>void Test2(void)<br>{<br>char *str = NULL;<br>GetMemory2(&amp;str, 100); // 注意参数是 &amp;str，而不是str<br>strcpy(str, "hello");<br>cout&lt;&lt; str &lt;&lt; endl;<br>free(str);<br>}</font></p>
<p><font face=宋体><br>由于"指向指针的指针"这个概念不容易理解，我们可以用函数返回值来传递动态内存。<br>这种方法更加简单，见示例4-3。</font></p>
<p>示例4-3 用函数返回值来传递动态内存<br>-----------------------------------<br>char *GetMemory3(int num)<br>{<br>char *p = (char *)malloc(sizeof(char) * num);<br>return p;<br>}<br>void Test3(void)<br>{<br>char *str = NULL;<br>str = GetMemory3(100);<br>strcpy(str,"hello");<br>cout&lt;&lt; str &lt;&lt; endl;<br>free(str);<br>}</p>
<p><br>用函数返回值来传递动态内存这种方法虽然好用，但是常常有人把return语句用错了。这里强调不要用return语句返回指向"栈内存"的指针，因为该内存在函数结束时自动消亡，见示例4-4。</p>
<p>示例4-4 return语句返回指向"栈内存"的指针<br>--------------------------------------------<br>char *GetString(void)<br>{<br>char p[] = "hello world";<br>return p;// 编译器将提出警告<br>}<br>void Test4(void)<br>{<br>char *str = NULL;str = GetString();// str 的内容是垃圾<br>cout&lt;&lt; str &lt;&lt; endl;<br>}</p>
<p><br>用调试器逐步跟踪Test4，发现执行str = GetString语句后str不再是NULL指针，<br>但是str的内容不是"hello world"而是垃圾。</p>
<p>如果把示例4-4改写成示例4-5，会怎么样？</p>
<p>示例4-5 return语句返回常量字符串<br>-----------------------------------<br>char *GetString2(void)<br>{<br>char *p = "hello world";<br>return p;<br>}<br>void Test5(void)<br>{<br>char *str = NULL;<br>str = GetString2();<br>cout&lt;&lt; str &lt;&lt; endl;<br>}</p>
<p><br>函数Test5运行虽然不会出错，但是函数GetString2的设计概念却是错误的。<br>因为GetString2内的"hello world"是常量字符串，位于静态存储区，它在程序生命期内恒定不变。<br>无论什么时候调用GetString2，它返回的始终是同一个"只读"的内存块。</p>
<p>&#160;</p>
<p>5 free和delete把指针怎么啦？<br>------------------------------------------<br><font style="BACKGROUND-COLOR: #ff0000">别看free和delete的名字恶狠狠的（尤其是delete），<br>它们只是把指针所指的内存给释放掉，但并没有把指针本身干掉。</font><br>用调试器跟踪示例5，发现指针p被free以后其地址仍然不变（非NULL），<br>只是该地址对应的内存是垃圾，p成了"野指针"。<br>如果此时不把p设置为NULL，会让人误以为p是个合法的指针。<br>如果程序比较长，我们有时记不住p所指的内存是否已经被释放，<br>在继续使用p之前，通常会用语句if (p !=NULL)进行防错处理。<br>很遗憾，此时if语句起不到防错作用，因为即便p不是NULL指针，<br>它也不指向合法的内存块。</p>
<p>示例5 p成为野指针<br>--------------------<br>char *p = (char *) malloc(100);<br>strcpy(p, "hello");<br>free(p);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // p 所指的内存被释放，但是p所指的地址仍然不变 ...<br>if(p != NULL) // 没有起到防错作用<br>{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcpy(p, "world"); // 出错<br>}</p>
<p>&#160;</p>
<p>6 动态内存会被自动释放吗？<br>------------------------------------------<br>函数体内的局部变量在函数结束时自动消亡。很多人误以为示例6是正确的。<br>理由是p是局部的指针变量，它消亡的时候会让它所指的动态内存一起完蛋。这是错觉！</p>
<p>示例7-6 试图让动态内存自动释放<br>------------------------------<br>void Func(void)<br>{<br>char *p = (char *) malloc(100); // 动态内存会自动释放吗？<br>}</p>
<p><br>我们发现指针有一些"似是而非"的特征：<br>------------------------------------<br><font style="BACKGROUND-COLOR: #ff0000">（1）指针消亡了，并不表示它所指的内存会被自动释放。<br>（2）内存被释放了，并不表示指针会消亡或者成了NULL指针。</font><br>&nbsp;&nbsp;&nbsp;&nbsp; 这表明释放内存并不是一件可以草率对待的事。也许有人不服气，<br>&nbsp;&nbsp;&nbsp;&nbsp; 一定要找出可以草率行事的理由：<br>&nbsp;&nbsp;&nbsp;&nbsp; 如果程序终止了运行，一切指针都会消亡，动态内存会被操作系统回收。<br>&nbsp;&nbsp;&nbsp;&nbsp; 既然如此，在程序临终前，就可以不必释放内存、不必将指针设置为NULL了。<br>&nbsp;&nbsp;&nbsp;&nbsp; 终于可以偷懒而不会发生错误了吧？<br>想得美。如果别人把那段程序取出来用到其它地方怎么办？</p>
<p>&#160;</p>
<p>7 杜绝"野指针"<br>------------------------------------------<br>"野指针"不是NULL指针，是指向"垃圾"内存的指针。<br>人们一般不会错用NULL指针，因为用if语句很容易判断。<br>但是"野指针"是很危险的，if语句对它不起作用。</p>
<p>"野指针"的成因主要有两种：</p>
<p>（1）指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针，<br>它的缺省值是随机的，它会乱指一气。所以，指针变量在创建的同时应当被初始化，<br>要么将指针设置为NULL，要么让它指向合法的内存。例如<br>char *p = NULL;<br>char *str = (char *) malloc(100);</p>
<p>（2）指针p被free或者delete之后，没有置为NULL，让人误以为p是个合法的指针。参见7.5节。</p>
<p>（3）指针操作超越了变量的作用范围。这种情况让人防不胜防，示例程序如下：<br>class A<br>{<br>public:<br>void Func(void){ cout &lt;&lt; "Func of class A" &lt;&lt; endl;<br>}</p>
<p>void Test(void)<br>{<br>A *p;<br>{<br>A a;<br>p = &amp;a; // 注意 a 的生命期<br>}<br>p-&gt;Func();// p是"野指针"<br>}</p>
<p>函数Test在执行语句p-&gt;Func()时，对象a已经消失，而p是指向a的，所以p就成了"野指针"。<br>但奇怪的是我运行这个程序时居然没有出错，这可能与编译器有关。</p>
<p>&#160;</p>
<p>8 有了malloc/free为什么还要new/delete ？<br>------------------------------------------<br>malloc与free是C++/C语言的标准库函数，new/delete是C++的运算符。<br>它们都可用于申请动态内存和释放内存。</p>
<p>对于非内部数据类型的对象而言，光用maloc/free无法满足动态对象的要求。<br>对象在创建的同时要自动执行构造函数，对象在消亡之前要自动执行析构函数。<br>由于malloc/free是库函数而不是运算符，不在编译器控制权限之内，<br>不能够把执行构造函数和析构函数的任务强加于malloc/free。<br><br><font style="BACKGROUND-COLOR: #ff0000">因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new，以及一个能完成清理与释放内存工作的运</font></p>
<p>算符delete。注意new/delete不是库函数。<br>我们先看一看malloc/free和new/delete如何实现对象的动态内存管理，见示例8。</p>
<p>示例8 用malloc/free和new/delete如何实现对象的动态内存管理<br>-------------------------------------------------------------<br>class Obj<br>{<br>public :<br>Obj(void){ cout &lt;&lt; "Initialization" &lt;&lt; endl; }<br>~Obj(void){cout &lt;&lt; "Destroy" &lt;&lt; endl; }<br>void Initialize(void){ cout &lt;&lt; "Initialization" &lt;&lt; endl; }<br>void&nbsp;&nbsp;&nbsp; Destroy(void){ cout &lt;&lt; "Destroy" &lt;&lt; endl; }<br>};<br>void UseMallocFree(void)<br>{<br>Obj *a = (obj *)malloc(sizeof(obj)); // 申请动态内存<br>a-&gt;Initialize(); // 初始化<br>a-&gt;Destroy(); // 清除工作<br>free(a);// 释放内存<br>}<br>void UseNewDelete(void)<br>{<br>Obj *a = new Obj;// 申请动态内存并且初始化<br>delete a;// 清除并且释放内存<br>}</p>
<p>类Obj的函数Initialize模拟了构造函数的功能，函数Destroy模拟了析构函数的功能。<br>函数UseMallocFree中，由于malloc/free不能执行构造函数与析构函数，<br>必须调用成员函数Initialize和Destroy来完成初始化与清除工作。<br>函数UseNewDelete则简单得多。</p>
<p>所以我们不要企图用malloc/free来完成动态对象的内存管理，应该用new/delete。<br>由于内部数据类型的"对象"没有构造与析构的过程，对它们而言malloc/free和new/delete是等价的。<br><br>既然new/delete的功能完全覆盖了malloc/free，为什么C++不把malloc/free淘汰出局呢？<br>这是因为C++程序经常要调用C函数，而C程序只能用malloc/free管理动态内存。</p>
<p>如果用free释放"new创建的动态对象"，那么该对象因无法执行析构函数而可能导致程序出错。<br>如果用delete释放"malloc申请的动态内存"，理论上讲程序不会出错，但是该程序的可读性很差。<br>所以new/delete必须配对使用，malloc/free也一样。</p>
<p>&#160;</p>
<p>9 内存耗尽怎么办？<br>------------------------------------------<br>如果在申请动态内存时找不到足够大的内存块malloc和new将返回NULL指针，宣告内存申请失败。<br>通常有三种方式处理"内存耗尽"问题。</p>
<p>（1）判断指针是否为NULL，如果是则马上用return语句终止本函数。例如：<br>void Func(void)<br>{<br>A *a = new A;<br>if(a == NULL)<br>{<br>&nbsp;&nbsp; return;<br>}<br>...<br>}</p>
<p>（2）判断指针是否为NULL，如果是则马上用exit(1)终止整个程序的运行。例如：<br>void Func(void)<br>{<br>A *a = new A;<br>if(a == NULL)<br><font style="BACKGROUND-COLOR: #ff0000">{<br>&nbsp;&nbsp; cout &lt;&lt; "Memory Exhausted" &lt;&lt; endl;<br>&nbsp;&nbsp; exit(1);<br>}</font><br>...<br>}</p>
<p>（3）为new和malloc设置异常处理函数。</p>
<p>例如Visual C++可以用_set_new_hander函数为new设置用户自己定义的异常处理函数，<br>也可以让malloc享用与new相同的异常处理函数。详细内容请参考C++使用手册。</p>
<p>上述（1）（2）方式使用最普遍。如果一个函数内有多处需要申请动态内存，<br>那么方式（1）就显得力不从心（释放内存很麻烦），应该用方式（2）来处理。</p>
<p>很多人不忍心用exit(1)，问："不编写出错处理程序，让操作系统自己解决行不行？"<br>不行。<font style="BACKGROUND-COLOR: #ff0000">如果发生"内存耗尽"这样的事情，一般说来应用程序已经无药可救。<br>如果不用exit(1) 把坏程序杀死，它可能会害死操作系统。<br></font>道理如同：如果不把歹徒击毙，歹徒在老死之前会犯下更多的罪。</p>
<p>有一个很重要的现象要告诉大家。对于32位以上的应用程序而言<br>，无论怎样使用malloc与new，几乎不可能导致"内存耗尽"。<br>我在Windows 98下用Visual C++编写了测试程序，见示例9。<br>这个程序会无休止地运行下去，根本不会终止。<br>因为32位操作系统支持"虚存"，内存用完了，自动用硬盘空间顶替。<br>我只听到硬盘嘎吱嘎吱地响，Window 98已经累得对键盘、鼠标毫无反应。</p>
<p>我可以得出这么一个结论：对于32位以上的应用程序，"内存耗尽"错误处理程序毫无用处。这下可把Unix和Windows程序员们乐坏了：反正错误处理程序不起作用，我就不写了，省了很多麻烦。</p>
<p>我不想误导读者，必须强调：不加错误处理将导致程序的质量很差，千万不可因小失大。</p>
<p>示例9试图耗尽操作系统的内存<br>void main(void)<br>{<br>&nbsp;&nbsp; float *p = NULL;<br>&nbsp;&nbsp; while(TRUE)<br>&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp; p = new float[1000000]; <br>&nbsp;&nbsp;&nbsp; cout &lt;&lt; "eat memory" &lt;&lt; endl; <br>&nbsp;&nbsp;&nbsp; if(p==NULL) exit(1);<br>&nbsp;&nbsp; }<br>}</p>
<p>&#160;</p>
<p>10 malloc/free 的使用要点<br>------------------------------------------<br>函数malloc的原型如下：<br>void * malloc(size_t size);<br>用malloc申请一块长度为length的整数类型的内存，程序如下：<br>int *p = (int *) malloc(sizeof(int) * length);<br>我们应当把注意力集中在两个要素上："类型转换"和"sizeof"。<br>malloc返回值的类型是void *，所以在调用malloc时要显式地进行类型转换，<br>将void * 转换成所需要的指针类型。<br>malloc函数本身并不识别要申请的内存是什么类型，它只关心内存的总字节数。<br>我们通常记不住int,float等数据类型的变量的确切字节数。例如int变量在16位系统下是2个字节<br>，在32位下是4个字节；而float变量在16位系统下是4个字节，在32位下也是4个字节。</p>
<p>最好用以下程序作一次测试：<br>cout &lt;&lt; sizeof(char) &lt;&lt; endl;<br>cout &lt;&lt; sizeof(int) &lt;&lt; endl;<br>cout &lt;&lt; sizeof(unsigned int) &lt;&lt; endl;<br>cout &lt;&lt; sizeof(long) &lt;&lt; endl;<br>cout &lt;&lt; sizeof(unsigned long) &lt;&lt; endl;<br>cout &lt;&lt; sizeof(float) &lt;&lt; endl;<br>cout &lt;&lt; sizeof(double) &lt;&lt; endl;<br>cout &lt;&lt; sizeof(void *) &lt;&lt; endl;<br><br>在malloc的"()"中使用sizeof运算符是良好的风格，但要当心有时我们会昏了头，写出 p = malloc(sizeof(p))这样的程序来。</p>
<p>函数free的原型如下：</p>
<p>void free( void * memblock );<br><br>为什么free函数不象malloc函数那样复杂呢？这是因为指针p的类型以及它所指的内存的容量事先都是知道的，语句free(p)能正确地释放内存。如果p是NULL指针，那么free对p无论操作多少次都不会出问题。<br>如果p不是NULL指针，那么free对p连续操作两次就会导致程序运行错误。</p>
<p>&#160;</p>
<p>11 new/delete 的使用要点<br>------------------------------------------<br>运算符new使用起来要比函数malloc简单得多，例如：<br>int *p1 = (int *)malloc(sizeof(int) * length);<br>int *p2 = new int[length];<br>这是因为new内置了sizeof、类型转换和类型安全检查功能。对于非内部数据类型的对象而言，<br>new在创建动态对象的同时完成了初始化工作。<br>如果对象有多个构造函数，那么new的语句也可以有多种形式。<br>例如<br>class Obj<br>{<br>public :<br>Obj(void); // 无参数的构造函数<br>Obj(int x); // 带一个参数的构造函数<br>...<br>}<br>void Test(void)<br>{<br>Obj *a = new Obj;<br>Obj *b = new Obj(1); // 初值为1<br>...<br>delete a;<br>delete b;<br>}<br>如果用new创建对象数组，那么只能使用对象的无参数构造函数。例如<br>Obj *objects = new Obj[100]; // 创建100个动态对象<br>不能写成<br>Obj *objects = new Obj[100](1);// 创建100个动态对象的同时赋初值1<br>在用delete释放对象数组时，留意不要丢了符号&#8216;[]'。例如<br>delete []objects; // 正确的用法<br>delete objects; // 错误的用法<br>后者相当于delete objects[0]，漏掉了另外99个对象。</p>
<img src ="http://www.cppblog.com/finehai/aggbug/90453.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/finehai/" target="_blank">Bluesea</a> 2009-07-18 20:08 <a href="http://www.cppblog.com/finehai/archive/2009/07/18/90453.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>进制转换程序</title><link>http://www.cppblog.com/finehai/archive/2009/07/18/90452.html</link><dc:creator>Bluesea</dc:creator><author>Bluesea</author><pubDate>Sat, 18 Jul 2009 12:05:00 GMT</pubDate><guid>http://www.cppblog.com/finehai/archive/2009/07/18/90452.html</guid><wfw:comment>http://www.cppblog.com/finehai/comments/90452.html</wfw:comment><comments>http://www.cppblog.com/finehai/archive/2009/07/18/90452.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/finehai/comments/commentRss/90452.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/finehai/services/trackbacks/90452.html</trackback:ping><description><![CDATA[<p>#include&lt;iostream&gt;<br>#include &lt;algorithm&gt;<br>using namespace std;</p>
<p>char * change(int n, int base)<br>{<br>&nbsp;&nbsp;char *p, *val;<br>&nbsp;&nbsp;if(base&lt;2||base&gt;36)<br>&nbsp;&nbsp;&nbsp;return NULL;<br>&nbsp;&nbsp;val = (char *) malloc(40);<br>&nbsp;&nbsp;if(!val)<br>&nbsp;&nbsp;&nbsp;return NULL;<br><span style="COLOR: #000000">&nbsp;&nbsp;p=val;<br>&nbsp;&nbsp;while( n)</span><br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;*p= (n%base)&gt;9? n%base-10+'a':n%base+'0';<br>&nbsp;&nbsp;&nbsp;n/=base;<br>&nbsp;&nbsp;&nbsp;++p;<br>&nbsp;&nbsp;}</p>
<p><span>&nbsp;&nbsp;reverse(val,p);<br>&nbsp;&nbsp;*p='\0';<br>&nbsp;&nbsp;++p;<br>&nbsp;&nbsp;return val;<br></span>}</p>
<p>&nbsp;int main(int argc, char* argv[])<br>&nbsp;{<br>&nbsp;&nbsp;char * test;<br>&nbsp;&nbsp;int n,base;<br>&nbsp;&nbsp;while(cin&gt;&gt;n&gt;&gt;base)<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;test=change(n,base);<br>&nbsp;&nbsp;&nbsp;if(test){<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;"Change "&lt;&lt;n&lt;&lt;" to base "&lt;&lt;base&lt;&lt;" = "&lt;&lt;test&lt;&lt;endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;free(test);<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;else<br>&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;"Wrong input."&lt;&lt;endl;<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;return 0;<br>&nbsp;}</p>
<img src ="http://www.cppblog.com/finehai/aggbug/90452.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/finehai/" target="_blank">Bluesea</a> 2009-07-18 20:05 <a href="http://www.cppblog.com/finehai/archive/2009/07/18/90452.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>windows下多线程问题</title><link>http://www.cppblog.com/finehai/archive/2009/07/18/90449.html</link><dc:creator>Bluesea</dc:creator><author>Bluesea</author><pubDate>Sat, 18 Jul 2009 11:37:00 GMT</pubDate><guid>http://www.cppblog.com/finehai/archive/2009/07/18/90449.html</guid><wfw:comment>http://www.cppblog.com/finehai/comments/90449.html</wfw:comment><comments>http://www.cppblog.com/finehai/archive/2009/07/18/90449.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/finehai/comments/commentRss/90449.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/finehai/services/trackbacks/90449.html</trackback:ping><description><![CDATA[<p style="FONT-SIZE: 14pt">锁的概念 原子操作 信号量&nbsp; 临界区 线程同步</p>
<p style="FONT-SIZE: 14pt">死锁：</p>
<p style="FONT-SIZE: 14pt">构成死锁的条件四个，缺一不可</p>
<p style="FONT-SIZE: 14pt">1一个线程只能单独用一个资源</p>
<p style="FONT-SIZE: 14pt">2正在使用的资源可以申请其他资源，同时自己的不会放开</p>
<p style="FONT-SIZE: 14pt">3只有申请到其他资源，这个线程才会放开</p>
<p style="FONT-SIZE: 14pt">4各个线程是循环状态，就是每个线程要按照一定的顺序申请，然后最后成为一个环。</p>
<p style="FONT-SIZE: 14pt">原子操作：就是不可以有中断的操作</p>
<p style="FONT-SIZE: 14pt">信号量:与pv有关，表示资源的分配和释放的情况。信号S，p则s－1，v则s＋1。s表示可以使用的进程的数目。如果s&gt;0表示还有进程可以使用，调用p则分配了资源，那么s－1，s&lt;0表示没有了资源可以使用，或者需要释放的资源。 调用v操作，表示释放的资源，因此s＋1。调用P操作测试消息是否到达，调用V操作发送消息。</p>
<p style="FONT-SIZE: 14pt">都是设计到同步和互斥概念的东西。</p>
<p style="FONT-SIZE: 14pt">临界区：就是在p（s）和v（s）之间的一种状态。</p>
<p style="FONT-SIZE: 14pt">线程同步：</p>
<p style="FONT-SIZE: 14pt">　使隶属于同一进程的各线程协调一致地工作称为线程的同步</p>
<li>临界区（CCriticalSection）
<li>事件（CEvent）
<li>互斥量（CMutex）
<li>信号量（CSemaphore）
<p style="FONT-SIZE: 14pt">A、使用 CCriticalSection 类
<p style="FONT-SIZE: 14pt">　　当多个线程访问一个独占性共享资源时,可以使用&#8220;临界区&#8221;对象。任一时刻只有一个线程可以拥有临界区对象，拥有临界区的线程可以访问被保护起来的资源或代码段，其他希望进入临界区的线程将被挂起等待，直到拥有临界区的线程放弃临界区时为止，这样就保证了不会在同一时刻出现多个线程访问共享资源。<br><br>CCriticalSection类的用法非常简单，步骤如下：<br>　
<ol>
    <li>定义CCriticalSection类的一个全局对象（以使各个线程均能访问），如CCriticalSection critical_section；
    <li>在访问需要保护的资源或代码之前，调用CCriticalSection类的成员Lock（）获得临界区对象：
    <pre>critical_section.Lock();</pre>
    在线程中调用该函数来使线程获得它所请求的临界区。如果此时没有其它线程占有临界区对象，则调用Lock()的线程获得临界区；否则，线程将被挂起，并放入到一个系统队列中等待，直到当前拥有临界区的线程释放了临界区时为止。
    <li>访问临界区完毕后，使用CCriticalSection的成员函数Unlock()来释放临界区：
    <pre>critical_section.Unlock();</pre>
    再通俗一点讲，就是线程A执行到critical_section.Lock();语句时，如果其它线程(B)正在执行critical_section.Lock();语句后且critical_section. Unlock();语句前的语句时，线程A就会等待，直到线程B执行完critical_section. Unlock();语句，线程A才会继续执行。 </li>
</ol>
<p style="FONT-SIZE: 14pt">下面再通过一个实例进行演示说明。</p>
<p style="FONT-SIZE: 14pt"><br>例程8 MultiThread8</p>
<ol>
    <li>建立一个基于对话框的工程MultiThread8，在对话框IDD_MULTITHREAD8_DIALOG中加入两个按钮和两个编辑框控件，两个按钮的ID分别为IDC_WRITEW和IDC_WRITED，标题分别为&#8220;写&#8216;W&#8217;&#8221;和&#8220;写&#8216;D&#8217;&#8221;；两个编辑框的ID分别为IDC_W和IDC_D，属性都选中Read-only；
    <li>在MultiThread8Dlg.h文件中声明两个线程函数：
    <pre>UINT WriteW(LPVOID pParam);
    UINT WriteD(LPVOID pParam);</pre>
    <li>使用ClassWizard分别给IDC_W和IDC_D添加CEdit类变量m_ctrlW和m_ctrlD；
    <li>在MultiThread8Dlg.cpp文件中添加如下内容：<br><br>为了<a onclick="javascript:tagshow(event, '%CE%C4%BC%FE');" href="javascript:;" target=_self>文件</a>中能够正确使用同步类，在文件开头添加：
    <pre>#include "afxmt.h"</pre>
    定义临界区和一个字符数组，为了能够在不同线程间使用，定义为全局变量：
    <pre>CCriticalSection critical_section;
    char g_Array[10];</pre>
    添加线程函数：
    <pre>UINT WriteW(LPVOID pParam)
    {
    CEdit *pEdit=(CEdit*)pParam;
    pEdit-&gt;SetWindowText("");
    critical_section.Lock();
    //锁定临界区，其它线程遇到critical_section.Lock();语句时要等待
    //直至执行critical_section.Unlock();语句
    for(int i=0;i&lt;10;i++)
    {
    g_Array[i]=''W'';
    pEdit-&gt;SetWindowText(g_Array);
    Sleep(1000);
    }
    critical_section.Unlock();
    return 0;
    }
    UINT WriteD(LPVOID pParam)
    {
    CEdit *pEdit=(CEdit*)pParam;
    pEdit-&gt;SetWindowText("");
    critical_section.Lock();
    //锁定临界区，其它线程遇到critical_section.Lock();语句时要等待
    //直至执行critical_section.Unlock();语句
    for(int i=0;i&lt;10;i++)
    {
    g_Array[i]=''D'';
    pEdit-&gt;SetWindowText(g_Array);
    Sleep(1000);
    }
    critical_section.Unlock();
    return 0;
    }</pre>
    <li>分别双击按钮IDC_WRITEW和IDC_WRITED，添加其响应函数：
    <pre>void CMultiThread8Dlg::OnWritew()
    {
    CWinThread *pWriteW=AfxBeginThread(WriteW,
    &amp;m_ctrlW,
    THREAD_PRIORITY_NORMAL,
    0,
    CREATE_SUSPENDED);
    pWriteW-&gt;ResumeThread();
    }
    void CMultiThread8Dlg::OnWrited()
    {
    CWinThread *pWriteD=AfxBeginThread(WriteD,
    &amp;m_ctrlD,
    THREAD_PRIORITY_NORMAL,
    0,
    CREATE_SUSPENDED);
    pWriteD-&gt;ResumeThread();
    }</pre>
    由于代码较简单，不再详述。编译、运行该例程，您可以连续点击两个按钮，观察体会临界类的作用。 </li>
</ol>
<p style="FONT-SIZE: 14pt">B、使用 CEvent 类
<p style="FONT-SIZE: 14pt">　　CEvent 类提供了对事件的支持。事件是一个允许一个线程在某种情况发生时，唤醒另外一个线程的同步对象。例如在某些网络应用程序中，一个线程（记为A）负责监听通讯端口，另外一个线程（记为B）负责更新用户数据。通过使用CEvent 类，线程A可以通知线程B何时更新用户数据。每一个CEvent 对象可以有两种状态：有信号状态和无信号状态。线程监视位于其中的CEvent 类对象的状态，并在相应的时候采取相应的操作。<br>　　在MFC中，CEvent 类对象有两种类型：人工事件和自动事件。一个自动CEvent 对象在被至少一个线程释放后会自动返回到无信号状态；而人工事件对象获得信号后，释放可利用线程，但直到调用成员函数ReSetEvent()才将其设置为无信号状态。在创建CEvent 类的对象时，默认创建的是自动事件。 CEvent 类的各成员函数的原型和参数说明如下：</p>
<pre>1、CEvent(BOOL bInitiallyOwn=FALSE,
BOOL bManualReset=FALSE,
LPCTSTR lpszName=NULL,
LPSECURITY_ATTRIBUTES lpsaAttribute=NULL);</pre>
<p style="FONT-SIZE: 14pt"></p>
<ul>
    <li>bInitiallyOwn:指定事件对象初始化状态，TRUE为有信号，FALSE为无信号；
    <li>bManualReset：指定要创建的事件是属于人工事件还是自动事件。TRUE为人工事件，FALSE为自动事件；
    <li>后两个参数一般设为NULL，在此不作过多说明。 </li>
</ul>
<pre>2、BOOL CEvent：：SetEvent();</pre>
<p style="FONT-SIZE: 14pt">　　将 CEvent 类对象的状态设置为有信号状态。如果事件是人工事件，则 CEvent 类对象保持为有信号状态，直到调用成员函数ResetEvent()将 其重新设为无信号状态时为止。如果CEvent 类对象为自动事件，则在SetEvent()将事件设置为有信号状态后，CEvent 类对象由系统自动重置为无信号状态。<br><br>如果该函数执行成功，则返回非零值，否则返回零。</p>
<pre>3、BOOL CEvent：：ResetEvent();</pre>
<p style="FONT-SIZE: 14pt">　　该函数将事件的状态设置为无信号状态，并保持该状态直至SetEvent()被调用时为止。由于自动事件是由系统自动重置，故自动事件不需要调用该函数。如果该函数执行成功，返回非零值，否则返回零。我们一般通过调用WaitForSingleObject函数来监视事件状态。前面我们已经介绍了该函数。由于语言描述的原因，CEvent 类的理解确实有些难度，但您只要通过仔细玩味下面例程，多看几遍就可理解。</p>
<p style="FONT-SIZE: 14pt">例程9 MultiThread9</p>
<ol>
    <li>建立一个基于对话框的工程MultiThread9，在对话框IDD_MULTITHREAD9_DIALOG中加入一个按钮和两个编辑框控件，按钮的ID为IDC_WRITEW，标题为&#8220;写&#8216;W&#8217;&#8221;；两个编辑框的ID分别为IDC_W和IDC_D，属性都选中Read-only;
    <li>在MultiThread9Dlg.h文件中声明两个线程函数：
    <pre>UINT WriteW(LPVOID pParam);
    UINT WriteD(LPVOID pParam);</pre>
    <li>使用ClassWizard分别给IDC_W和IDC_D添加CEdit类变量m_ctrlW和m_ctrlD；
    <li>在MultiThread9Dlg.cpp文件中添加如下内容：
    <p style="FONT-SIZE: 14pt">为了文件中能够正确使用同步类，在文件开头添加</p>
    <pre>#include "afxmt.h"</pre>
    定义事件对象和一个字符数组，为了能够在不同线程间使用，定义为全局变量。
    <pre>CEvent eventWriteD;
    char g_Array[10];</pre>
    添加线程函数：
    <pre>UINT WriteW(LPVOID pParam)
    {
    CEdit *pEdit=(CEdit*)pParam;
    pEdit-&gt;SetWindowText("");
    for(int i=0;i&lt;10;i++)
    {
    g_Array[i]=''W'';
    pEdit-&gt;SetWindowText(g_Array);
    Sleep(1000);
    }
    eventWriteD.SetEvent();
    return 0;
    }
    UINT WriteD(LPVOID pParam)
    {
    CEdit *pEdit=(CEdit*)pParam;
    pEdit-&gt;SetWindowText("");
    WaitForSingleObject(eventWriteD.m_hObject,INFINITE);
    for(int i=0;i&lt;10;i++)
    {
    g_Array[i]=''D'';
    pEdit-&gt;SetWindowText(g_Array);
    Sleep(1000);
    }
    return 0;
    }</pre>
    　　仔细分析这两个线程函数, 您就会正确理解CEvent 类。线程WriteD执行到 WaitForSingleObject(eventWriteD.m_hObject,INFINITE);处等待，直到事件eventWriteD为有信号该线程才往下执行，因为eventWriteD对象是自动事件，则当WaitForSingleObject()返回时，系统自动把eventWriteD对象重置为无信号状态。
    <li>双击按钮IDC_WRITEW，添加其响应函数：
    <pre>void CMultiThread9Dlg::OnWritew()
    {
    CWinThread *pWriteW=AfxBeginThread(WriteW,
    &amp;m_ctrlW,
    THREAD_PRIORITY_NORMAL,
    0,
    CREATE_SUSPENDED);
    pWriteW-&gt;ResumeThread();
    CWinThread *pWriteD=AfxBeginThread(WriteD,
    &amp;m_ctrlD,
    THREAD_PRIORITY_NORMAL,
    0,
    CREATE_SUSPENDED);
    pWriteD-&gt;ResumeThread();
    }</pre>
    编译并运行程序，单击&#8220;写&#8216;W&#8217;&#8221;按钮，体会事件对象的作用。 </li>
</ol>
<p style="FONT-SIZE: 14pt">C、使用CMutex 类</p>
<p style="FONT-SIZE: 14pt">　　互斥对象与临界区对象很像.互斥对象与临界区对象的不同在于:互斥对象可以在进程间使用,而临界区对象只能在同一进程的各线程间使用。当然，互斥对象也可以用于同一进程的各个线程间，但是在这种情况下，使用临界区会更节省系统资源，更有效率。</p>
<p style="FONT-SIZE: 14pt">D、使用CSemaphore 类</p>
<p style="FONT-SIZE: 14pt">　　当需要一个计数器来限制可以使用某个线程的数目时，可以使用&#8220;信号量&#8221;对象。CSemaphore 类的对象保存了对当前访问某一指定资源的线程的计数值，该计数值是当前还可以使用该资源的线程的数目。如果这个计数达到了零，则所有对这个CSemaphore 类对象所控制的资源的访问尝试都被放入到一个队列中等待，直到超时或计数值不为零时为止。一个线程被释放已访问了被保护的资源时，计数值减1；一个线程完成了对被控共享资源的访问时，计数值增1。这个被CSemaphore 类对象所控制的资源可以同时接受访问的最大线程数在该对象的构建函数中指定。<br><br>CSemaphore 类的构造函数原型及参数说明如下：</p>
<pre>CSemaphore (LONG lInitialCount=1,
LONG lMaxCount=1,
LPCTSTR pstrName=NULL,
LPSECURITY_ATTRIBUTES lpsaAttributes=NULL);</pre>
<ul>
    <li>lInitialCount:信号量对象的初始计数值，即可访问线程数目的初始值；
    <li>lMaxCount：信号量对象计数值的最大值，该参数决定了同一时刻可访问由信号量保护的资源的线程最大数目；
    <li>后两个参数在同一进程中使用一般为NULL，不作过多讨论； </li>
</ul>
<p style="FONT-SIZE: 14pt">　　在用CSemaphore 类的构造函数创建信号量对象时要同时指出允许的最大资源计数和当前可用资源计数。一般是将当前可用资源计数设置为最大资源计数，每增加一个线程对共享资源的访问，当前可用资源计数就会减1，只要当前可用资源计数是大于0的，就可以发出信号量信号。但是当前可用计数减小到0时，则说明当前占用资源的线程数已经达到了所允许的最大数目，不能再允许其它线程的进入，此时的信号量信号将无法发出。线程在处理完共享资源后，应在离开的同时通过ReleaseSemaphore()函数将当前可用资源数加1。</p>
<p style="FONT-SIZE: 14pt">下面给出一个简单实例来说明 CSemaphore 类的用法。</p>
<p style="FONT-SIZE: 14pt">例程10 MultiThread10</p>
<ol>
    <li>建立一个基于对话框的工程MultiThread10，在对话框IDD_MULTITHREAD10_DIALOG中加入一个按钮和三个编辑框控件，按钮的ID为IDC_START，标题为&#8220;同时写&#8216;A&#8217;、&#8216;B&#8217;、&#8216;C&#8217;&#8221;；三个编辑框的ID分别为IDC_A、IDC_B和IDC_C，属性都选中Read-only；
    <li>在MultiThread10Dlg.h文件中声明两个线程函数：
    <pre>UINT WriteA(LPVOID pParam);
    UINT WriteB(LPVOID pParam);
    UINT WriteC(LPVOID pParam);</pre>
    <li>使用ClassWizard分别给IDC_A、IDC_B和IDC_C添加CEdit类变量m_ctrlA、m_ctrlB和m_ctrlC；
    <li>在MultiThread10Dlg.cpp文件中添加如下内容：
    <p style="FONT-SIZE: 14pt">为了文件中能够正确使用同步类，在文件开头添加：</p>
    <pre>#include "afxmt.h"</pre>
    定义信号量对象和一个字符数组，为了能够在不同线程间使用，定义为全局变量：
    <pre>CSemaphore semaphoreWrite(2,2); //资源最多访问线程2个，当前可访问线程数2个
    char g_Array[10];</pre>
    <p style="FONT-SIZE: 14pt">添加三个线程函数：</p>
    <pre>UINT WriteA(LPVOID pParam)
    {
    CEdit *pEdit=(CEdit*)pParam;
    pEdit-&gt;SetWindowText("");
    WaitForSingleObject(semaphoreWrite.m_hObject,INFINITE);
    CString str;
    for(int i=0;i&lt;10;i++)
    {
    pEdit-&gt;GetWindowText(str);
    g_Array[i]=''A'';
    str=str+g_Array[i];
    pEdit-&gt;SetWindowText(str);
    Sleep(1000);
    }
    ReleaseSemaphore(semaphoreWrite.m_hObject,1,NULL);
    return 0;
    }
    UINT WriteB(LPVOID pParam)
    {
    CEdit *pEdit=(CEdit*)pParam;
    pEdit-&gt;SetWindowText("");
    WaitForSingleObject(semaphoreWrite.m_hObject,INFINITE);
    CString str;
    for(int i=0;i&lt;10;i++)
    {
    pEdit-&gt;GetWindowText(str);
    g_Array[i]=''B'';
    str=str+g_Array[i];
    pEdit-&gt;SetWindowText(str);
    Sleep(1000);
    }
    ReleaseSemaphore(semaphoreWrite.m_hObject,1,NULL);
    return 0;
    }
    UINT WriteC(LPVOID pParam)
    {
    CEdit *pEdit=(CEdit*)pParam;
    pEdit-&gt;SetWindowText("");
    WaitForSingleObject(semaphoreWrite.m_hObject,INFINITE);
    for(int i=0;i&lt;10;i++)
    {
    g_Array[i]=''C'';
    pEdit-&gt;SetWindowText(g_Array);
    Sleep(1000);
    }
    ReleaseSemaphore(semaphoreWrite.m_hObject,1,NULL);
    return 0;
    }</pre>
    这三个线程函数不再多说。在信号量对象有信号的状态下，线程执行到WaitForSingleObject语句处继续执行，同时可用线程数减1；若线程执行到WaitForSingleObject语句时信号量对象无信号，线程就在这里等待，直到信号量对象有信号线程才往下执行。
    <li>双击按钮IDC_START，添加其响应函数：
    <pre>void CMultiThread10Dlg::OnStart()
    {
    CWinThread *pWriteA=AfxBeginThread(WriteA,
    &amp;m_ctrlA,
    THREAD_PRIORITY_NORMAL,
    0,
    CREATE_SUSPENDED);
    pWriteA-&gt;ResumeThread();
    CWinThread *pWriteB=AfxBeginThread(WriteB,
    &amp;m_ctrlB,
    THREAD_PRIORITY_NORMAL,
    0,
    CREATE_SUSPENDED);
    pWriteB-&gt;ResumeThread();
    CWinThread *pWriteC=AfxBeginThread(WriteC,
    &amp;m_ctrlC,
    THREAD_PRIORITY_NORMAL,
    0,
    CREATE_SUSPENDED);
    pWriteC-&gt;ResumeThread();
    }</pre>
    </li>
</ol>
</li>
<img src ="http://www.cppblog.com/finehai/aggbug/90449.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/finehai/" target="_blank">Bluesea</a> 2009-07-18 19:37 <a href="http://www.cppblog.com/finehai/archive/2009/07/18/90449.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++的重要性质</title><link>http://www.cppblog.com/finehai/archive/2009/07/18/90446.html</link><dc:creator>Bluesea</dc:creator><author>Bluesea</author><pubDate>Sat, 18 Jul 2009 11:25:00 GMT</pubDate><guid>http://www.cppblog.com/finehai/archive/2009/07/18/90446.html</guid><wfw:comment>http://www.cppblog.com/finehai/comments/90446.html</wfw:comment><comments>http://www.cppblog.com/finehai/archive/2009/07/18/90446.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/finehai/comments/commentRss/90446.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/finehai/services/trackbacks/90446.html</trackback:ping><description><![CDATA[<p style="FONT-SIZE: 14pt">c＋＋的重要性质:</p>
<p style="FONT-SIZE: 14pt">OOP object oriented programming<br>property&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; method<br>member variable,member function</p>
<p style="FONT-SIZE: 14pt">encapsulation<br>enheritance<br>polymorphism<br>overloading</p>
<p style="FONT-SIZE: 14pt">ellipse circle triangle rectangle square</p>
<p style="FONT-SIZE: 14pt">virtual作用？<br>如果没有virtual，那么就继承了基类指针的性质，如果有virtual，那么就指向对</p>
<p style="FONT-SIZE: 14pt">象的类型。虚函数正式为了对&#8220;如果以一个基类的指针指向一个派生类的对象，那么</p>
<p style="FONT-SIZE: 14pt">通过该指针只能够调用基类所定义的成员函数&#8221;这条规则反其道而行的设计。</p>
<p style="FONT-SIZE: 14pt">纯虚函数作用？<br>就是在基类中并不实现，但是为了在派生类中使用，就需要分配一个并不执行，但</p>
<p style="FONT-SIZE: 14pt">是还需要继承的函数。就是纯虚函数 virtual function（）＝0；纯虚函数不需要</p>
<p style="FONT-SIZE: 14pt">定义，在派生类中被重新定义。</p>
<p style="FONT-SIZE: 14pt">什么是抽象类？<br>拥有虚函数的类。抽象类不能产生出对象实体，但是可以拥有指向抽象类的指针，</p>
<p style="FONT-SIZE: 14pt">便于操作抽象类的各个派生类。<br>虚函数派生下去仍是虚函数，而且可以省略virtual。</p>
<p style="FONT-SIZE: 14pt">虚函数到底有什么作用？<br>1如果你估计派生类会重新定义一个成员函数，那么你就把基类中的这个函数写成</p>
<p style="FONT-SIZE: 14pt">virtual<br>2通过单一指令调用不同函数，就是多态Polymorphism,"ability to asume many</p>
<p style="FONT-SIZE: 14pt">forms"<br>3虚函数是c＋＋语言polymorphism性质以及动态联编的关键<br>4既然抽象类中的虚函数不打算被调用，那么就把它设置成纯虚函数。<br>5拥有纯虚函数者为抽象类。<br>6抽象类不能产生出对象实体，但是我们可以拥有指向抽象类的指针，以便于操作抽</p>
<p style="FONT-SIZE: 14pt">象类的各个派生类。<br>7虚函数派生下去仍是虚函数，可以不写virtual。</p>
<p style="FONT-SIZE: 14pt">虚函数怎样工作？<br>在含有虚函数的类中，编译器会为它做出一个虚函数表，表中的每一个元素都指向</p>
<p style="FONT-SIZE: 14pt">一个虚函数的地址。</p>
<p style="FONT-SIZE: 14pt">什么是upcasting？<br>它是向上强制性类型转换。<br>class CMyDoc:public CDocument;<br>CMyDoc mydoc;</p>
<p style="FONT-SIZE: 14pt">(CDocument)mydodc.func();(upcasting)<br>注意一般不用upcasting。</p>
<p style="FONT-SIZE: 14pt">静态变量到底是什么？<br>static double m_rate;<br>static成员变量不属于对象的一部分，而是类的一部分，程序可以在没有诞生任何</p>
<p style="FONT-SIZE: 14pt">对象的时候就处理此种成员变量，但首相你必须初始化它。<br>static成员变量的初始化不要安排到构造函数中，因为构造函数可以一再被调用；</p>
<p style="FONT-SIZE: 14pt">也不要把初始化安排在头<a onclick="javascript:tagshow(event, '%CE%C4%BC%FE');" href="javascript:;" target=_self>文件</a>中，因为可能会被嵌入到许多地方。应该在类以外的</p>
<p style="FONT-SIZE: 14pt">任何位置设定其初值。<br>static变量可以想象成一个全程变量。<br>static成员函数不需要借助任何对象，可以被调用执行，所以编译器不会为它暗加</p>
<p style="FONT-SIZE: 14pt">一个this指针。因此static成员函数无法处理类中的non－static成员变量。<br>static的构造很析够就相当于全局变量，只是它会在全局函数之前析够。构造函数</p>
<p style="FONT-SIZE: 14pt">和析够函数都是以函数为标志的。</p>
<p style="FONT-SIZE: 14pt">error LINK2001：unresolved external symbol""();一般是因为没有初始化static</p>
<p style="FONT-SIZE: 14pt">的值。</p>
<p style="FONT-SIZE: 14pt"><br>new的好处？<br>分配对象所需内存空间，并且引发构造函数的执行。</p>
<p style="FONT-SIZE: 14pt">什么是RTTI?<br>RTTI Runtime Type Information 动态类型识别<br>就是知道程序执行过程中某个对象是属于那个类的。</p>
<p style="FONT-SIZE: 14pt"><br>什么是动态生成（Dynamic Creation）?</p>
<p style="FONT-SIZE: 14pt">什么是异样处理(Exception Handling)?<br>使用三个expection保留字:<br>try:其后跟随一段以{}圈出的程序代码，exception将在那里被处理。（就是将要处</p>
<p style="FONT-SIZE: 14pt">理的代码）<br>catch：其后{},里边是处理程序。（就是怎样处理了）<br>throw：用来产生一个exception。</p>
<p style="FONT-SIZE: 14pt"><br>什么是模板？<br>template，就是可以重复利用的架构。<br>template &lt;class T&gt;<br>T power(T base,int exponent);</p>
<p style="FONT-SIZE: 14pt">这里的T就是可以随时改变的量。当然这里的T是类的意思，可以是系统定义的类，</p>
<p style="FONT-SIZE: 14pt">也可以是自己定义的类。<br>这里注意对于，模板，两个对象如果都使用了同一个模板，在编译的时候是不知道</p>
<p style="FONT-SIZE: 14pt">的，但是<a onclick="javascript:tagshow(event, '%C1%B4%BD%D3');" href="javascript:;" target=_self>链接</a>的时候，连接器就会将他们重复的部分去掉。标准的说就是 链接器会</p>
<p style="FONT-SIZE: 14pt">把所有冗余的template码剔除。在Borland链接器里头称为smart技术。</p>
<img src ="http://www.cppblog.com/finehai/aggbug/90446.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/finehai/" target="_blank">Bluesea</a> 2009-07-18 19:25 <a href="http://www.cppblog.com/finehai/archive/2009/07/18/90446.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>