2017-09-02 38 views
6

我是C++的初学者,因此对这个愚蠢的问题表示歉意。我在这里发布它,因为我无法在stackoverflow上找到类似的答案。在自定义异常的方法/构造函数签名中带和不带throw()的C++

我是通过在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(); 
    } 
}; 

上面的代码被老师表示。构造函数刚刚实现了在基类exception中定义的虚函数。我到了那里。

现在,当我尝试使用不同的版本进行练习时,我尝试使用自定义函数而不是重新定义虚拟(因为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"; 
} 
  • 那么为什么在what()虚函数中使用const throw()?它有什么不同?

谢谢大家。

+3

“因为C++没有严格执行接口的概念”它的确适用于纯虚函数,如果这就是你的意思。 – tkausl

+1

你省略的throw()是一个'异常说明'它告诉编译器该函数不会抛出任何异常,'what()'函数即不说它强制执行。为了清楚起见,请阅读异常规范。 –

+1

非常有趣的问题。这不是同一个问题,但我认为[这个是有帮助的](https://stackoverflow.com/questions/5230463/what-does-this-function-declaration-mean-in-c) – user1754322

回答

3

函数签名

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

可以读作:whatstd::exception虚拟成员函数返回一个指向恒定字符(阵列)和不修改该对象的成员(因此2nd const),并保证不会在其代码中抛出异常。

请注意,现在不推荐使用异常规范:相反,因为C++ 11中有noexcept说明符来声明“保证”不会抛出异常的函数。此外,由于C++ 17 throw()已成为noexcept(true)的同义词,但具有稍微不同的行为。

有关更多详细信息,请参阅noexceptthis description。它还说:“请注意,函数的noexcept规范不是编译时检查;它只是程序员通知编译器函数是否应该抛出异常的一种方法,编译器可以使用这些信息来启用对非抛出函数的某些优化[...]“。

+0

谢谢你@王 - 鹅口疮。我对“保证不抛出异常”的最后部分有疑问。如果我添加修改自定义异常类为虚拟const char * what()const throw()char * pMemory = new char [999999999999999];',它会抛出一个'std :: bad_alloc'异常,那么什么意思是提到它保证不抛出异常? – file2cable

+1

@ file2cable查看cppreference的链接我把它放在我的答案中:它有一个接近页面中间的例子:总之,将引发异常并导致调用'std :: terminate',中止程序(如果你没有指定不同的终止处理程序)。 –

4

我想表明从斯科特迈尔斯

“有效的C++” 第三版

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

这并不是说DoSomething的绝不会抛出异常的一些报价;它 说,如果doSomething引发异常,这是一个严重的错误, 和意外的功能应该被调用。†

有关意外功能的信息,请参阅您最喜爱的搜索引擎或 全面的C++文本。 (你可能有更好的运气寻找set_unexpected, 指定意想不到的功能的功能。)

并从 “有效的现代C++”

在C++ 11,无条件noexcept功能 ,保证他们不会发出异常。

如果在运行时,一个异常离开了f,违反了f的异常规范。在C++ 98异常规范中,调用堆栈被展开给f的调用者,并且在某些 动作与此处不相关之后,程序执行将终止。通过C++ 11异常规范,运行时行为稍有不同:在程序执行终止之前,堆栈只可能解压缩为 。 展开调用堆栈并将其展开可能会对代码生成产生意想不到的巨大影响。在noexcept函数中,如果异常会将 传播出函数,并且它们不必确保noexcept函数中的对象是 以与构造相反的顺序销毁,则应将异常堆栈置于不可展开状态离开功能。 具有“throw()”异常规范的函数缺乏这种优化灵活性,因为函数没有异常规范。

相关问题