为什么这有效?C++异常继承模糊
#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();
}
}
我想这应该不是由于暧昧转换编译从abc_error
到std::exception
。我错过了什么?我想出了继承关系图,但我无法弄清楚为什么这段代码能够工作(箭头表示虚拟继承,而这些行表示非虚拟继承)。
std::exception std::exception
+ +
| |
| |
+ +
std::runtime_error std::runtime_error
+ +
| |
| +-->boost::exception<-+ |
+ | | +
foo_error+<-----+ +--->+bar_error
| |
| |
| |
+abc_error+
它看起来像abc_error
包括std::exception
两个实例所以catch
(或因此我认为)应该不能投abc_error
到std::exception
。还是应该?
UPDATE
我不能回答,此刻我自己的问题,所以我要在这里继续。我已经将问题缩小到:
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;
}
上面的示例按预期方式工作,并且是完美的一段代码。如果我将catch (const VirtualBase& e)
替换为catch (const NonVirtualBase& e)
,我认为它是理智的并且合理。 但它也适用,如果我用catch (const NonVirtualBaseBase& e)
替换同一行,这对我来说似乎是奇怪和错误的。一个编译器错误?
对于格式良好的代码+1,很好的问题与解释和酷的ASCII艺术:) –
这是哪个编译器? – Agentlien
@Agentlien这是 Microsoft(R)C/C++优化编译器版本16.00.30319.01 x64 –