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 model
và other
đượ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.
Nguồn
2015-09-13 17:54:23
Trường hợp ngoại lệ của bạn có lớp cơ sở chung không? – robert
@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. –
@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 –