Câu trả lời:
std::exception
là lớp có mục đích duy nhất là đóng vai trò là lớp cơ sở trong hệ thống phân cấp ngoại lệ. Nó không có công dụng khác. Nói cách khác, về mặt khái niệm nó là một thứ trừu tượng lớp (mặc dù nó không được định nghĩa là lớp trừu tượng theo nghĩa C ++ của thuật ngữ này).
std::runtime_error
là một lớp chuyên biệt hơn, giảm dần từ std::exception
, dự định được ném trong trường hợp có nhiều lỗi thời gian chạy . Nó có một mục đích kép. Nó có thể bị ném bởi chính nó hoặc nó có thể đóng vai trò là lớp cơ sở cho các loại ngoại lệ lỗi thời gian chạy chuyên dụng khác nhau, chẳng hạn như std::range_error
, std::overflow_error
v.v. Bạn có thể định nghĩa các lớp ngoại lệ của riêng mình giảm dần std::runtime_error
, cũng như bạn có thể xác định ngoại lệ của riêng mình các lớp giảm dần từ std::exception
.
Cũng giống như std::runtime_error
, thư viện tiêu chuẩn chứa std::logic_error
, cũng giảm dần std::exception
.
Điểm có hệ thống phân cấp này là cung cấp cho người dùng cơ hội sử dụng toàn bộ sức mạnh của cơ chế xử lý ngoại lệ C ++. Vì mệnh đề 'bắt' có thể bắt ngoại lệ đa hình, người dùng có thể viết các mệnh đề 'bắt' có thể bắt các loại ngoại lệ từ một cây con cụ thể của hệ thống phân cấp ngoại lệ. Ví dụ: catch (std::runtime_error& e)
sẽ bắt tất cả các ngoại lệ từ std::runtime_error
cây con, cho phép tất cả những người khác đi qua (và bay xa hơn lên ngăn xếp cuộc gọi).
PS Thiết kế một hệ thống phân cấp lớp ngoại lệ hữu ích (sẽ chỉ cho phép bạn nắm bắt các loại ngoại lệ mà bạn quan tâm tại mỗi điểm của mã của bạn) là một nhiệm vụ không hề nhỏ. Những gì bạn thấy trong thư viện C ++ tiêu chuẩn là một cách tiếp cận khả thi, được cung cấp cho bạn bởi các tác giả của ngôn ngữ. Như bạn thấy, họ đã quyết định chia tất cả các loại ngoại lệ thành "lỗi thời gian chạy" và "lỗi logic" và cho phép bạn tiến hành từ đó với các loại ngoại lệ của riêng bạn. Tất nhiên, có những cách khác để cấu trúc hệ thống phân cấp đó, có thể phù hợp hơn trong thiết kế của bạn.
Cập nhật: Tính di động Linux vs Windows
Như Loki Astari và unixman83 đã lưu ý trong câu trả lời và nhận xét của họ bên dưới, hàm tạo của exception
lớp không nhận bất kỳ đối số nào theo tiêu chuẩn C ++. Microsoft C ++ có một hàm tạo lấy các đối số trong exception
lớp, nhưng điều này không chuẩn. Các runtime_error
lớp học có một đối số constructor lấy ( char*
) trên cả hai nền tảng Windows và Linux. Để được xách tay, sử dụng tốt hơn runtime_error
.
(Và hãy nhớ, chỉ vì một đặc điểm kỹ thuật của dự án của bạn nói rằng mã của bạn không phải chạy trên Linux, điều đó không có nghĩa là nó không bao giờ phải chạy trên Linux.)
std::exception
. Chắc chắn, tất cả std
mọi thứ ném các lớp dẫn xuất của điều đó, nhưng hoàn toàn không có lý do để chỉ ném std::exception
các đối tượng dẫn xuất.
std::exception
nên được xem xét (lưu ý xem xét) cơ sở trừu tượng của hệ thống phân cấp ngoại lệ tiêu chuẩn. Điều này là do không có cơ chế chuyển trong một thông điệp cụ thể (để làm điều này, bạn phải lấy được và chuyên môn hóa what()
). Không có gì ngăn bạn sử dụng std :: ngoại lệ và đối với các ứng dụng đơn giản, đó có thể là tất cả những gì bạn cần.
std::runtime_error
mặt khác có các hàm tạo hợp lệ chấp nhận một chuỗi dưới dạng một thông điệp. Khi what()
được gọi là một con trỏ const char được trả về, các điểm tại một chuỗi C có cùng chuỗi như được truyền vào hàm tạo.
try
{
if (badThingHappened)
{
throw std::runtime_error("Something Bad happened here");
}
}
catch(std::exception const& e)
{
std::cout << "Exception: " << e.what() << "\n";
}
std::exception(std::string)
. Bây giờ tôi nhận ra rằng tôi phải ném std::runtime_error
nếu tôi muốn mã của mình hoạt động trong Linux (GCC).