2010-01-11 116 views
6

我想封裝Win32錯誤(從GetLastError()返回)以某種形式的異常類。但是,我不希望只有一個Win32異常,而是希望能夠獲得可用於常見錯誤的特殊異常,如ERROR_ACCESS_DENIED。C++異常設計模式

例如,我不得不聲明如下類別:

class WindowsException : public std::exception 
{ 
public: 
    static WindowsException Create(DWORD lastError); 
    //blah 

}; 

class ErrorAccessDeniedException : public WindowsException 
{ 
public: 
    //blah 
}; 

不過,我想在Win32異常負責選擇合適的異常返回。也就是說,異常的運動員應該是這樣的:

int DangerousMethod() { 
    throw WindowsAPI::WindowsException::Create(GetLastError()); 
} 

及捕獲可能看起來像:

try 
{ 
    DangerousMethod(); 
} catch(WindowsAPI::ErrorAccessDeniedException ex) 
{ 
    //Code for handling ERROR_ACCESS_DENIED 
} catch(WindowsAPI::WindowsException ex) 
{ 
    //Code for handling other kinds of error cases. 
} 

我的問題是,如果WindowsException ::創建工廠方法返回一個WindowsException,然後子類型(潛在的ErrorAccessDeniedException)被分割爲基本類型。也就是說,該實例不能是多態的。我不想使用new'd指針,因爲這會強制異常處理程序在完成時刪除它。

有誰知道可以優雅地解決這個問題的設計解決方案嗎?

Billy3

+0

您可以創建一個宏來聲明幾個不同的異常類型,並根據'GetLastError()'的值創建一個拋出工廠。但說實話,我只見過這樣的問題:http://code.google.com/p/synergy-plus/source/browse/trunk/lib/arch/XArchWindows.cpp – 2010-01-11 02:08:35

+0

問題與該解決方案是它不允許您創建特定的catch處理程序 - 對於該類型的所有異常,這是一種單一的異常類型。 – 2010-01-11 02:23:55

+1

你應該通過參考的方式來捕捉你的例外,而不是像上面的代碼示例所顯示的那樣通過價值 – 2010-01-11 07:55:31

回答

12

變化

int DangerousMethod() { 
    throw WindowsAPI::WindowsException::Create(GetLastError()); 
} 

int DangerousMethod() { 
    WindowsAPI::WindowsException::Throw(GetLastError()); 
} 

含義,而不是返回異常,然後把它扔(這將切片,當你觀察到的),有你的幫手/工廠方法直接拋出。

+1

... DUH BILL :)非常感謝。 – 2010-01-11 02:09:07

+2

當我讀到這個問題時,我發明了一個複雜的解決方案,其中每個可能的異常的靜態實例都由框架維護。一旦你看到它,Terry的解決方案只是「DUH明顯」。 (或者,或者我們都是愚蠢的:-) – 2010-01-11 02:21:49

+1

WindowsAPI :: WindowsException :: Throw()是什麼問題,並讓該函數調用GetLastError()? – sbi 2010-01-11 12:13:18

2

一些更多的異常處理的背景閱讀:http://www.informit.com/articles/article.aspx?p=373339

的類型切片和重新拋出的說明:

當重新拋出異常E, 寧願寫隨便扔;而不是 的投擲e;因爲第一種形式 總是保留 重新排列的對象的多態性。

+2

不是說這是不好的信息,但是......這與我的問題有什麼關係? – 2010-01-11 02:20:58

+0

只是警告更多可能的異常處理切片問題。 – 2010-01-11 04:24:38