c++ 在自定义异常的 method/constructor 签名中有和没有 throw()

c++ with and without throw() in method/constructor signature for a custom exception

我是 C++ 的初学者,因此对于这个愚蠢的问题深表歉意。我把它贴在这里是因为我在 Whosebug 上找不到类似的答案。

我正在处理 C++ 中的异常,并且在动手处理自定义异常时,我有这段代码

class MyException: public std::exception{
public:
    virtual const char* what() const throw() {
        return "something bad happened";
    }

};

// class that throws above exception

class canGoWrong {
public:
    canGoWrong(){
        throw MyException();
    }
};

上面的代码是老师展示的。构造函数只是实现了基classexception中定义的虚函数。我到那里了。

现在我在尝试不同版本的练习时,我尝试使用自定义函数而不是重新定义虚拟(因为c++没有严格执行接口的概念,如果我错了请指正在这里。)

我写成

class my_custom_shit_exception: public std::exception {
public:
    const char* show() { // I omitted the const throw() here
            return "This is an error encountered\n";
    }
};

class myclass {
public:
    myclass() {
        throw my_custom_shit_exception();
    }
};

总而言之,我没有发现两种方式的行为差异

public:
const char* show() {
        return "This is an error encountered\n";
}
virtual const char* what() const throw() {
    return "something bad happened";
}

感谢大家。

函数签名

class std::exception {
    //...
public:
    virtual const char* what() const throw();
    //...
};

可以理解为:whatstd::exception的虚成员函数,returns是指向常量字符(数组)的指针,不修改该对象的成员(因此是第二个const)并且保证不会在其代码中抛出异常。

请注意异常规范现在已被弃用:相反,自 C++11 以来,有 noexcept 说明符来声明 "guarantee" 不抛出异常的函数。此外,自 C++17 以来,throw() 已成为 noexcept(true) 的同义词,但行为略有不同。

更多详细信息,请参阅 noexceptthis description

那里还说:"Note that a noexcept specification on a function is not a compile-time check; it is merely a method for a programmer to inform the compiler whether or not a function should throw exceptions. The compiler can use this information to enable certain optimizations on non-throwing functions [...]"。

我想展示一些 Scott Meyers 的名言

"Effective C++" 第三版

int doSomething() throw(); // note empty exception spec.

This doesn’t say that doSomething will never throw an exception; it says that if doSomething throws an exception, it’s a serious error, and the unexpected function should be called. †

For information on the unexpected function, consult your favorite search engine or comprehensive C++ text. (You’ll probably have better luck searching for set_unexpected, the function that specifies the unexpected function.)

并且来自 "Effective Modern C++"

In C++11, unconditional noexcept is for functions that guarantee they won’t emit exceptions.

If, at runtime, an exception leaves f, f’s exception specification is violated. With the C++98 exception specification, the call stack is unwound to f’s caller, and, after some actions not relevant here, program execution is terminated. With the C++11 exception specification, runtime behavior is slightly different: the stack is only possibly unwound before program execution is terminated. The difference between unwinding the call stack and possibly unwinding it has a surprisingly large impact on code generation. In a noexcept function, optimizers need not keep the runtime stack in an unwindable state if an exception would propagate out of the function, nor must they ensure that objects in a noexcept function are destroyed in the inverse order of construction should an exception leave the function. Functions with “throw()” exception specifications lack such optimization flexibility, as do functions with no exception specification at all.