這是我的一個面試問題。處理構造函數的異常
令人驚訝的是,我從來沒有想過給自己一個這樣的問題。
我們可以在構造函數C++中有異常處理嗎?
現在時態並沒有多想我說「是的,我們可以做一個constructor.lets說我們正在使用new運算符分配一些內存到一個指針成員,它會拋出一個錯誤的alloc異常,這樣就有可能會有異常提出「
然後後來我認爲構造函數永遠不會返回一個值。那麼構造函數中的異常怎麼會被抓到。現在我問這個問題了!
有人能幫我擺脫這種困惑嗎?
這是我的一個面試問題。處理構造函數的異常
令人驚訝的是,我從來沒有想過給自己一個這樣的問題。
我們可以在構造函數C++中有異常處理嗎?
現在時態並沒有多想我說「是的,我們可以做一個constructor.lets說我們正在使用new運算符分配一些內存到一個指針成員,它會拋出一個錯誤的alloc異常,這樣就有可能會有異常提出「
然後後來我認爲構造函數永遠不會返回一個值。那麼構造函數中的異常怎麼會被抓到。現在我問這個問題了!
有人能幫我擺脫這種困惑嗎?
看到這個GOTW Constructor Failures問題哪些地址您的查詢有點並繼續說這是浪費時間。
+1我打算寫一個關於function-try-block的選項和它的許多缺陷,但我不會接近Sutter的描述:) – 2011-04-21 10:57:17
這是一篇非常有趣的文章,def + 1 – Justin 2011-04-21 19:15:04
C++具有類似於其他語言的try-catch子句。該教程可以在網上查到:http://www.cplusplus.com/doc/tutorial/exceptions/
編輯:例如變成完全的工作代碼
#include <iostream>
using namespace std;
class A
{
public:
void f(){
throw 10;
}
A(){
try{
f();
}
catch(int e){
cout << "Exception caught\n";
}
}
};
int main (int argc, const char * argv[])
{
A a;
return 0;
}
這將產生輸出:
Exception caught
@ laas.i知道有很多documents.But我特別要求在構造函數中的異常處理。這並不代表我的問題。 – Vijay 2011-04-21 10:50:09
C++沒有'finally'塊,並且C++中的異常處理在許多方面與Java等語言有所不同,例如對於清理,C++使用http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization – helpermethod 2011-04-21 10:53:14
@Helper方法 - 你當然是對'finally'正確的,但據我瞭解,@ zombie詢問**構造函數內的異常處理**,所以我的示例仍然有效,或者應該糾正問題。我用更多的代碼更新我的答案。 – Laas 2011-04-21 11:27:45
構造函數沒有返回類型, 所以不可能使用返回碼 。 構造函數失敗的最好方法是因此給 拋出異常。如果你沒有 使用異常的選項, 「最不壞」的解決辦法是把 對象變成「殭屍」狀態由 設置內部狀態位使 對象的行爲有點像它的儘管它在技術上仍然 活着,但它仍然死亡。
你會趕上調用代碼例外,而不是在構造函數中。
查看How can I handle a constructor that fails?瞭解更多詳情(實際上,我建議閱讀關於異常處理的整個頁面,真正有啓發性)。
我讀過這篇文章,但我期待人們在這種場景中使用的一些實用方法。 – Vijay 2011-04-21 10:51:31
+1,但人們必須說這個問題也有點棘手。通常,當你以某種方式在構造函數中失敗時,它就會拋出一個構造函數,這完全可以在構造函數中嘗試/捕獲以處理其他失敗並避免構造函數首先失敗(或重新拋出)。根據情況,這可能是可取的。例如,如果在構造函數中構造兩個對象,並且第二個引發bad_alloc,那麼你會怎麼做?捕獲調用代碼中的異常將泄漏第一個對象。在構造函數內處理避免了這一點。 – Damon 2011-04-21 10:56:53
@ zombie:有什麼場景?從構造函數中拋出異常?構造函數失敗?一個捕獲異常的構造函數? – forsvarir 2011-04-21 10:57:21
異常處理和返回類型完全不同。當程序在構造函數中發現異常時,它會通過catch塊[如果使用]或拋出調用方(main())將該異常拋出。在這種情況下,我們在構造函數和異常處理中都有catch塊。一旦處理異常,構造函數/函數中的其餘語句將開始執行。看下面的例子,
class A
{
public:
A(){
printf("Hi Constructor of A\n");
try
{
throw 10;
}
catch(...)
{
printf("the String is unexpected one in constructor\n");
}
printf("Hi Constructor of A\n");
}
~A(){
printf("Hi destructor of A\n");
}
};
int main()
{
try{
A obj ;
throw "Bad allocation";
}
catch(int i)
{
printf("the Exception if Integer is = %d\n", i);
}
catch(double i)
{
printf("the Exception if double is = %f\n", i);
}
catch(A *objE)
{
printf("the Exception if Object \n");
}
catch(...)
{
printf("the Exception if character/string \n");
}
printf("Code ends\n");
return 0;
}
這產生輸出:
Start: Constructor of A
the String is unexpected one in constructor
End: Constructor of A
Hi destructor of A
the Exception if character/string
Code ends
你會捕獲該異常調用代碼,而不是在構造函數中。 – helpermethod 2011-04-21 10:48:10
異常不會以與返回值相同的方式返回,它們將堆棧跳到第一個適當的catch塊,因此儘管您無法從構造函數返回值,但可以從中引發異常。 – forsvarir 2011-04-21 10:50:30
@Helper方法:如果您在構造函數中分配了內存,您肯定會想要在構造函數中捕獲異常,以便您可以取消分配內存(然後重新拋出)。但更智能的是讓對象只動態分配一個對象,所以你不需要執行這種手動清理。 – 2011-04-21 11:17:21