【问题标题】: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&amp; 绑定,但"coercion" 不是std::string。 catch 子句捕获 existing 对象。
  • 如果有第二个 catch 块采用 myOwnString 类型会发生什么?那岂不是模棱两可?
  • @Pubby 好吧,如果有第二个 catch 块占用不同的 Base 怎么办?
  • 这个问题仍然没有被接受的答案有什么特别的原因吗?

标签: c++ exception-handling language-design coercion subtyping


【解决方案1】:

捕获抛出的异常与将参数传递给函数完全不同。 有相似之处,但也有细微差别。

三个主要区别是:

  • 异常总是至少被复制一次(根本无法避免)
  • catch 子句按照声明的顺序进行检查(不是最合适的)
  • 它们受到较少形式的类型转换
    • 基于继承的覆盖,
    • 从有类型指针转换为无类型指针(const void* 捕获任何指针)

不允许任何其他类型的转换(例如,intdouble,或隐式 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&
}

如果您切换 BaseBase2 捕获顺序,您会注意到不同的行为。 如果LeafBase2私下继承,那么catch Base2&amp;无论放在哪里都无法访问(假设我们抛出Leaf

通常很简单:顺序很重要。

【讨论】:

    【解决方案2】:

    C++11 标准的第 15.3/3 段定义了处理程序与某个异常对象匹配的确切条件,这些条件不允许用户定义的转换: p>

    处理程序匹配E if 类型的异常对象

    ——处理程序的类型为cv Tcv T&amp;ET 是同一类型(忽略顶级cv-qualifiers), 或

    ——处理程序的类型为cv Tcv T&amp;TE 的明确公共基类,或者

    ——处理程序的类型是cv1 T* cv2E是一个指针类型,可以转换为 由一个或两个处理程序

    • 标准指针转换 (4.10) 不涉及到指向私有或受保护的指针的转换 或模棱两可的类

    • 资格转换

    ——处理程序是一个指针或指向成员类型的指针,Estd::nullptr_t

    [...]

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-14
      • 2010-12-21
      • 2012-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-09
      • 2012-05-27
      相关资源
      最近更新 更多