As in my prevoius example in java - common practice to rethrow exceptions, we have seen that it is always good to rethrow an new exception with the old exception as its inner exception, and it is not too bad after to just throw the exception that you have just catched (only you loose the information that the original exception has).
in C++, there is a special syntax to rethrow the exception that has been caught. which is just call "throw" without any argument, here is what you do
try {
// statements.
} catch (const exception& ex_) {
throw;
}
because of the "const reference &" syntax in the code above.
Since not all C++ classes has the necessary call stack support, we might not be able to show every clearly the major diference in terms of the call stack.
class UnsupportedException : public exception {
public:
const exception * const innerException() {
return _innerException;
}
UnsupportedException(const char* message_, const exception * const innerException_) : exception(message_), message(message_), _innerException(innerException_) {
}
UnsupportedException(const UnsupportedException& rhs) :
exception(rhs.message), message(rhs.message), _innerException(rhs._innerException)
{
}
/** one thing is missing which is called delegaing constructor */
virtual const char * what() {
return ((const UnsupportedException *) this)->what();
}
virtual const char * what() const {
char* b = new char[100];
strcpy(b, message);
if (_innerException != NULL) {
strcat(b, "cause by \n");
strcat(b, _innerException->what());
}
return b;
}
private:
const char * message;
const exception * const _innerException;
};
void generateException()
{
const UnsupportedException exc = UnsupportedException("not implemented 'generateException'", new exception("Inner exception"));
throw exc;
}
void rethrowException()
{
try {
generateException();
} catch (exception& ex_) {
throw;
}
}
void rethrowDestroyOriginalInfo() {
try {
generateException();
} catch (const exception & ex_) {
throw ex_;
}
}
void rethrowExceptionWithInnerException()
{
try {
generateException();
} catch (exception& ex_) {
throw UnsupportedException("wrapped new UnsupportedException", new UnsupportedException(dynamic_cast<const UnsupportedException &>(ex_)));
}
}
int _tmain(int argc, _TCHAR* argv[])
{
try {
rethrowException();
}
catch (const UnsupportedException & ex_) {
cout << "in catch (const exception & ex_)" << endl;
const char * what = ex_.what();
cout << what << endl;
}
cout << "============================ " << endl;
try {
rethrowDestroyOriginalInfo();
}
catch (const UnsupportedException & ex_) {
cout << "in catch (const exception & ex_)" << endl;
const char * what = ex_.what();
cout << what << endl;
}
catch (const exception & ex_) {
cout << "in const exception & ex_" << endl;
const char * what = ex_.what();
cout << what << endl;
}
cout << "============================ " << endl;
try {
rethrowExceptionWithInnerException();
}
catch (const UnsupportedException & ex_) {
cout << "in catch (const exception & ex_)" << endl;
const char * what = ex_.what();
cout << what << endl;
}
catch (const exception & ex_) {
cout << "in const exception & ex_" << endl;
const char * what = ex_.what();
cout << what << endl;
}
return 0;
}
and the output of the running the above program is like this:
in catch (const exception & ex_) not implemented 'generateException'cause by Inner exception ============================ in const exception & ex_ not implemented 'generateException' ============================ in catch (const exception & ex_) wrapped new UnsupportedExceptioncause by not implemented 'generateException'cause by Inner exception
As you can see, with the "throw;" the standard way of rethrowing excpetion, it has the correct error messages and with the "throw ex;", the real type of exception may be lost in the catch handler (you can see the second output", the third is what we try to replicate for the c# or java style of throwing exception - which to be honest, I am not sure if that is indeed what we really what we wantted to do in C++;
本文探讨了C++中异常处理的最佳实践,特别是如何重新抛出异常并保持原始异常信息的方法。通过示例展示了不同方式重新抛出异常的效果,包括使用特殊语法`throw;`保留异常堆栈信息以及手动创建新异常来包装原有异常。
436

被折叠的 条评论
为什么被折叠?



