This question is similar to c++ Exception Class Design and follows:
I want to design exception class hierarchy for my application and here are the design points I used:
Exception should be derived from standard exception classes (those are
std::exception
,std::logic_error
andstd::runtime_error
).Exception class should be able to take error description (i.e. what is called
what
) and position where it occurred (const std::string &file, int line
)Exception should not throw any exception during construction or from any other member.
Given this I have:
#define throw_line(TException, what) throw TException((what), __FILE__, __LINE__)
class AnException : public std::exception {
public:
AnException(const std::string &what, const std::string &file, int line) noexcept {
try {
what_ = what;
file_ = file;
line_ = line;
} catch (std::exception &e) {
was_exception_ = true;
}
}
virtual ~AnException() noexcept {}
virtual const char *what() const noexcept override {
if (was_exception_) {
return "Exception occurred while construct this exception. No further information is available."
} else {
try {
std::string message = what_ + " at " + file_ + ":" + std::to_string(line);
return message.c_str();
} catch (std::exception &e) {
return "Exception occurred while construct this exception. No further information is available."
}
}
}
};
class ParticularException : public AnException {
...
}
As you can see, it appears to be somewhat complex to construct such class, because we definitely should not have exceptions in constructor (otherwise std::terminate()
will be called) or in what()
member.
The question: is this example of a good design or I should remove some restrictions (like, having file/line information) to simplify it? Is there a better way?
I'm free to use C++11/C++14, but trying to keep off C++17 since it is not yet finished and compilers may not fully implement it.
Note: I want this code to be cross-platform.
Thanks in advance.
Edit 1: The follow up question: how can I retire file/line information, but keep that in logs? May be printing stacktrace is a better solution than what I have now? I mean leave exception class which just holds an error message (what
) and call something like print_backtrace
on upper level of exception handling chain.