I have read answers to following questions ->
c++ exception : throwing std::string
My requirement is to catch exceptions and allow a mechanism to reformat the error messages and then re-throw the exceptions. So I thought of writing my exception class which will provide a method to reformat the error message at various catch points.To make reformatting easy, I'm embedding a string object in myexception_base class.
I have also referred to this article -> http://www.boost.org/community/error_handling.html which clearly says not to embed string objects in exception classes.
The article also has a quote "Peter Dimov makes an excellent argument that the proper use of a what() string is to serve as a key into a table of error message formatters." but it does not elaborate on it any further.
I have written the code as given below and my questions are -
1) If I don't embed a string object in my exception class, it will make it difficult to reformat the what messages. Please tell me How shall I approach to my requirement without embedding a string object in my exception class?
2) If I carry on with my current approach of embedding a string object and providing a method to format error message. Is my way of handling some scenarios correct ? (Issue 1 and Issue 2 in which error msg doesn't get formatted)
Issue 1 - wrong exception getting propagated to catch points ? Issue 2 - Error Message not getting formatted in some scenarios ? Issue 1 and Issue 2 are mentioned in comments in code below.
Kindly have a look at the code. I have given lot of comments in code so lines of code has increased but if I remove the comments it has very less lines of code.
#include <string>
#include <exception>
#include <iostream>
using namespace std;
class myexception_base : public exception {
private:
string error_msg;
public:
myexception_base(const char* str) : error_msg(str) {
// std::string here here can throw an exception while error_msg
//initialisation through MIL.
// myexception_base object will not be constructed
// and wrong exception will be propagated to catch point(Issue 1)
}
const char* what() const throw() {
try {
return error_msg.c_str();
} catch (...) {}
// c_str can throw.
// I can't remove throw specification from what()
// because what() in base std::exception has throw() specification
// In case c_str() throws an exception program will terminate
// So to stop abnormal termination of program c_str
// is wrapped in a try catch block to ignore std::string exception
// program will not terminate but what message is not reformatted
// in such scenario (Issue 2)
}
void append_error_msg(const char* str) {
error_msg.append(str);
// append can throw
// Again error_msg will not be formatted (Issue 2)
}
~myexception_base() throw() {
}
};
void f();
void f2();
void f() {
throw myexception_base("Error Msg1");
}
void f2() {
//Some intermediate Catch point will reformat e.what() msg
//by appending an error msg2
try {
f();
}
catch (myexception_base& e) {
e.append_error_msg(": Error Msg2");
throw;
}
}
int main () {
try {
f2();
}
catch(const exception& e) {
// Finally the exception is caught in the upper most layer
// and proper error_msg is given to user
cout<<e.what()<<"\n";
}
}