﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-哇哇小白-文章分类-C++ 技术</title><link>http://www.cppblog.com/smartwhite/category/2322.html</link><description>哇哇小白 个人领域</description><language>zh-cn</language><lastBuildDate>Sat, 14 Jun 2008 18:54:46 GMT</lastBuildDate><pubDate>Sat, 14 Jun 2008 18:54:46 GMT</pubDate><ttl>60</ttl><item><title>C++ 异常处理</title><link>http://www.cppblog.com/smartwhite/articles/10686.html</link><dc:creator>哇哇小白</dc:creator><author>哇哇小白</author><pubDate>Sat, 29 Jul 2006 14:49:00 GMT</pubDate><guid>http://www.cppblog.com/smartwhite/articles/10686.html</guid><wfw:comment>http://www.cppblog.com/smartwhite/comments/10686.html</wfw:comment><comments>http://www.cppblog.com/smartwhite/articles/10686.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/smartwhite/comments/commentRss/10686.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/smartwhite/services/trackbacks/10686.html</trackback:ping><description><![CDATA[		<font face="Courier New" size="2">C++ 的异常处理<br /><br />    <font color="#a9a9a9"><i>头一次发文章,也不知道是不是放在这里...</i></font><br /><br />    我们的程序总是会碰到一些不可预料的情况：当读取一个文件失败、当初始化驱动出错、当内存不足…。这些都给我们的程序的正常运行带来了麻烦。在 C 中，大家习惯于用函数的返回值来标志这些错误当然你在 C++ 中仍然可以也这么干；在 C++ 中，引入了一种错误处理机制 异常处理 Exception Handling。<br /><br /></font>
		<font face="Courier New" size="2">    一般的异常处理的代码写法是这样的：</font>
		<br />
		<font face="Courier New" size="2">
				<blockquote>
						<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 88%;">
								<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->
								<span style="color: rgb(0, 0, 255);">int</span>
								<span style="color: rgb(0, 0, 0);"> main( )<br />    {<br />        </span>
								<span style="color: rgb(0, 0, 255);">try</span>
								<span style="color: rgb(0, 0, 0);">
										<br />        {<br />             </span>
								<span style="color: rgb(0, 128, 0);">//</span>
								<span style="color: rgb(0, 128, 0);"> 你的程序代码   </span>
								<span style="color: rgb(0, 128, 0);">
										<br />
								</span>
								<span style="color: rgb(0, 0, 0);">        }<br />        </span>
								<span style="color: rgb(0, 0, 255);">catch</span>
								<span style="color: rgb(0, 0, 0);">( type1 </span>
								<span style="color: rgb(0, 0, 0);">&amp;</span>
								<span style="color: rgb(0, 0, 0);"> ref1 )<br />        {<br />            </span>
								<span style="color: rgb(0, 128, 0);">//</span>
								<span style="color: rgb(0, 128, 0);"> 针对 throw type1 对象的处理代码</span>
								<span style="color: rgb(0, 128, 0);">
										<br />
								</span>
								<span style="color: rgb(0, 0, 0);">        }<br />        </span>
								<span style="color: rgb(0, 0, 255);">catch</span>
								<span style="color: rgb(0, 0, 0);">( type2 </span>
								<span style="color: rgb(0, 0, 0);">&amp;</span>
								<span style="color: rgb(0, 0, 0);"> ref2 )<br />        {<br />            </span>
								<span style="color: rgb(0, 128, 0);">//</span>
								<span style="color: rgb(0, 128, 0);"> 针对 throw type2 对象的处理代码   </span>
								<span style="color: rgb(0, 128, 0);">
										<br />
								</span>
								<span style="color: rgb(0, 0, 0);">        }<br />        </span>
								<span style="color: rgb(0, 0, 255);">catch</span>
								<span style="color: rgb(0, 0, 0);">( <img src="http://www.cppblog.com/images/dot.gif" /> )<br />        {<br />            </span>
								<span style="color: rgb(0, 128, 0);">//</span>
								<span style="color: rgb(0, 128, 0);"> 剩下的所有错误</span>
								<span style="color: rgb(0, 128, 0);">
										<br />
								</span>
								<span style="color: rgb(0, 0, 0);">        }<br />    }</span>
						</div>
				</blockquote>    可以看到程序被 try ， catch关键字分成了几个部分。try 块中放的是程序正常运行的代码；catch块里则是相应的错误处理代码。对应一个 try 可以有几个 catch ， 不同的 catch 通过它们的参数来捕获不同的异常。<br /><br />    当在try中的代码运行中出错，我们可以通过 throw 关键字来抛出异常：<br /><blockquote><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 88%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">( size </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);"> )</span><span style="color: rgb(0, 0, 255);">throw</span><span style="color: rgb(0, 0, 0);"> MyException(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> logic error </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);</span></div></blockquote>    <br />    这里抛出了一个自定义的异常类型，你可以抛出任何你想要的异常类型，然后用对应的 catch 将其捕获（ 实际上 C++ 已经中内建了一些异常类型，感兴趣的话可以去查阅《Thinking in C++ VOL 2》等书籍 ）。对应上面的 throw 我们的 catch 需要这样写：<br /><blockquote><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 88%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);">( MyException </span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);"> my_exception )<br /> {<br />      </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> 处理错误</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"> }</span></div></blockquote>    <br />    如果这里的 catch 捕获了这个异常后发现搞不定它，那么它得负责任得将异常向上递交：<br /></font>
		<blockquote>
				<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 88%;">
						<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->
						<span style="color: rgb(0, 0, 255);">catch</span>
						<span style="color: rgb(0, 0, 0);">( MyException </span>
						<span style="color: rgb(0, 0, 0);">&amp;</span>
						<span style="color: rgb(0, 0, 0);"> my_exception )<br />{<br />    </span>
						<span style="color: rgb(0, 128, 0);">//</span>
						<span style="color: rgb(0, 128, 0);"> 我搞不定</span>
						<span style="color: rgb(0, 128, 0);">
								<br />
						</span>
						<span style="color: rgb(0, 0, 0);">    </span>
						<span style="color: rgb(0, 0, 255);">throw</span>
						<span style="color: rgb(0, 0, 0);">；<br />}</span>
				</div>
				<font face="Courier New" size="2">
						<br />
				</font>
		</blockquote>
		<font face="Courier New" size="2">    这样程序会找更外面的 try 对应的 catch 来处理这个异常。</font>
		<br />
		<font face="Courier New" size="2">
		</font>
		<br />
		<font face="Courier New" size="2">
    如前面所说，当我们的程序执行到 throw 的时候，它会寻找对应的 catch 转而执行 catch
中的异常处理代码，等等～在跳转之前，程序会自动析构所有栈上的对象，就是也就是静态构造的对象，但是对于动态创建的对象会有些麻烦，即使你在某处
delete 掉了它，如果在此之前有异常抛出，很有可能这个 delete 根本不会被执行…<br /></font>
		<blockquote>
				<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;">
						<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->
						<span style="color: rgb(0, 0, 255);">void</span>
						<span style="color: rgb(0, 0, 0);"> RunComputer( )<br />{<br />    Computer </span>
						<span style="color: rgb(0, 0, 0);">*</span>
						<span style="color: rgb(0, 0, 0);"> p_pc </span>
						<span style="color: rgb(0, 0, 0);">=</span>
						<span style="color: rgb(0, 0, 0);"> </span>
						<span style="color: rgb(0, 0, 255);">new</span>
						<span style="color: rgb(0, 0, 0);"> Computer( );<br />            <br />    p_pc.Run( );    </span>
						<span style="color: rgb(0, 128, 0);">//</span>
						<span style="color: rgb(0, 128, 0);"> 如果这里抛出异常？</span>
						<span style="color: rgb(0, 128, 0);">
								<br />
						</span>
						<span style="color: rgb(0, 0, 0);">
								<br />    delete p_pc;<br />}</span>
				</div>
				<br />
		</blockquote>    <font face="Courier New" size="2">这种情况将导致内存泄漏，delete p_pc 有可能被跳过。为了避免这种情况我们可以在异常抛出的地方将对应的资源先释放一次：<br /></font><blockquote><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> RunComputer( )<br />{<br />    Computer </span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);"> p_pc </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Computer( );<br />            <br />    </span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);"><br />    {<br />        p_pc.Run( );    </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> 抛出异常</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">    }<br />    </span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);">( <img src="http://www.cppblog.com/images/dot.gif" /> )<br />    {<br />        delete p_pc;    </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> delete 了以后向上递交</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">        </span><span style="color: rgb(0, 0, 255);">throw</span><span style="color: rgb(0, 0, 0);">;<br />    }<br /><br />    delete p_pc;<br />}</span></div><br /></blockquote>   <font face="Courier New" size="2"> 这样看上去是不是很不爽？为一个 new 要写两个 delete 。<br />    还有个更好的方法来解决这种问题，那就是使用 std::auto_ptr ，它的原理是将你的指针存放在一个静态对象中，当 throw 发生时，auto_ptr 会被析构，你的指针也会自动的被 delete。<br /><br /></font><blockquote><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> RunComputer( )<br />{<br />    std::auto_ptr</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">Computer</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"> p_pc( </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Computer( ) );<br />            <br />    p_pc.Run( );    </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> 抛出异常也不怕<br /><br />    </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> 无论是 throw 跳出 还是 函数返回 ，p_pc 都会自动被 delete </span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">}</span></div><br /></blockquote><font face="Courier New" size="2">    看上去这样算是圆满了。<br /><br />     那我们是不是该把指针都替换成 auto_ptr 呢 ? 且慢 , auto_ptr 是为了存放指针而设计的 , 为了保证它保存的指针不被删除两次 , 当我们拷贝一个 auto_ptr 时 , 新的 auto_ptr 会得到那个指针的所有权 .<br /><br />     未完...</font><br /><img src ="http://www.cppblog.com/smartwhite/aggbug/10686.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/smartwhite/" target="_blank">哇哇小白</a> 2006-07-29 22:49 <a href="http://www.cppblog.com/smartwhite/articles/10686.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>