【问题标题】:Why does the compiler look for a default constructor for my exception class?为什么编译器要为我的异常类寻找默认构造函数?
【发布时间】:2015-09-05 13:04:00
【问题描述】:

我为我的库定义了一个小的异常层次结构。它继承自std::runtime_error,像这样:

class library_exception : public std::runtime_error {
    using std::runtime_error::runtime_error;
};

class specific_exception : public library_exception {
    int guilty_object_id;

    specific_exception(int guilty_object_id_)
        : guilty_object_id(guilty_object_id_) {}
};

编译器说:

错误:调用 'library_exception' 的隐式删除的默认构造函数

并指向 specific_exception 构造函数。

为什么要在这里调用默认构造函数?

【问题讨论】:

    标签: c++ default-constructor


    【解决方案1】:

    library_exception 继承自 std::runtime_error。后者没有默认构造函数,这意味着前者不可默认构造。

    同样,specific_exception 不是默认可构造的,因为它的基类不是。你需要一个默认的基类构造函数,因为基类是隐式初始化的:

    specific_exception(int guilty_object_id_)
        : guilty_object_id(guilty_object_id_) {}
    

    要解决此问题,请调用适当的基类构造函数:

    specific_exception(int guilty_object_id_)
        : library_exception("hello, world!"),
          guilty_object_id(guilty_object_id_) {}
    

    【讨论】:

      【解决方案2】:

      撤回: 这个答案被误导了。 (所指的构造函数实际上是用于类成员的默认初始化,而不是类本身。)

      std::runtime_error 有一个字符串字段,如下所示:

      class runtime_error {
          std::string msg;
      
      public:
          runtime_error(std::string msg) : msg(msg) { }
      };
      

      msg 未由您的构造函数初始化(并且不能初始化,因为该字段是私有的)。因此调用默认构造函数。更准确地说,

      默认初始化 […] 是在没有初始化器的情况下构造变量时执行的初始化。

      默认初始化在三种情况下执行:

      3) 当构造函数初始值设定项列表中未提及基类或非静态数据成员并且调用该构造函数时。

      默认初始化的效果是:

      如果 T 是一个 [...] 类类型,则考虑构造函数并对其进行重载决策以针对空参数列表。调用选择的构造函数(默认构造函数之一)为新对象提供初始值。

      (cppreference.com)

      但是,我仍然不明白为什么它抱怨基类 library_exception 而不是 specific_exception。在 specific_exception 中添加无参数构造函数并没有什么不同。

      【讨论】:

      • 当基类的默认构造函数之一被删除时,默认构造函数不是被删除了吗?所以library_exception 有一个已删除的默认构造函数。注意:这里不能引用标准
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-12-06
      • 1970-01-01
      • 2014-07-07
      • 2019-05-17
      • 2017-02-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多