• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            C++分析研究  
            C++
            日歷
            <2013年9月>
            25262728293031
            1234567
            891011121314
            15161718192021
            22232425262728
            293012345
            統計
            • 隨筆 - 92
            • 文章 - 4
            • 評論 - 4
            • 引用 - 0

            導航

            常用鏈接

            留言簿

            隨筆檔案

            文章檔案

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

             

              構造函數中拋出的異常

              1、標準C++中定義構造函數是一個對象構建自己,分配所需資源的地方,一旦構造函數執行完畢,則表明這個對象已經誕生了,有自己的行為和內部的運行狀態,之后還有對象的消亡過程(析構函數的執行)。可誰能保證對象的構造過程一定能成功呢?說不定系統當前的某個資源不夠,導致對象不能完全構建好自己(人都有畸形兒,更何況別的呢?朋友們!是吧!),因此通過什么方法來表明對象的構造失敗了呢?C++程序員朋友們知道,C++中的構造函數是沒有返回值的,所以不少關于C++編程方面的書上得出結論:"因為構造函數沒有返回值,所以通知對象的構造失敗的唯一方法那就是在構造函數中拋出異常".主人公阿愚非常不同意這種說法,誰說的,便不信邪!雖然C++標準規定構造函數是沒有返回值,可我們知道每個函數實際上都會有一個返回值的,這個值被保存在eax寄存器中,因此實際上是有辦法通過編程來實現構造函數返回一個值給上層的對象創建者。當然即便是構造函數真的不能有返回值,我們也可以通過一個指針類型或引用類型的出參來獲知對象的構造過程的狀態。示例如下:

              class MyTest_Base

              {

              public:

              MyTest_Base (int& status)

              {

              //do other job

              // 由于資源不夠,對象構建失敗

              // 把status置0,通知對象的構建者

              status = 0;

              }

              protected:

              };

              void main()

              {

              int status;

              MyTest_Base obj1(status);

              // 檢查對象的構建是否成功

              if(status ==0) cout 《 "對象構建失敗" 《 endl;

              }

              程序運行的結果是:

              對象構建失敗

              是啊!上面我們不也得到了對象構造的成功與否的信息了嗎?可大家有沒有覺得這當中有點問題?主人公阿愚建議大家在此停留片刻,仔細想想它會有什么問題?OK!也許大家都知道了問題的所在,來驗證一下吧!

              class MyTest_Base

              {

              public:

              MyTest_Base (int& status)

              {

              //do other job

              // 由于資源不夠,對象構建失敗

              // 把status置0,通知對象的構建者

              status = 0;

              }

              virtual ~ MyTest_Base ()

              {

              cout 《 "銷毀一個MyTest_Base類型的對象" 《 endl;

              }

              protected:

              };

              void main()

              {

              int status;

              MyTest_Base obj1(status);

              // 檢查對象的構建是否成功

              if(status ==0) cout 《 "對象構建失敗" 《 endl;

              }

              程序運行的結果是:

              對象構建失敗

              銷毀一個MyTest_Base類型的對象

              沒錯,對象的析構函數被運行了,這與C++標準中所規定的面向對象的一些特性是有沖突的。一個對象都沒有完成自己的構造,又何來析構!好比一個夭折的畸形兒還沒有出生,又何來死之言。因此這種方法是行不通的。那怎么辦?那就是上面那個結論中的后一句話是對的,通知對象的構造失敗的唯一方法那就是在構造函數中拋出異常,但原因卻不是由于構造函數沒有返回值而造成的。恰恰相反,C++標準中規定構造函數沒有返回值正是由于擔心很容易與面向對象的一些特性相沖突,因此干脆來個規定,構造函數不能有返回值(主人公阿愚的個人理解,有不同意見的朋友歡迎討論)。

              2、構造函數中拋出異常將導致對象的析構函數不被執行。哈哈^-^,阿愚很開心,瞧瞧!如果沒有C++的異常處理機制鼎立支持,C++中的面向對象特性都無法真正實現起來,C++標準總不能規定所有的對象都必須成功構造吧!這也太理想化了,也許只有等到共產主義社會實現的那一天(CPU可以隨便拿,內存可以隨便拿,所有的資源都是你的!)才說不定有可能·····,所以說C++的異常處理和面向對象確實是誰也離不開誰。當然示例還是要看一下,如下:

              class MyTest_Base

              {

              public:

              MyTest_Base (string name = "") : m_name(name)

              {

              throw std::exception("在構造函數中拋出一個異常,測試!");

              cout 《 "構造一個MyTest_Base類型的對象,對象名為:"《m_name 《 endl;

              }

              virtual ~ MyTest_Base ()

              {

              cout 《 "銷毀一個MyTest_Base類型的對象,對象名為:"《m_name 《 endl;

              }

              void Func() throw()

              {

              throw std::exception("故意拋出一個異常,測試!");

              }

              void Other() {}

              protected:

              string m_name;

              };

              void main()

              {

              try

              {

              // 對象構造時將會拋出異常

              MyTest_Base obj1("obj1");

              obj1.Func();

              obj1.Other();

              }

              catch(std::exception e)

              {

              cout 《 e.what() 《 endl;

              }

              catch(…)

              {

              cout 《 "unknow exception"《 endl;

              }

              }

              程序的運行結果將會驗證:"構造函數中拋出異常將導致對象的析構函數不被執行"

              3、是不是到此,關于構造函數中拋出異常的處理的有關討論就能結束了呢?非也!非也!主人公阿愚還有進一步的故事需要講述!來看一個更復雜一點的例子吧!如下:

              class MyTest_Base

              {

              public:

              MyTest_Base (string name = "") : m_name(name)

              {

              cout 《 "構造一個MyTest_Base類型的對象,對象名為:"《m_name 《 endl;

              }

              virtual ~ MyTest_Base ()

              {

              cout 《 "銷毀一個MyTest_Base類型的對象,對象名為:"《m_name 《 endl;

              }

              void Func() throw()

              {

              throw std::exception("故意拋出一個異常,測試!");

              }

              void Other() {}

              protected:

              string m_name;

              };

              class MyTest_Parts

              {

              public:

              MyTest_Parts ()

              {

              cout 《 "構造一個MyTest_Parts類型的對象" 《 endl;

              }

              virtual ~ MyTest_Parts ()

              {

              cout 《 "銷毀一個MyTest_Parts類型的對象"《 endl;

              }

              };

              class MyTest_Derive : public MyTest_Base

              {

              public:

              MyTest_Derive (string name = "") : m_component(), MyTest_Base(name)

              {

              throw std::exception("在MyTest_Derive對象的構造函數中拋出了一個異常!");

              cout 《 "構造一個MyTest_Derive類型的對象,對象名為:"《m_name 《 endl;

              }

              virtual ~ MyTest_Derive ()

              {

              cout 《 "銷毀一個MyTest_Derive類型的對象,對象名為:"《m_name 《 endl;

              }

              protected:

              MyTest_Parts m_component;

              };

              void main()

              {

              try

              {

              // 對象構造時將會拋出異常

              MyTest_Derive obj1("obj1");

              obj1.Func();

              obj1.Other();

              }

              catch(std::exception e)

              {

              cout 《 e.what() 《 endl;

              }

              catch(…)

              {

              cout 《 "unknow exception"《 endl;

              }

              }

              程序運行的結果是:

              構造一個MyTest_Base類型的對象,對象名為:obj1

              構造一個MyTest_Parts類型的對象

              銷毀一個MyTest_Parts類型的對象

              銷毀一個MyTest_Base類型的對象,對象名為:obj1

              在MyTest_Derive對象的構造函數中拋出了一個異常!

              上面這個例子中,MyTest_Derive從MyTest_Base繼承,同時MyTest_Derive還有一個MyTest_Parts類型的成員變量。現在MyTest_Derive構造的時候,是在父類MyTest_Base已構造完畢和MyTest_Parts類型的成員變量m_component也已構造完畢之后,再拋出了一個異常,這種情況稱為對象的部分構造。是的,這種情況很常見,對象總是由不斷的繼承或不斷的聚合而來,對象的構造過程實際上是這些所有的子對象按規定順序的構造過程,其中這些過程中的任何一個子對象在構造時發生異常,對象都不能說自己完成了全部的構造過程,因此這里就有一個棘手的問題,當發生對象的部分構造時,對象將析構嗎?如果時,又將如何析構呢?托福答案

              從運行結果可以得出如下結論:

              (1) 對象的部分構造是很常見的,異常的發生點也完全是隨機的,程序員要謹慎處理這種情況;

              (2) 當對象發生部分構造時,已經構造完畢的子對象將會逆序地被析構(即異常發生點前面的對象);而還沒有開始構建的子對象將不會被構造了(即異常發生點后面的對象),當然它也就沒有析構過程了;還有正在構建的子對象和對象自己本身將停止繼續構建(即出現異常的對象),并且它的析構是不會被執行的。sat答案

              構造函數中拋出異常時概括性總結

              (1) C++中通知對象構造失敗的唯一方法那就是在構造函數中拋出異常;

              (2) 構造函數中拋出異常將導致對象的析構函數不被執行;

              (3) 當對象發生部分構造時,已經構造完畢的子對象將會逆序地被析構;

              (4) 其是還是那句話, "C++的異常處理不會破壞任何一條面向對象的特性!",因此主人公阿愚再次建議朋友們,牢牢記住這一條!

            posted on 2014-01-10 21:30 HAOSOLA 閱讀(657) 評論(0)  編輯 收藏 引用
             
            Copyright © HAOSOLA Powered by: 博客園 模板提供:滬江博客
            PK10開獎 PK10開獎
            欧美午夜A∨大片久久| 亚洲伊人久久成综合人影院 | 中文国产成人精品久久亚洲精品AⅤ无码精品 | 大伊人青草狠狠久久| 日本一区精品久久久久影院| 一本一道久久精品综合| 久久久免费观成人影院| 无码AV波多野结衣久久| 国产亚洲精午夜久久久久久 | 色综合久久久久综合体桃花网| 久久精品人人做人人爽97| 欧美午夜精品久久久久久浪潮| 欧美伊人久久大香线蕉综合| 久久99免费视频| 人妻丰满AV无码久久不卡| 久久久精品无码专区不卡| 高清免费久久午夜精品| 亚洲欧美国产日韩综合久久| 国内精品久久久久伊人av| 人妻少妇久久中文字幕| 久久久久国色AV免费看图片| 国内精品伊人久久久久av一坑 | 国产高清国内精品福利99久久| 欧美噜噜久久久XXX| 中文成人无码精品久久久不卡 | 久久久久亚洲AV无码永不| 久久夜色精品国产www| 66精品综合久久久久久久| 久久精品中文无码资源站| 伊人久久大香线蕉成人| 久久天天躁狠狠躁夜夜2020老熟妇| 久久久久亚洲AV无码网站| 久久精品人人做人人妻人人玩| 久久久无码精品亚洲日韩蜜臀浪潮 | 女人香蕉久久**毛片精品| 久久久久亚洲精品无码蜜桃| 一本色道久久HEZYO无码| 亚洲精品国产字幕久久不卡| 欧美激情一区二区久久久| 国产成人精品综合久久久久| 精品伊人久久久|