所以背景,我在Java编程语言方面有很强的背景。在C ++语言方面,我是一个完全的菜鸟。基本上我知道在C ++中有两种不同的语法来定义构造函数,我只是不明白它们的区别。
在编写异常构造函数时,如下所示(在类似于没有返回类型的方法的庄园中),编译器输出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."){};
};
有人可以解释一下这里发生了什么吗?
答案 0 :(得分:3)
在第二个例子中,冒号和左括号之间的部分称为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
对象的基本成员完全无关。这个临时表在表达式结束时被销毁。
基本上我知道有两种不同的语法用于定义 C ++中的构造函数
通过这个,我假设你的两种方式是(1)with和(2)没有初始化列表。通常这是真的。但是,在某些情况下,与您的一样,只有一种方法。也就是说,带有初始化列表。
答案 1 :(得分:2)
异常没有什么特别之处。 (事实上,与Java不同,C ++在异常类和任何其他类之间没有任何区别,如果你愿意,你可以抛出整数。)
构造函数只有一种正确的语法,而它是第二种。第一个片段做了一些不同的事情:首先,它试图在没有参数的情况下调用基础构造函数(即它与编写DivideByZeroException() : runtime_error() { runtime_error("message"); }
的情况相同),然后创建一个临时的runtime_error
构造函数体中的对象并立即丢弃它(正文中的runtime_error
行与在Java中单独编写new RuntimeException()
的效果大致相同。
发生错误是因为runtime_error
没有没有参数的构造函数,因此调用这样的构造函数的隐式尝试失败。