简体   繁体   English

带有和不带throw()的方法/构造函数签名中的c ++,用于自定义异常

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

I am beginner in c++, and hence apologies for this silly question. 我是c ++的初学者,因此为这个愚蠢的问题道歉。 I am posting it here because I cannot find a similar answer on stackoverflow. 我在这里发帖是因为我在stackoverflow上找不到类似的答案。

I was progressing through exceptions in C++ and as I was doing some hands on with custom exceptions, I have this code 我正在逐步完成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();
    }
};

The above code was shown by the teacher. 上面的代码由老师展示。 The constructor just implemented a virtual function defined in the base class exception . 构造函数刚刚实现了基类exception定义的虚函数。 I got till there. 我到那儿。

Now when I was trying a different version to practice, I tried to use a custom function instead of re-defining the virtual (as c++ doesn't strictly enforce the concept of interface, please correct me if I am wrong here.) 现在,当我尝试使用不同版本进行练习时,我尝试使用自定义函数而不是重新定义虚拟(因为c ++没有严格执行接口的概念,如果我在这里错了,请纠正我。)

I wrote it as 我把它写成了

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();
    }
};

To summarise, I didn't find a difference in behaviour in both ways 总而言之,我没有发现两种方式的行为差异

public:
const char* show() {
        return "This is an error encountered\n";
}
virtual const char* what() const throw() {
    return "something bad happened";
}
  • So why was the const throw() used in the what() virtual function? 那么为什么const throw()what()虚函数中使用? What difference it makes? 它有什么不同?

Thanks to all. 谢谢大家。

I wanted to show some quotes from Scott Meyers 我想展示Scott Meyers的一些引用

"Effective C++" Third Edition “有效的C ++”第三版

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

This doesn't say that doSomething will never throw an exception; 这并不是说doSomething永远不会抛出异常; it says that if doSomething throws an exception, it's a serious error, and the unexpected function should be called. 它说如果doSomething抛出一个异常,那就是一个严重的错误,应该调用意外的函数。

For information on the unexpected function, consult your favorite search engine or comprehensive C++ text. 有关意外功能的信息,请参阅您最喜欢的搜索引擎或全面的C ++文本。 (You'll probably have better luck searching for set_unexpected, the function that specifies the unexpected function.) (您可能会更好地搜索set_unexpected,这是指定意外函数的函数。)

And from the "Effective Modern C++" 并从“有效的现代C ++”

In C++11, unconditional noexcept is for functions that guarantee they won't emit exceptions. 在C ++ 11中,无条件noexcept用于保证它们不会发出异常的函数。

If, at runtime, an exception leaves f, f's exception specification is violated. 如果在运行时,异常离开f,则违反了f的异常规范。 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. 使用C ++ 98异常规范,调用堆栈将向f的调用者展开,并且在此处不相关的某些操作之后,程序执行将终止。 With the C++11 exception specification, runtime behavior is slightly different: the stack is only possibly unwound before program execution is terminated. 使用C ++ 11异常规范,运行时行为略有不同:堆栈只能在程序执行终止之前解除。 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. 在noexcept函数中,如果异常将从函数传播出来,优化器不需要将运行时堆栈保持在不可解除的状态,也不必确保如果异常离开函数,则以构造的逆序销毁noexcept函数中的对象。 。 Functions with “throw()” exception specifications lack such optimization flexibility, as do functions with no exception specification at all. 具有“throw()”异常规范的函数缺乏这种优化灵活性,完全没有异常规范的函数也是如此。

The function signature 功能签名

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

can be read as: what is a virtual member function of std::exception which returns a pointer to a constant character (array) and which does not modify members of that object (hence the 2nd const ) and which guarantees not to throw an exception in its code. 可以理解为: whatstd::exception的虚拟成员函数,它返回一个指向常量字符(数组)的指针,并且不修改该对象的成员(因此是第二个const ),并保证不抛出异常在其代码中。

Beware that the exception-specification is nowadays deprecated: Instead, since C++11 there is the noexcept specifier to declare functions that "guarantee" not to throw exceptions. 请注意,异常规范现在已被弃用:相反,从C ++ 11开始,有noexcept说明符来声明“保证”不抛出异常的函数。 Additionally, since C++17 the throw() has become a synonym for noexcept(true) , but with a slightly different behaviour. 另外,从C ++ 17开始, throw()已成为noexcept(true)的同义词,但行为略有不同。

For more details, refer to this description of noexcept . 有关更多详细信息,请参阅noexcept 此说明

There it also says: "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 [...]". 它还说:“请注意,函数的noexcept规范不是编译时检查;它只是程序员通知编译器函数是否应该抛出异常的方法。编译器可以使用此信息来对非投掷函数启用某些优化[...]“。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM