2013-10-22 61 views
0

比方說,我有這樣的:型鑄件例外

namespace MyNamespace{ 

class Exception : public std::runtime_error 
{ 
public: 
    explicit Exception(const std::string &msg) : std::runtime_error(msg) {} 
}; 

} //namespace MyNamespace 

而且還有一個碼的地方在我的程序:

try{ 
    foo(); 
} 
catch (const MyNamespace::Exception &exc){ 
    std::cout << exc.what(); 
} 

的問題是(我要你檢查我) - 將我趕上了異常,如果我在寫foo的:

1)throw MyNamespace::Exception("Hello world!");

在這裏,我想,是的,我會的,是因爲我明確指出了異常的類型(並且它是「顯式」關鍵字的必要條件),並且std :: string沒有「顯式」關鍵字,這意味着我可以拋出「Hello world!」。不是的std :: string( 「世界,你好!」)

2)throw MyNamespace::Exception(std::string("Hello world!"));

obviosly,我會的。

3)throw "Hello world!";

在這裏,我想,不,我不會,關鍵字 「顯性」 存在的原因。

4)throw std::string("Hello world");

沒有(同樣的原因)

和5)我趕對子級在3-4的情況下expections如果我沒有明確的關鍵字? (我認爲是)

更新: 6)當臨時對象std :: string將被創建?在什麼時間點?

回答

2

你對1-4的回答是正確的,但背後的理由是有點關閉。

3)這與explicit關鍵字無關。 throw之後的表達式的類型是const char[12],並且由規則引發的異常的類型爲const char*

4)再次,與explicit字符串構造函數無關,真的。拋出的類型是std::string,並且只有std::string(帶或不帶引用)類型的處理程序才能捕獲它。

5)很明顯,沒有。

6)拋出異常時。

+0

感謝您的回答,但我沒有意識到第六個問題的答案:爲什麼會在異常是_thrown_時創建,而不是_cought_?我們是否在談論std :: string的權利? –

+0

因爲語言規範是這樣說的。 catch子句不知道要創建什麼類型的對象,因爲單個處理程序可以匹配幾個不同的throw表達式。無論我們是否在討論'std :: string'都不是真正相關的。 – jrok

+0

啊,我的意思是有點不一樣。如果我們只拋出像「Hello world!」這樣的const char [x],就會創建臨時對象std :: string。 –

1

您的3和4的理由是錯誤的,因此,如此,你的答案5.這裏的原因:

當你catch一個例外,沒有轉化爲每一個執行,除轉化爲基類。所以catch (Foo const&)將永遠不會捕獲任何可轉換爲Foo的東西,除了Foo的子類。這是的原因,而不是explicit構造函數,你的代碼不會拋出std::stringchar[]

+0

感謝您的回答,我現在明白了。 –

2

從3-5的措辭中,您顯然認爲C++試圖將throwcatch語句匹配,就好像它從重載函數中選擇最佳匹配進行調用。事實並非如此。 throw聲明與任何catch聲明分開考慮 - 事實上,在捕獲代碼被寫入之前,您可以編譯函數foo及其throw語句,因此它不能選擇將std::string轉換爲捕獲代碼最終尋找的某種類型......它可能不知道這一點。

拋出的值的類型完全取決於throw的參數類型,因爲如果表達式沒有出現在throw中,它會在周圍的上下文中被理解。例如:

void foo() 
{ 
    ... 
    throw XXX; 
} 

...拋出相同的類型......

void foo() 
{ 
    ... 
    auto what_will_be_thrown = XXX; 
    throw what_will_be_thrown; 
} 

轉換像const char*std::string追趕的時候,雖然你可以通過趕上派生類型不應用公共基類(用於引用或指針),當然你可以使用const引用等等來捕獲類型。

Re 6) - 無論值的類型是什麼,它都是在第調用構造函數,就像調用任何其他函數調用的時間方式一樣,但在這種情況下,被拋出的對象可能構建在與正常調用棧不同的內存區域中,這樣它就可以在堆棧解除時繼續存在尋找匹配的catch語句。不過,編譯器編排的具體方式並未在標準中指定。

+0

這似乎很詳細和認知的答案,謝謝你。 –