我喜欢把一个异常的时候我的C++方法会遇到什么奇怪的和不能恢复。它是确定要扔一个 std::string 指针?

这里就是我期待着这样做:

void Foo::Bar() {
    if(!QueryPerformanceTimer(&m_baz)) {
        throw new std::string("it's the end of the world!");
    }
}

void Foo::Caller() {
    try {
        this->Bar(); // should throw
    }
    catch(std::string *caught) { // not quite sure the syntax is OK here...
        std::cout << "Got " << caught << std::endl;
    }
}
有帮助吗?

解决方案

是。 std :: exception 是基本的异常类C ++标准库。您可能希望避免将字符串用作异常类,因为它们本身可以在使用期间抛出异常。如果发生这种情况,那你将在哪里?

boost有一个很好的文档,关于异常和错误处理的良好风格。值得一读。

其他提示

一些原则:

  1. 你有一个std :: exception基类,你应该从它派生异常。这样一般的异常处理程序仍然有一些信息。

  2. 不要抛出指针而是对象,这样就可以为你处理内存。

  3. 示例:

    struct MyException : public std::exception
    {
       std::string s;
       MyException(std::string ss) : s(ss) {}
       ~MyException() throw () {} // Updated
       const char* what() const throw() { return s.c_str(); }
    };
    

    然后在您的代码中使用它:

    void Foo::Bar(){
      if(!QueryPerformanceTimer(&m_baz)){
        throw MyException("it's the end of the world!");
      }
    }
    
    void Foo::Caller(){
      try{
        this->Bar();// should throw
      }catch(MyException& caught){
        std::cout<<"Got "<<caught.what()<<std::endl;
      }
    }
    

所有这些工作:

#include <iostream>
using namespace std;

//Good, because manual memory management isn't needed and this uses
//less heap memory (or no heap memory) so this is safer if
//used in a low memory situation
void f() { throw string("foo"); }

//Valid, but avoid manual memory management if there's no reason to use it
void g() { throw new string("foo"); }

//Best.  Just a pointer to a string literal, so no allocation is needed,
//saving on cleanup, and removing a chance for an allocation to fail.
void h() { throw "foo"; }

int main() {
  try { f(); } catch (string s) { cout << s << endl; }
  try { g(); } catch (string* s) { cout << *s << endl; delete s; }
  try { h(); } catch (const char* s) { cout << s << endl; }
  return 0;
}

你应该更喜欢h到f到g。请注意,在最不优选的选项中,您需要明确释放内存。

它有效,但如果我是你,我不会这样做。完成后,您似乎没有删除该堆数据,这意味着您已经创建了内存泄漏。 C ++编译器负责确保即使在弹出堆栈时异常数据也保持活动状态,因此不要觉得您需要使用堆。

顺便说一下,抛出 std :: string 并不是最好的方法。如果你使用一个简单的包装器对象,你将会有更多的灵活性。它现在可能只是封装字符串,但是将来你可能希望包含其他信息,例如导致异常的一些数据或者行号(非常常见)。您不希望在代码库中的每个位置更改所有异常处理,因此请立即采取行动,不要丢弃原始对象。

此外,可能扔东西来自std::异常你应该扔匿名临时和捕参考:

void Foo::Bar(){
  if(!QueryPerformanceTimer(&m_baz)){
    throw std::string("it's the end of the world!");
  }
}

void Foo:Caller(){
  try{
    this->Bar();// should throw
  }catch(std::string& caught){ // not quite sure the syntax is ok here...
    std::cout<<"Got "<<caught<<std::endl;
  }
}
  • 你应该扔匿名的 临时使编译器交易 与对象的生命周期的什么 你扔-如果你扔 一些新的东西-ed断堆, 其他人需要免费的 事情。
  • 你应该赶上的引用 防止对象的切片

.

看到迈尔的"有效C++-3rd edition"的详细信息,或者访问 https://www.securecoding.cert.org/.../ERR02-A.+Throw+anonymous+temporaries+and+catch+by+reference

在C ++中抛出异常的最简单方法:

#include <iostream>
using namespace std;
void purturb(){
    throw "Cannot purturb at this time.";
}
int main() {
    try{
        purturb();
    }
    catch(const char* msg){
        cout << "We caught a message: " << msg << endl;
    }
    cout << "done";
    return 0;
}

打印:

We caught a message: Cannot purturb at this time.
done

如果捕获抛出的异常,则包含异常并且程序将继续。如果您没有捕获异常,则程序存在并打印:

此应用程序已请求Runtime以不寻常的方式终止它。请联系应用程序的支持团队以获取更多信息。

虽然这个问题是相当的旧和已经回答,我只是想增加一个注如何做到适当的例外处理 C++11:

使用 std::nested_exceptionstd::throw_with_nested

使用这些在我看来,导致清除的设计和使得不必要创建一个例外类层次。

注意,这使你能够 得到回溯上你的例外 在你的代码,而不需要一个调试器或繁琐的记录。它描述了在计算器 在这里,在这里,, ,如何写入一个适当的例外处理,这将再次引发嵌套的例外情况。

因为你可以这样做任何衍生出异常类,可以添加了很多的信息这样一种回溯!你也可以来看看我 兆瓦在。, ,其中一个回溯会看起来像这样的东西:

Library API: Exception caught in function 'api_function'
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top