7

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

4

3 回答 3

13

const在方法声明该方法不会改变对象之后。(也有例外,通常它用来表示“不以外部可见的方式改变对象。)

方法声明之后是throw()异常说明;它类似于throws E1, E2您在 Java 中看到的异常规范。但是,在 C++ 中,异常规范不会在编译时检查,通常被认为几乎没有用(它们现在已被弃用)。throw()是唯一有用的形式,这意味着函数声明它不能抛出异常(如果是,这是一个逻辑错误,程序将调用意外的异常处理程序,默认情况下终止程序)。

析构函数是显式声明的,因为如果未指定,编译器将生成一个调用基类析构函数的析构函数,并且编译器生成的析构函数不会使用throw()异常规范(尽管在析构函数中抛出异常从来都不是一个好主意) .

于 2012-11-06T20:37:39.023 回答
3

你目前正在处理一些 C++ 风格的东西!因此,当您想要实际拥有一个exception-object 时,您可以使用std::exception,这在 cppreference 上进行了解释。

但是由于您可以在 C++ 中抛出和捕获所有内容,您甚至可以定义自己的异常类或使用更基本的方面,例如

try  {
    throw("S0M3, M4YB3 CR1PT1C STR1NG!");  
} catch(char const* exceptStr) {  
    SomeFuncThatDecodesTheString(exceptStr); 
}

你的其他话题更多是一种个人风格或标准:

  • 一个空的析构函数~FooClass() {}只有两个显示“我真的什么都不做!”。有时它们也可能很有用,当你使用一个严格的系统来编写你的类时(例如,首先是公共空间,首先包括标准 ctor 和作为第二个函数的标准 dtor ......)来强制你(或一些其他编码器)写入现有的大括号/函数,因此不会破坏你的神圣秩序:)
  • 您可以为其他人编写throw()保险类,该类仅抛出括号中所述类型的异常。因此,一个函数void FooFunc() throw(int,char) 应该只抛出intschars。一个空throw()的只是实际上说“嘿编码器,我什么都不扔!”。您经常会在 C++ 标准库中找到它,因为您(大多数情况下)只能查看原型而不是源代码。顺便说一句,这throw(someType(s))可能是一个谎言。该函数可能会抛出任何其他类型,或者什么也不会!但是,当您使用此功能时,请不要撒谎;)

编辑:

我想补充一点,它noexcept也可以(从C++11开始)用于声明函数,而不是抛出任何异常。这个比较好理解throw()

LG ntor

于 2012-11-06T20:30:37.013 回答
2

throw()在析构函数规范中意味着析构函数不会抛出异常。C++ 中的析构函数不应该抛出异常——这就是为什么

C++ 中的析构函数不是继承的。如果您不编写自己的析构函数,那么编译器会自动为您生成析构函数。如果存在此类,则该析构函数将调用基类的析构函数。

const声明中的说明符Exception::what()意味着可以为类型的常量对象调用此方法Exceptionthrow()说明符的含义与析构函数相同。

你应该买一本关于 C++ 的书,这些都是非常基本的问题。

于 2012-11-06T20:48:59.433 回答