Tôi đang mã hóa một thư viện nhỏ và tôi gặp một số rắc rối với việc thiết kế xử lý ngoại lệ. Tôi phải nói rằng tôi (vẫn) bị nhầm lẫn bởi tính năng này của ngôn ngữ C ++ và tôi đã cố gắng đọc càng nhiều càng tốt về chủ đề này để hiểu được những gì tôi sẽ phải làm để làm việc đúng với các lớp ngoại lệ.
Tôi quyết định sử dụng một system_error
kiểu tiếp cận lấy cảm hứng từ việc thực hiện STL của future_error
lớp.
Tôi có một bảng liệt kê chứa các mã lỗi:
enum class my_errc : int
{
error_x = 100,
error_z = 101,
error_y = 102
};
và một lớp ngoại lệ duy nhất (được hỗ trợ bởi một error_category
loại cấu trúc và mọi thứ khác cần thiết cho system_error
mô hình):
// error category implementation
class my_error_category_impl : public std::error_category
{
const char* name () const noexcept override
{
return "my_lib";
}
std::string message (int ec) const override
{
std::string msg;
switch (my_errc(ec))
{
case my_errc::error_x:
msg = "Failed 1.";
break;
case my_errc::error_z:
msg = "Failed 2.";
break;
case my_errc::error_y:
msg = "Failed 3.";
break;
default:
msg = "unknown.";
}
return msg;
}
std::error_condition default_error_condition (int ec) const noexcept override
{
return std::error_condition(ec, *this);
}
};
// unique instance of the error category
struct my_category
{
static const std::error_category& instance () noexcept
{
static my_error_category_impl category;
return category;
}
};
// overload for error code creation
inline std::error_code make_error_code (my_errc ec) noexcept
{
return std::error_code(static_cast<int>(ec), my_category::instance());
}
// overload for error condition creation
inline std::error_condition make_error_condition (my_errc ec) noexcept
{
return std::error_condition(static_cast<int>(ec), my_category::instance());
}
/**
* Exception type thrown by the lib.
*/
class my_error : public virtual std::runtime_error
{
public:
explicit my_error (my_errc ec) noexcept :
std::runtime_error("my_namespace ")
, internal_code(make_error_code(ec))
{ }
const char* what () const noexcept override
{
return internal_code.message().c_str();
}
std::error_code code () const noexcept
{
return internal_code;
}
private:
std::error_code internal_code;
};
// specialization for error code enumerations
// must be done in the std namespace
namespace std
{
template <>
struct is_error_code_enum<my_errc> : public true_type { };
}
Tôi chỉ có một số ít tình huống trong đó tôi đưa ra các ngoại lệ được minh họa bằng bảng liệt kê mã lỗi.
Ở trên đã không ngồi tốt với một trong những người đánh giá của tôi. Ông cho rằng tôi nên tạo ra một hệ thống phân cấp các lớp ngoại lệ với một lớp cơ sở xuất phát từ std::runtime_error
việc có mã lỗi được nhúng trong điều kiện trộn lẫn các thứ - ngoại lệ và mã lỗi - và sẽ tẻ nhạt hơn khi xử lý điểm xử lý; hệ thống phân cấp ngoại lệ cũng sẽ cho phép dễ dàng tùy chỉnh thông báo lỗi.
Một trong những lập luận của tôi là tôi muốn giữ cho nó đơn giản, rằng thư viện của tôi không cần phải đưa ra nhiều loại ngoại lệ và việc tùy chỉnh cũng dễ dàng trong trường hợp này vì nó được xử lý tự động - error_code
có error_category
liên quan đến nó dịch mã thông báo lỗi thích hợp.
Tôi phải nói rằng tôi đã không bảo vệ tốt sự lựa chọn của mình, bằng chứng là tôi vẫn còn một số hiểu lầm liên quan đến ngoại lệ C ++.
Tôi muốn biết nếu thiết kế của tôi có ý nghĩa. Điều gì sẽ là lợi thế của phương pháp khác so với phương pháp tôi đã chọn vì tôi phải thừa nhận rằng tôi cũng không thấy điều đó? Tôi có thể làm gì để cải thiện?