【问题标题】:C++ exception definitionC++ 异常定义
【发布时间】:2012-01-24 11:30:04
【问题描述】:

谁能向我解释一下 C++ 中标准异常的定义:

virtual const char* what() const throw();

const throw()最后是什么意思?

【问题讨论】:

  • 为什么这么生气?如果你每次不了解 C++ 的某些部分时都感到沮丧,那么你很快就会心脏病发作!另请注意,现在不推荐使用异常说明符,因此幸运的是,您会看到越来越少的异常说明符。

标签: c++ exception exception-handling


【解决方案1】:

这是两个独立的、不相关的东西。

const 表示成员函数不会修改任何(非mutable)成员变量;这反过来意味着它可以在const 对象上调用。例如:

class Foo {
public:
    void a() const {
        x = 5;  // Compiler error!
    }

    void b() {
        x = 5;  // This is fine
    }

private:
    int x;
};

int main() {
    Foo       p;
    const Foo q;

    p.a();   // This is fine
    p.b();   // This is fine
    q.a();   // This is fine
    q.b();   // Compiler error!
}

throw() 是一个异常说明符。它声明这个函数不会抛出异常。参见例如Should I use an exception specifier in C++? 进行讨论。

【讨论】:

    【解决方案2】:

    const 表示该函数不会改变它所嵌入的类的任何成员,throw() 是一个异常规范;该函数承诺不会抛出异常。

    请注意,自 C++11 起,异常规范 throw 已被弃用,原因如下:异常列表太难维护,而 throw(...) 无法表达,因此 throw() 基本上是唯一的规范无论如何都要使用,并且这些规范会在运行时动态检查,产生很大的开销,从而减慢您的应用程序。

    现在,您可以放心地将throw() 替换为noexcept(true),或者只是noexcept。不会检查这种方法是否真的抛出异常——这是你给编译器的保证,反之亦然。如果抛出异常,则调用std::terminate

    【讨论】:

      【解决方案3】:

      这些是不同的问题。


      关于const

      来自标准(如果太长,只阅读粗体部分):

      非静态成员函数

      [...] 非静态成员函数可以声明为 const、volatile 或 const volatile。这些 cv 限定符 影响 this 指针的类型(9.3.2)。它们还会影响成员函数的函数类型(8.3.5); 声明为 const 的成员函数是 const 成员函数,声明为 volatile 的成员函数是 一个 volatile 成员函数和一个声明为 const volatile 的成员函数是一个 const volatile 成员 功能。 [...]

      this 指针

      [...] 在 const 成员函数中,调用该函数的对象是通过 const 访问来访问的 小路;因此,const 成员函数不得修改对象及其非静态数据成员。 [...]

      存储类说明符

      [...] 类数据成员上的可变说明符使应用于包含类对象的 const 说明符无效 并允许修改可变类成员,即使对象的其余部分是 const (7.1.6.1)。

      总结:以const 限定的成员函数不允许更改任何未声明mutable 的成员。 mutable的原因是即使一个对象是const,也可以做缓存之类的机制;良好的做法是调用 const 成员函数不会改变对象的可观察行为。


      关于throw()

      异常规范 [expect.spec]

      函数声明列出了其函数可能通过使用 异常规范作为其声明符的后缀。

      更具体地说,它是一个动态异常规范,并且是一个

      如果

      [...] 函数的动态异常规范包含类型 T T 类型的处理程序将匹配 E 类型的异常 (15.3)。

      换句话说,() 中的类型是该函数可能抛出的异常。但是,通常的做法是不使用非空动态异常规范for some good reasons

      使用throw(),即一个空的异常列表,在 C++11 之前被接受的做法是注释从不抛出的函数。但是,从当前标准 C++11 开始,应该改用 noexcept

      此外,从 C++11 开始,

      [ 注意:不推荐使用动态异常规范(参见附录 D)。 ——尾注]

      所以请改用noexcept

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-08-24
        • 2010-12-09
        • 1970-01-01
        • 1970-01-01
        • 2018-01-05
        • 1970-01-01
        • 2011-01-31
        • 2016-06-11
        相关资源
        最近更新 更多