在C ++中编写自定义异常

时间:2012-11-06 20:23:38

标签: c++ custom-exceptions

我来自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不应该足够吗?

3 个答案:

答案 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 ++的书,这些都是非常基本的问题。