c ++exception:抛出std :: string
我想抛出一个exception,当我的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 ++标准库中的基本exception类。 您可能希望避免使用string作为exception类,因为它们本身在使用过程中可能会引发exception。 如果发生这种情况,那么你会在哪里?
boost有很好的例外和error handling风格的文档 。 这是值得一读的。
一些原则:
-
你有一个std ::exception的基类,你应该从你的exception派生。 那样一般的exception处理程序还是有一些信息的。
-
不要抛出指针而是抛弃对象,这样内存就是为你处理的。
例:
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。 请注意,在最不可取的选项中,您需要明确释放内存。
它有效,但如果我是你,我不会这样做。 您完成后似乎并没有删除堆数据,这意味着您已经创build了内存泄漏。 C ++编译器负责确保exception数据在堆栈popup时保持活动状态,因此不要觉得需要使用堆。
顺便说一句,抛出一个std::string
不是最好的方法开始。 如果你使用一个简单的包装器对象,你将拥有更多的灵活性。 它现在可能只是封装一个string
,但也许将来你会想要包含其他信息,比如一些导致exception的数据或者一个行号(很常见)。 你不想在你的代码库中的每一个地方改变你所有的exception处理,所以现在就走高路,不要扔原始对象。
除了可能抛出从std :: exception派生的东西,你应该抛出匿名临时对象并引用:
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; } }
- 你应该抛出匿名的临时对象,这样编译器就会处理你抛出的任何对象的生命周期 – 如果你扔掉堆中的新东西,别人就需要释放这个东西。
- 你应该捕获引用来防止对象切片
。
有关详细信息,请参阅Meyer的“Effective C ++ – 第3版”或访问https://www.securecoding.cert.org/…/ERR02-A.+Throw+anonymous+temporaries+and+catch+by+reference
在C ++中抛出一个exception的最简单的方法是:
#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
如果您捕获抛出的exception,则包含该exception,程序将继续。 如果你没有发现exception,那么程序就会存在并打印出来:
This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information.