fre*_*low 12 c++ exception-handling language-design coercion subtyping
try
{
throw Derived();
}
catch (Base&)
{
std::cout << "subtyping\n";
}
try
{
throw "lol";
}
catch (std::string)
{
std::cout << "coercion\n";
}
Run Code Online (Sandbox Code Playgroud)
输出:
subtyping
terminate called after throwing an instance of 'char const*'
Run Code Online (Sandbox Code Playgroud)
为什么异常处理对子类型有好处,但不是强制?
eme*_*esx 18
捕获抛出异常与将参数传递给函数完全不同.有相似之处,但也有微妙的差异.
3个主要区别是:
catch 条款按照声明的顺序进行检查(不是最合适的)const void*捕获任何指针)任何其他类型的转换是不允许的(如int到double,或隐const char*于string-您的例子).
关于您在评论中的问题 假设存在层次结构:
class Base {};
class Derived: public Base {};
class Base2 {};
class Leaf: public Derived, public Base2 {};
Run Code Online (Sandbox Code Playgroud)
现在,根据catch子句的顺序,将执行适当的块.
try {
cout << "Trying ..." << endl;
throw Leaf();
} catch (Base& b) {
cout << "In Base&";
} catch (Base2& m) {
cout << "In Base2&"; //unreachable due to Base&
} catch (Derived& d) {
cout << "In Derived&"; // unreachable due to Base& and Base2&
}
Run Code Online (Sandbox Code Playgroud)
如果切换Base并Base2捕获订单,您会发现不同的行为.如果Leaf私下继承Base2,那么catch Base2&无论放在哪里都会无法到达(假设我们抛出一个Leaf)
一般来说很简单:订单很重要.
C++ 11标准的第15.3/3段定义了处理程序与某个异常对象匹配的确切条件,并且这些条件不允许用户定义的转换:
处理程序是类型为
Eif 的异常对象的匹配项-该处理程序的类型是
cv T或cv T&和E和T是相同的类型(忽略顶层cv-qualifiers),或- 处理程序是类型
cv T或cv T&,T是一个明确的公共基类E,或- 处理程序是类型的
cv1 T* cv2,E是一种指针类型,可以通过其中一个或两个转换为处理程序的类型
标准指针转换(4.10),不涉及到指向私有或受保护或模糊类的指针的转换
资格转换
-该处理程序是一个指针或指针构件类型和
E是std::nullptr_t.[...]