我来自Ruby和Java背景,最近开始探索C ++。
虽然我通过简单地继承异常类来创建自定义异常的初始尝试失败了,但我发现在网站上发布了以下示例:
class Exception : public exception
{
public:
Exception(string m="exception!") : msg(m) {}
~Exception() throw() {}
const char* what() const throw() { return msg.c_str(); }
private:
string msg;
};
我对C ++语义的理解目前还不是很成熟,我希望能够更好地理解这里发生的事情。
在声明const char* what() const throw()
中const throw()
部分做了什么,它是什么类型的编程结构?
此外,throw()
在析构函数规范~Exception()
中的目的和意图是什么?为什么我需要有一个析构函数规范,尽管我不需要它特别做某事?从例外继承的destructor
不应该足够吗?
答案 0 :(得分:13)
const
。 (也有例外,通常它用来表示“不会以外部可见的方式改变对象。”
方法声明后的throw()
是异常规范;它类似于您在Java中看到的throws E1, E2
异常规范。但是,在C ++中,异常规范在编译时不会被检查,并且通常被认为是无用的(现在它们已被弃用)。 throw()
是唯一有用的形式,这意味着函数声明它不能抛出异常(如果是,它是一个逻辑错误,程序将调用一个意外的异常处理程序,默认情况下终止程序)。
析构函数是显式声明的,因为如果不指定,编译器将生成一个析构函数来调用基类析构函数,编译器生成的析构函数将不会使用throw()
异常规范(尽管抛出异常的事实)在析构函数中从来都不是一个好主意。)
答案 1 :(得分:3)
您目前正在处理C ++的一些风格!
因此,当您想要实际拥有exception
- 对象时,您可以使用std::exception
,其解释为here on cppreference。
但是既然你可以在C ++中抛出并捕获所有内容,你甚至可以定义自己的异常类或使用更基本的方面,例如。
try {
throw("S0M3, M4YB3 CR1PT1C STR1NG!");
} catch(char const* exceptStr) {
SomeFuncThatDecodesTheString(exceptStr);
}
您的其他主题更像是一种个人风格或标准:
~FooClass() {}
这样的空洞析构函数只有两个显示“我什么都不做!”。有时它们也可能有用,当你使用严格的系统编写你的类时(例如首先是公共空间,首先包括标准ctor,标准dtor作为第二个函数......)以强迫你(或者一些)其他编码器)写入现有的大括号/功能,因此不会消除你的神圣秩序:) throw()
,该课程只会抛出这些类型的例外情况。因此,函数void FooFunc() throw(int,char)
应仅抛出 ints 和 chars 。空throw()
只是实际上说“嘿编码器,我什么都不扔!”。您经常会在C ++标准库中找到它,因为您(大多数时候)只能查看原型而不是源代码。 BTW throw(someType(s))
可能是谎言。函数可能抛出任何其他类型或根本没有!但是当你使用它时,不要成为骗子;)我想补充一点,noexcept
可以(因为 C ++ 11 )也可用于声明一个函数,而不是抛出任何异常。这比throw()
更容易理解。
LG ntor
答案 2 :(得分:2)
throw()
意味着析构函数不会抛出异常。 C ++中的析构函数不应抛出异常 - here is why。
C ++中的析构函数不是继承的。如果您不编写自己的析构函数,那么编译器将自动为您生成析构函数。如果存在这样的类,析构函数将调用基类的析构函数。
const
声明中的 Exception::what()
说明符表示可以为Exception
类型的常量对象调用此方法。 throw()
说明符与析构函数的含义相同。
你应该得到一本关于C ++的书,这些都是非常基本的问题。