2010-01-11 36 views
6

Tôi muốn đóng gói các lỗi Win32 (những lỗi được trả về từ GetLastError()) trong một số dạng của lớp ngoại lệ. Thay vì có một ngoại lệ Win32 duy nhất, tuy nhiên, tôi muốn có thể có một ngoại lệ chuyên biệt có thể bắt được cho các lỗi phổ biến, chẳng hạn như ERROR_ACCESS_DENIED.Mẫu thiết kế ngoại lệ C++

Ví dụ, tôi muốn có các lớp học tuyên bố như thế này:

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

}; 

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

Tuy nhiên, tôi muốn ngoại trừ Win32 chịu trách nhiệm về chọn ngoại trừ quyền trở lại. Đó là, ném những ngoại lệ nên trông giống như:

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

và catcher có thể trông giống như:

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

Vấn đề của tôi là nếu WindowsException :: Tạo phương pháp nhà máy trả về một WindowsException, sau đó subtype (có khả năng là ErrorAccessDeniedException) được cắt xuống kiểu cơ sở. Đó là, trường hợp không thể được đa hình. Tôi không muốn sử dụng một con trỏ mới, bởi vì điều đó sẽ buộc xử lý ngoại lệ để xóa nó khi nó được thực hiện.

Có ai biết giải pháp thiết kế có khả thi để giải quyết vấn đề này một cách thanh lịch không?

Billy3

+0

Bạn có thể tạo macro để khai báo một vài loại ngoại lệ khác nhau và tạo một nhà máy để ném dựa trên giá trị của 'GetLastError()'; nhưng thành thật mà nói, tôi chỉ từng thấy vấn đề này được tiếp cận như vậy: http://code.google.com/p/synergy-plus/source/browse/trunk/lib/arch/XArchWindows.cpp –

+0

Vấn đề với giải pháp đó là nó không cho phép bạn tạo các trình xử lý bắt cụ thể - đó là một loại ngoại lệ duy nhất cho tất cả các ngoại lệ của loại đó. –

+1

Bạn nên nắm bắt ngoại lệ của bạn bằng cách tham chiếu bằng cách này, không phải bằng giá trị như mẫu mã trên của bạn hiện đang hiển thị –

Trả lời

12

Thay đổi

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

Để

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

Ý nghĩa, thay vì trả lại những ngoại lệ sau đó ném nó (mà sẽ cắt, như bạn quan sát), có helper của bạn/máy phương pháp ném trực tiếp.

+1

... DUH BILL :) Cảm ơn bạn rất nhiều. –

+2

Như tôi đã đọc câu hỏi tôi đã phát minh ra một giải pháp phức tạp, nơi một trường hợp tĩnh của mọi ngoại lệ có thể được duy trì bởi khuôn khổ. Giải pháp của Terry chỉ là "DUH Rõ ràng" một khi bạn đã nhìn thấy nó. (Hoặc là, hoặc cả hai chúng ta đều ngu ngốc :-) –

+1

Có gì sai với 'WindowsAPI :: WindowsException :: Throw()' và cho phép hàm đó gọi 'GetLastError()'? – sbi

2

Một số chi tiết ngoại trừ nền xử lý đọc: http://www.informit.com/articles/article.aspx?p=373339

Lưu ý về kiểu cắt và rethrowing:

Khi rethrowing một ngoại lệ đ thích viết chỉ ném; thay vào đó ném e; bởi vì hình thức đầu tiên luôn duy trì tính đa hình của đối tượng được khôi phục .

+2

Không nói đó là thông tin xấu, nhưng ... điều đó có liên quan gì đến câu hỏi của tôi? –

+0

Chỉ cần cảnh báo về các vấn đề có thể xảy ra với xử lý ngoại lệ. –