異常機(jī)制的使用
根據(jù)上述規(guī)則,典型的try-catch的結(jié)構(gòu)示例如下:本文引用地址:http://m.butianyuan.cn/article/202581.htm
細(xì)心的讀者也許會發(fā)現(xiàn),上面例子中是通過引用來捕獲類的對象。當(dāng)異常對象類型為某個類時,有3種方式傳遞到catch子句里:指針、傳值和引用。也許大家首先想到的是指針,指針的確是效率很高的工具,而且不涉及到對象拷貝。但不要忘了,前面的規(guī)則15-0-2中明確指出,拋出的異常對象不應(yīng)該是指針類型。而對于傳值和引用,在MISRA C++中給出的規(guī)定是:通過引用捕獲異常。
規(guī)則15-3-5(強(qiáng)制):若異常對象為類的對象時,應(yīng)該通過引用來捕獲。
通過值傳遞,不但會增加拷貝對象的開銷,而且還會出現(xiàn)“退化”問題。所謂“退化”是指:如果異常對象是一個派生類對象,但被作為基類捕獲,那么只有基類的函數(shù)(包括虛函數(shù))能被調(diào)用,派生類中增加的數(shù)據(jù)成員都不能被訪問。通過引用捕獲則沒有這個問題。下面的例子具體地說明了“退化”問題:
鑒于類的構(gòu)造函數(shù)和析構(gòu)函數(shù)的特殊性,還有兩點需要注意。
規(guī)則15-3-3(強(qiáng)制):如果類的構(gòu)造函數(shù)和析構(gòu)函數(shù)是function-try-block結(jié)構(gòu)的,在catch處理程序中不能引用該類或其基類的非靜態(tài)成員。
這種行為的后果是不定的。比如說,當(dāng)構(gòu)造對象分配內(nèi)存時拋出了異常,這時該對象本身還不存在,訪問其成員也就出錯。相反,在析構(gòu)函數(shù)里,可能在異常處理程序執(zhí)行前該對象已被成功銷毀了,也就無從訪問其成員了。而類的靜態(tài)成員則沒有上述問題。
規(guī)則15-5-1(強(qiáng)制)。類的析構(gòu)函數(shù)退出后不能還有未處理的異常。
當(dāng)異常拋出時,會進(jìn)行棧展開。如果在某個析構(gòu)過程中引發(fā)沒有被處理的異常,程序?qū)圆欢ǖ姆绞浇K止。析構(gòu)函數(shù)拋出異常的問題在很多C++的書中都有討論,概括來說:析構(gòu)函數(shù)應(yīng)盡可能地避免拋出異常,如果的確無法避免,則析構(gòu)函數(shù)自己應(yīng)該包含處理所有可能拋出的異常的代碼。
4 小 結(jié)
異常機(jī)制是C++嶄新而高級的特性之一。與其他C++特性一樣,C++標(biāo)準(zhǔn)并沒有規(guī)定應(yīng)該如何來實現(xiàn)異常機(jī)制,這依賴于具體的編譯器。異常機(jī)制是有代價的,它會增加代碼大小和運(yùn)行開銷。以VC++為例,異常處理是通過在函數(shù)調(diào)用棧里增加許多相關(guān)的數(shù)據(jù)結(jié)構(gòu)來實現(xiàn)的,感興趣的讀者可以查看相關(guān)資料,這里不再進(jìn)一步討論;而且異常處理是在操作系統(tǒng)的協(xié)助下,由C++編譯器和運(yùn)行時異常處理庫共同完成的。如何合理地使用異常機(jī)制來提高程序的健壯性,MISRA C++給出了一些規(guī)范,但具體還需要程序員反復(fù)斟酌,甚至需要多次實驗。至此,關(guān)于MISRA-C++:2008的學(xué)習(xí)暫告一段落。
在這4期的講座中,我們主要討論了C++對于C新增的特性,列舉和解釋了其中有代表性的規(guī)則,且盡量使每篇文章都能涵蓋C++的一個重要特性。有些例子是在我們理解的基礎(chǔ)上加的,可能存在著錯誤或偏差,歡迎大家和我們共同討論。通過這4期介紹,希望大家能夠意識到:C++對于C并不是簡單的語言的改進(jìn),C++面向?qū)ο蟮乃枷霃母旧嫌绊懥塑浖募軜?gòu)。
可以預(yù)見,隨著嵌入式產(chǎn)業(yè)的飛速發(fā)展,在嵌入式領(lǐng)域C++將會有輝煌的前景。對C++進(jìn)行改造,使其適用于嵌入式環(huán)境,提高其可靠性,對于推動C++在嵌入式領(lǐng)域的應(yīng)用是很重要的。MISRA-C已經(jīng)在嵌入式C語言上取得了很大的成功,成為行業(yè)普遍認(rèn)同和遵循的規(guī)范。我們希望MISRA-C++也能和MISRA-C一樣,推動C++在嵌入式領(lǐng)域的規(guī)范化。
評論