2013-03-28 230 views
0

之前拋出異常防止構造C++通過構造函數體

我想一個類來throw其構造身體的大括號{利用自己的成員函數,以防止施工前的異常。我所定義的成員函數,它的目的僅僅是無條件throw異常,與任意選擇的非void返回類型和一個僞數據成員,其類型返回類型相匹配,這樣我可以通過構建與該數據成員觸發throw在構造函數初始化器列表中調用所述成員函數。這是有效的,但並不優雅,因爲在非玩具類中,虛擬變量不能用於其他目的,只能爲成員函數運行提供藉口,並且成員函數的非返回類型除了用於其他用途外,有一個藉口可以通過相同類型的虛擬數據成員的構造函數來調用它。

這個玩具編譯但不優雅:

class Toy 
{ 
public: 
    Toy() : dummy(preventer()) {} 
private: 
    int dummy; 
    int preventer() {throw -1; return 0;} 
}; 

#include <iostream> 

int main() 
{ 
    try 
    { 
     Toy t; 
    } 
    catch (const int& e) 
    { 
     std::cout << "caught the exception\n"; 
    } 
    return 0; 
} 

控制檯輸出:

caught the exception 

沒有虛擬變量,是有辦法的大括號之前拋出一個異常{的構造函數體?

+1

看到這個線程:http://stackoverflow.com/questions/2672398/throw-exception-from-constructor-initializer? – taocp 2013-03-28 02:23:30

+0

@Ken White,我不是特別想創建一個單例。一般來說,我只想知道如何在構造函數的正文之前防止構造。 – CodeBricks 2013-03-28 02:25:16

+0

明白了。 :-)我看到@SongWang發佈並刪除了我的評論的鏈接;一定發生了,就像你回答。 – 2013-03-28 02:26:30

回答

1

你能避免功能的假返回值是這樣的:

bool called = (function(), true); 

逗號運營商在右側的兩個表達式計算表達式反過來,丟棄所有,但最後的結果。我想知道的是,爲什麼你堅持要在開啓花括號之前這樣做。你究竟想在這裏達到什麼目的,你不能在函數中調用函數作爲體內的第一件事情?

需要注意的是,如果你想盡可能早地放棄,這樣做,在一個單獨的基類(您可以使用有私有繼承)可能是最好的解決方案。這是唯一的解決方案,可以阻止您構建其他基地,而您的解決方案不會。

+0

要回答你的問題:我試圖儘可能防止施工,而不是爲了性能原因在ctor主體中。我想在某些運行時確定的用例中阻止構造。在這些情況下,我希望在昂貴的數據成員依次構建之前阻止構建。 – CodeBricks 2013-03-29 16:00:28

+0

在這種情況下,第一個基類的構造函數將是一個好地方。不過,我不相信你的方法是有限的。分配內存和處理異常是一項昂貴的操作,所以我寧願避免這種情況。這是你的決定。祝你好運! – 2013-03-29 17:41:27

+0

我假設你的'bool called =(function(),true);'逗號運算符方法是類內定義數據成員初始值設定項的一部分。在ctor初始化器中有沒有辦法做到這一點? – CodeBricks 2013-03-29 18:45:36

2

是的,你可以使用一個基類,而不是一個數據成員,然後調用基類的構造函數。

需要注意的是GNU調試gdb的舊版本(幾年前)未能就這種異常中斷。

但是,工作與Visual C++ OK,我相信也與GNU工具鏈的現代版本。

+0

+1,很好的答案,謝謝。給了一個加票,但我必須選擇一個答案來接受,並且接受的答案除了繼承之外還提供了一個額外的解決方案。 – CodeBricks 2013-03-29 23:42:48