异常处理和强制
Posted
技术标签:
【中文标题】异常处理和强制【英文标题】:Exception handling and coercion 【发布时间】:2013-02-12 10:46:07 【问题描述】:try
throw Derived();
catch (Base&)
std::cout << "subtyping\n";
try
throw "lol";
catch (std::string)
std::cout << "coercion\n";
输出:
subtyping
terminate called after throwing an instance of 'char const*'
为什么异常处理对子类型很好,但对强制却不行?
【问题讨论】:
当您抛出异常以尝试匹配异常处理程序时,不会创建新对象。 因为Derived()
是 Base
并且可以被Base&
绑定,但"coercion"
不是std::string
。 catch 子句捕获 existing 对象。
如果有第二个 catch 块采用 myOwnString
类型会发生什么?那岂不是模棱两可?
@Pubby 好吧,如果有第二个 catch 块占用不同的 Base 怎么办?
这个问题仍然没有被接受的答案有什么特别的原因吗?
【参考方案1】:
捕获抛出的异常与将参数传递给函数完全不同。 有相似之处,但也有细微差别。
三个主要区别是:
异常总是至少被复制一次(根本无法避免)catch
子句按照声明的顺序进行检查(不是最合适的)
它们受到较少形式的类型转换:
基于继承的覆盖,
从有类型指针转换为无类型指针(const void*
捕获任何指针)
不允许任何其他类型的转换(例如,int
到 double
,或隐式 const char*
到 string
- 你的例子)。
关于您在评论中提出的问题 假设存在层次结构:
class Base ;
class Derived: public Base ;
class Base2 ;
class Leaf: public Derived, public Base2 ;
现在根据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&
如果您切换 Base
和 Base2
捕获顺序,您会注意到不同的行为。
如果Leaf
从Base2
私下继承,那么catch Base2&
无论放在哪里都无法访问(假设我们抛出Leaf
)
通常很简单:顺序很重要。
【讨论】:
【参考方案2】:C++11 标准的第 15.3/3 段定义了处理程序与某个异常对象匹配的确切条件,这些条件不允许用户定义的转换: p>
处理程序匹配
E
if 类型的异常对象——处理程序的类型为
cv T
或cv T&
和E
和T
是同一类型(忽略***cv
-qualifiers), 或——处理程序的类型为
cv T
或cv T&
,T
是E
的明确公共基类,或者——处理程序的类型是
cv1 T* cv2
,E
是一个指针类型,可以转换为 由一个或两个处理程序标准指针转换 (4.10) 不涉及到指向私有或受保护的指针的转换 或模棱两可的类
资格转换
——处理程序是一个指针或指向成员类型的指针,
E
是std::nullptr_t
。[...]
【讨论】:
以上是关于异常处理和强制的主要内容,如果未能解决你的问题,请参考以下文章