2015-09-11 14 views
5

Ở đầu chương trình của tôi, tôi có một trình xử lý ngoại lệ.
Nó trông giống như sau:Tôi có thể viết một điều khoản bắt tương tự như các mẫu chức năng viết tắt không?

try{ 
    //majority of program 
} 
catch(...){ 
    Handle_All_Exceptions(); 
} 


void Handle_All_Exceptions(){ 
    try{throw;} 
    catch(TypeA const& e){Handle(e)  ;} 
    catch(TypeB const& e){Handle(e)  ;} 
    catch(TypeC const& e){Handle(e)  ;} 
    catch(TypeD const& e){Handle(e)  ;} 
    catch(...)   {Handle_Unknown();} 

} 

void Handle(TypeA const& e){ 
    //... 
} 
void Handle(TypeB const& e){ 
    //... 
} 
void Handle(TypeC const& e){ 
    //... 
} 
void Handle(TypeD const& e){ 
    //... 
} 
void Handle_Unknown(){ 
    //... 
} 

Như tôi đã có được nhiều loại ngoại lệ một nhiều hơn,
Tôi muốn để có một cách tiếp cận chung chung hơn.
Làm cách nào để áp dụng lập trình chung cho hàmHandle_All_Exceptions?


Có thể điều này có thể xảy ra trong các phiên bản C++ mới hơn không?

catch(auto e){Handle(e)}; 
catch(...){Handle_Unknown();} 
+0

Trường hợp ngoại lệ của bạn có lớp cơ sở chung không? – robert

+0

@robert, Không, nhưng tôi giả sử thừa kế std :: exception có thể là một cách tiếp cận tốt hơn. –

+1

@TrevorHickey đề nghị bạn xem xét std :: runtime_error cho lớp cơ sở của bạn: http: //en.cppreference.com/w/cpp/error/runtime_error –

Trả lời

0

Không thể thay đổi đáng kể ngôn ngữ và hệ thống ngoại lệ của ngôn ngữ. Trong khi các trình xử lý các điều khoản bắt và các tham số hàm có thể trông giống như cú pháp tương tự, chúng hoạt động khá khác nhau. Xem xét:

struct up {}; 
struct down { constexpr down(up) noexcept {} }; 

void func(down const&) {} 
void except() 
{ 
    try { 
     throw up {}; 
    } catch(down const&) {} 
} 

int main() 
{ 
    func(up {}); // fine 
    except(); // exception `up` escapes 
} 

Coliru

Nói cách khác, một tham số down const& sẽ chấp nhận bất cứ điều gì đó là mui trần-down, trong khi một handler down const& sẽ liên kết với đối tượng ngoại lệ kiểu down hoặc của một loại một cách rõ ràng, công khai bắt nguồn từ từ down.

Sự khác biệt lớn ở đây là mối quan hệ của biểu mẫu 'có thể chuyển đổi thành' có thể có nhiều dạng. Trong ví dụ của chúng tôi, chúng tôi đã sử dụng một hàm tạo chuyển đổi, nhưng thay vào đó chúng tôi có thể sử dụng toán tử chuyển đổi bên trong up. Trong khi đó là (công khai, rõ ràng) có nguồn gốc từ 'chỉ có thể được chọn tham gia theo một cách đơn giản, và tại chính xác một vị trí toàn chương trình: bất cứ nơi nào có kiểu dẫn xuất. Điều này rất quan trọng khi chúng tôi tính đến việc biên dịch riêng biệt. Hãy xem xét các chương trình sau đây:

// a.cpp 

// defined in b.cpp 
void throws() noexcept(false); 

template<typename X> 
concept bool Fooable = requires(X x) { x.foo(); } 

int main() 
{ 
    try { 
     throws(); 

     // imaginary syntax for catching models of a concept 
    } catch(Fooable const&) {} 
} 

// b.cpp 

// defined in c.cpp 
struct other; 

struct model { 
    void foo() {} 
    other* foo(int) { return nullptr; } 
    void bar() {} 
}; 

void throws() noexcept(false) 
{ throw model {}; } 

// c.cpp omitted 

Khi b.cpp được biên dịch, trình biên dịch không có cách nào để biết rằng a.cpp sẽ đặt câu hỏi 'Có phải đó là đối tượng bạn đang ném khả năng x.foo()?'. Nên nó bi quan ghi lại rằng thực tế dù sao (trong cùng một cách theo các quy tắc hiện tại 'có nguồn gốc từ' mối quan hệ, nếu có, được ghi lại ở đâu đó)? Nên nó cũng ghi lại một thực tế rằng model có khả năng x.bar(), mặc dù chương trình đầy đủ không cần nó? Điều gì xảy ra nếu Fooable thay vào đó được thử nghiệm cho x.foo(0)->baz()? Ở đâu, khi nào và như thế nào sẽ được ghi lại nếu other được định nghĩa sao cho biểu thức có ý nghĩa? Lưu ý cách modelother được xác định riêng và mỗi người không biết (nhiều) về người kia.

Chắc chắn những gì bạn yêu cầu không phải là không thể, nhưng tôi hy vọng chúng tôi có thể đồng ý với hệ thống chúng tôi hiện có và sẽ cần nhiều nỗ lực trước khi nó hoạt động. Theo các quy tắc hiện hành, việc lập trình chung cho các trường hợp ngoại lệ chỉ có thể đi xa, sử dụng các hệ thống phân cấp theo kiểu cũ là con đường của sự kháng cự ít nhất.

Các vấn đề liên quan