`

c++ - rethrow a exception gotchas

    博客分类:
  • c++
c++ 
阅读更多

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++;

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics