建構函式中丟擲的異常

2021-06-09 03:23:07 字數 2240 閱讀 1099

標準c++中定義建構函式是乙個物件構建自己,分配所需資源的地方,一旦建構函式執行完畢,則表明這個物件已經誕生了,有自己的行為和內部的執行狀態,之後還有物件的消亡過程(析構函式的執行)。可誰能保證物件的構造過程一定能成功呢?說不定系統當前的某個資源不夠,導致物件不能完全構建好自己。

物件總是由不斷的繼承或不斷的聚合而來,物件的構造過程實際上是這些所有的子物件按規定順序的構造過程,其中這些過程中的任何乙個子物件在構造時發生異常,物件都不能說自己完成了全部的構造過程,這種情況稱為物件的部分構造.因此這裡就有乙個棘手的問題,當發生物件的部分構造時,物件將析構嗎?如果時,又將如何析構呢?

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

(1) 物件的部分構造是很常見的,異常的發生點也完全是隨機的,程式設計師要謹慎處理這種情況;

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

建構函式中丟擲異常時概括性總結

(1) c++中通知物件構造失敗的唯一方法那就是在建構函式中丟擲異常;

(2) 建構函式中丟擲異常將導致物件的析構函式不被執行;

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

另一種做法,將對資源的申請,封裝到init函式中.

建立完物件後init.

但有乙個缺點,使用者必須記得在其它呼叫前,手動呼叫init.

析構函式中是不永許丟擲異常的,而且在c++標準中也特別宣告到了這一點。

c++異常處理模型是為c++語言量身設計的,更進一步的說,它實際上也是為c++語言中物件導向而服務的,我們在前面的文章中多次不厭其煩的宣告到,c++異常處理模型最大的特點和優勢就是對c++中的物件導向提供了最強大的無縫支援。好的,既然如此!那麼如果物件在執行期間出現了異常,c++異常處理模型有責任清除那些由於出現異常所導致的已經失效了的物件(也即物件超出了它原來的作用域),並釋放物件原來所分配的資源,這就是呼叫這些物件的析構函式來完成釋放資源的任務,所以從這個意義上說,析構函式已經變成了異常處理的一部分。不知大家是否明白了這段話所蘊含的真正內在涵義沒有,那就是上面的論述c++異常處理模型它其實是有乙個前提假設——析構函式中是不應該再有異常丟擲的。試想!如果物件出了異常,現在異常處理模組為了維護系統物件資料的一致性,避免資源洩漏,有責任釋放這個物件的資源,呼叫物件的析構函式,可現在假如析構過程又再出現異常,那麼請問由誰來保證這個物件的資源釋放呢?而且這新出現的異常又由誰來處理呢?不要忘記前面的乙個異常目前都還沒有處理結束,因此這就陷入了乙個矛盾之中,或者說無限的遞迴巢狀之中。所以c++標準就做出了這種假設,當然這種假設也是完全合理的,在物件的構造過程中,或許由於系統資源有限而致使物件需要的資源無法得到滿足,從而導致異常的出現,但析構函式完全是可以做得到避免異常的發生,畢竟你是在釋放資源呀!

系統非常複雜,不可能保證所有的程式設計師寫出的程式完全沒有bug。因此杜絕在析構函式中決不發生任何異常的這種保證確實是有點理想化了。那麼當無法保證在析構函式中不發生異常時,該怎麼辦?我們不能眼睜睜地看著系統崩潰呀!

其實還是有很好辦法來解決的。那就是把異常完全封裝在析構函式內部,決不讓異常丟擲函式之外。這是一種非常簡單,也非常有效的方法。按這種方法把上面的程式再做一點改動,那麼程式將避免了崩潰的厄運。如下:

class mytest_base

catch(…) {}

析構函式中丟擲異常時概括性總結

(1) c++中析構函式的執行不應該丟擲異常;

(2) 假如析構函式中丟擲了異常,那麼你的系統將變得非常危險,也許很長時間什麼錯誤也不會發生;但也許你的系統有時就會莫名奇妙地崩潰而退出了,而且什麼跡象也沒有,崩得你滿地找牙也很難發現問題究竟出現在什麼地方;

(3) 當在某乙個析構函式中會有一些可能(哪怕是一點點可能)發生異常時,那麼就必須要把這種可能發生的異常完全封裝在析構函式內部,決不能讓它丟擲函式之外.

其實很多程式設計師朋友受到過太多這種類似的冤枉,例如乙個程式原來執行挺好的,以後進行功能擴充後,程式卻時常出現崩潰現象。其實有時程式擴充時也沒新增多少**,而且相關程式設計師也很認真仔細檢查自己新增的**,確認後來新增的**確實沒什麼問題呀!可相關的負責人也許不這麼認為,覺得程式以前一直執行挺好的,經過你這一番修改之後就出錯了,能不是你新增的**所導致的問題嗎?真是程式開發領域的竇娥冤呀!其實這種推理完全是沒有根據和理由的,客觀公正一點地說,程式的崩潰與後來新增的模組**肯定是會有一定的相關性!但真正的bug也許就在原來的系統中一直存在,只不過以前一直沒誘發表現出來而已!

建構函式中丟擲的異常

建構函式中丟擲的異常 1 標準c 中定義建構函式是乙個物件構建自己,分配所需資源的地方,一旦建構函式執行完畢,則表明這個物件已經誕生了,有自己的行為和內部的執行狀態,之後還有物件的消亡過程 析構函式的執行 可誰能保證物件的構造過程一定能成功呢?說不定系統當前的某個資源不夠,導致物件不能完全構建好自己...

建構函式中丟擲的異常

建構函式中丟擲的異常 1 標準c 中定義建構函式是乙個物件構建自己,分配所需資源的地方,一旦建構函式執行完畢,則表明這個物件已經誕生了,有自己的行為和內部的執行狀態,之後還有物件的消亡過程 析構函式的執行 可誰能保證物件的構造過程一定能成功呢?說不定系統當前的某個資源不夠,導致物件不能完全構建好自己...

C 建構函式中丟擲的異常

分類 c c 程式設計 2011 04 19 10 03 4940人閱讀收藏 舉報c exception string class測試c 建構函式中丟擲的異常 1 標準c 中定義建構函式是乙個物件構建自己,分配所需資源的地 方,一旦建構函式執行完畢,則表明這個物件已經誕生了,有自己的行為和內部的執行...