MoreeffectiveC++:審慎使用異常規(guī)格

字號(hào):

毫無(wú)疑問(wèn),異常規(guī)格是一個(gè)引人注目的特性。它使得代碼更容易理解,因?yàn)樗鞔_地描述了一個(gè)函數(shù)可以?huà)伋鍪裁礃拥漠惓!5撬恢皇且粋€(gè)有趣的注釋。編譯器在編譯時(shí)有時(shí)能夠檢測(cè)到異常規(guī)格的不一致。而且如果一個(gè)函數(shù)拋出一個(gè)不在異常規(guī)格范圍里的異常,系統(tǒng)在運(yùn)行時(shí)能夠檢測(cè)出這個(gè)錯(cuò)誤,然后一個(gè)特殊函數(shù)unexpected將被自動(dòng)地調(diào)用。異常規(guī)格既可以做為一個(gè)指導(dǎo)性文檔同時(shí)也是異常使用的強(qiáng)制約束機(jī)制,它好像有著很誘人的外表。
    不過(guò)在通常情況下,美貌只是一層皮,外表的美麗并不代表其內(nèi)在的素質(zhì)。函數(shù)unexpected缺省的行為是調(diào)用函數(shù)terminate,而terminate缺省的行為是調(diào)用函數(shù)abort,所以一個(gè)違反異常規(guī)格的程序其缺省的行為就是halt(停止運(yùn)行)。在激活的stack frame中的局部變量沒(méi)有被釋放,因?yàn)閍bort在關(guān)閉程序時(shí)不進(jìn)行這樣的清除操作。對(duì)異常規(guī)格的觸犯變成了一場(chǎng)并不應(yīng)該發(fā)生的災(zāi)難。
    不幸的是,我們很容易就能夠編寫(xiě)出導(dǎo)致發(fā)生這種災(zāi)難的函數(shù)。編譯器僅僅部分地檢測(cè)異常的使用是否與異常規(guī)格保持一致。一個(gè)函數(shù)調(diào)用了另一個(gè)函數(shù),并且后者可能拋出一個(gè)違反前者異常規(guī)格的異常,(A函數(shù)調(diào)用B函數(shù),因?yàn)锽函數(shù)可能拋出一個(gè)不在A函數(shù)異常規(guī)格之內(nèi)的異常,所以這個(gè)函數(shù)調(diào)用就違反了A函數(shù)的異常規(guī)格 譯者注)編譯器不對(duì)此種情況進(jìn)行檢測(cè),并且語(yǔ)言標(biāo)準(zhǔn)也禁止它們拒絕這種調(diào)用方式(盡管可以顯示警告信息)。
    例如函數(shù)f1沒(méi)有聲明異常規(guī)格,這樣的函數(shù)就可以?huà)伋鋈我夥N類(lèi)的異常:
    extern void f1(); // 可以?huà)伋鋈我獾漠惓?BR>    假設(shè)有一個(gè)函數(shù)f2通過(guò)它的異常規(guī)格來(lái)聲明其只能拋出int類(lèi)型的異常:
    void f2() throw(int);
    f2調(diào)用f1是非常合法的,即使f1可能拋出一個(gè)違反f2異常規(guī)格的異常:
    void f2() throw(int)
    {
    ...
    f1(); // 即使f1可能拋出不是int類(lèi)型的
    //異常,這也是合法的。
    ...
    }
    當(dāng)帶有異常規(guī)格的新代碼與沒(méi)有異常規(guī)格的老代碼整合在一起工作時(shí),這種靈活性就顯得很重要。
    因?yàn)槟愕木幾g器允許你調(diào)用一個(gè)函數(shù)其拋出的異常與發(fā)出調(diào)用的函數(shù)的異常規(guī)格不一致,并且這樣的調(diào)用可能導(dǎo)致你的程序執(zhí)行被終止,所以在編寫(xiě)軟件時(shí)采取措施把這種不一致減小到最少。一種好方法是避免在帶有類(lèi)型參數(shù)的模板內(nèi)使用異常規(guī)格。例如下面這種模板,它好像不能拋出任何異常:
    // a poorly designed template wrt exception specifications
    template
    bool operator==(const T& lhs, const T& rhs) throw()
    {
    return &lhs == &rhs;
    }
    這個(gè)模板為所有類(lèi)型定義了一個(gè)操作符函數(shù)operator==。對(duì)于任意一對(duì)類(lèi)型相同的對(duì)象,如果對(duì)象有一樣的地址,該函數(shù)返回true,否則返回false。