创建异常时构造函数语法的差异 (c++)

differences in constructor syntax when creating exceptions (c++)

所以背景,我在 Java 编程语言方面有很强的背景。说到 C++ 语言,我完全是菜鸟。基本上我知道在 C++ 中定义构造函数有两种不同的语法,我只是不明白其中的区别。

当如下编写异常构造函数时(在类似于没有 return 类型的方法的庄园中),编译器输出 no matching function for call to 'std::runtime_error::runtime_error()' 错误:

#include <stdexcept>
using namespace std;

class DivideByZeroException : public runtime_error {
public :
    DivideByZeroException() {
        runtime_error("attempted to divide by zero.");
    }
};

但是,当构造函数修改为以下内容时,代码编译无错:

#include <stdexcept>
using namespace std;

class DivideByZeroException : public runtime_error {
public :
    DivideByZeroException() :
        runtime_error("attempted to divide by zero."){};
};

有人可以解释一下这是怎么回事吗?

在第二个示例中,冒号和左大括号之间的部分称为 initialization list。这是你初始化成员和基础 类 的地方。如果您不使用初始化列表(如您的第一个示例),则您的成员和基础 类 是默认初始化的。但是 std::runtime_error 没有默认构造函数,这就是您出错的原因。

no matching function for call to 'std::runtime_error::runtime_error()'

编译器正在尝试调用 std::runtime_error 的默认构造函数,但它不存在。所以它必须在初始化列表中初始化。至于第一个示例的构造函数中的代码行:

DivideByZeroException() {
    runtime_error("attempted to divide by zero.");   // this one
}

构造一个临时的 runtime_error 对象,它与 DivideByZeroException 对象的基本成员完全无关。该临时变量在表达式末尾被销毁。

Basically I know that there are two different syntaxes for defining constructors in C++

据此,我假设您的意思是 (1) 有和 (2) 没有初始化列表的两种方式。通常这是真的。但是,在某些情况下,就像您的情况一样,只有一种方法。也就是说,一个初始化列表。

异常没有什么特别的。 (事实上​​,与 Java 不同,C++ 看不到异常 class 和任何其他 class 之间有任何区别,如果需要,您可以抛出整数。)

构造函数只有一种正确的语法,这是第二种。第一个片段做了一些不同的事情:首先,它尝试调用不带参数的基本构造函数(即它与您编写 DivideByZeroException() : runtime_error() { runtime_error("message"); } 相同),然后它在构造函数中创建一个临时的 runtime_error 对象body 并立即丢弃它(body 中的 runtime_error 行与在 Java 中单独写入 new RuntimeException() 的效果大致相同。

错误发生是因为 runtime_error 没有不带参数的构造函数,因此调用此类构造函数的隐式尝试失败。