Tại sao tính năng này hoạt động?C++ ngoại lệ thừa kế ngoại lệ
#include <exception>
#include <iostream>
#include <stdexcept>
#include <boost/exception/all.hpp>
struct foo_error : virtual boost::exception, public std::runtime_error
{
explicit foo_error(const char* what)
: std::runtime_error(what)
{ }
explicit foo_error(const std::string& what)
: std::runtime_error(what)
{ }
};
struct bar_error : virtual boost::exception, public std::runtime_error
{
explicit bar_error(const char* what)
: std::runtime_error(what)
{ }
explicit bar_error(const std::string& what)
: std::runtime_error(what)
{ }
};
struct abc_error : virtual foo_error, virtual bar_error
{
explicit abc_error(const char* what)
: foo_error(what), bar_error(what)
{ }
explicit abc_error(const std::string& what)
: foo_error(what), bar_error(what)
{ }
};
static void abc()
{
throw abc_error("abc error");
}
int main()
{
try
{
abc();
}
catch (const std::exception& e)
{
std::cerr << e.what();
}
}
Tôi nghĩ điều này không nên lập do chuyển đổi mơ hồ abc_error
-std::exception
. Tôi đang thiếu gì? Tôi đã đưa ra sơ đồ thừa kế, và tôi thực sự không thể hiểu tại sao mã này hoạt động (các mũi tên biểu thị thừa kế ảo và các dòng biểu thị thừa kế không ảo).
std::exception std::exception
+ +
| |
| |
+ +
std::runtime_error std::runtime_error
+ +
| |
| +-->boost::exception<-+ |
+ | | +
foo_error+<-----+ +--->+bar_error
| |
| |
| |
+abc_error+
Dường như abc_error
bao gồm hai trường hợp của std::exception
nên catch
(hoặc vì vậy tôi nghĩ) không nên có thể đúc abc_error
-std::exception
. Hay phải không?
CẬP NHẬT
tôi không thể trả lời câu hỏi của riêng tôi vào lúc này, vì vậy tôi sẽ tiếp tục ở đây. Tôi đã thu hẹp sự cố xuống:
struct NonVirtualBaseBase { };
struct NonVirtualBase : NonVirtualBaseBase { };
struct VirtualBase { };
struct A : virtual VirtualBase, NonVirtualBase { };
struct B : virtual VirtualBase, NonVirtualBase { };
struct C : A, B { };
int main()
{
try
{
throw C();
}
catch (const VirtualBase& e)
{
return 1;
}
return 0;
}
Mẫu ở trên hoạt động như mong đợi và là một đoạn mã hoàn hảo. Nó bị treo nếu tôi thay thế catch (const VirtualBase& e)
bằng catch (const NonVirtualBase& e)
mà tôi nghĩ là lành mạnh và có ý nghĩa. Nhưng nó cũng hoạt động nếu tôi thay thế cùng một dòng với catch (const NonVirtualBaseBase& e)
mà với tôi có vẻ lạ và sai. Lỗi trình biên dịch?
+1 cho mã được định dạng tốt, câu hỏi hay với lời giải thích và nghệ thuật ASCII mát mẻ :) –
Trình biên dịch này là gì? – Agentlien
@Agentlien Đó là Trình biên dịch tối ưu hóa Microsoft C/C++ Phiên bản 16.00.30319.01 cho x64 –