We know that the exception class has two derived classes: logic_error and runtime_error.
logic_error has four derived classes: domain_error, invalid_argument, length_error and out_of_range.
runtime_error has three derived classes: range_error, overflow_error and underflow_error.
While some of them are self-explanatory, like overflow_error and underflow_error, some are not that clear, especially range_error, both MSDN and cplusplus just say “to report a range error”, which is close to saying nothing, how it is different out_of_range and domain_error???
Another question is when I throw an exception, which one should I choose? For example, In reverse_string(char* s), which exception to throw when s is NULL? In float calc_ellipse_area(float a, float b), which to throw when a or b is <=0? Which to throw when a == b (strictly speaking, circle is not an ellipse!)?
Finally, practically speaking, does it really matter if I throw an exception which is not correctly categorized?
For both of these, use
std::invalid_argument.Or you can define your own exception called
null_argumentderiving fromstd::logic_error(or fromstd::invalid_argument), and use it forNULLargument.The point is that if none of the standard exception class applies to your situation, or you want more specific exception, then define one deriving from existing classes.
For example, if you want to throw exception when you encounter an invalid index, then either you can use
std::out_of_rangeor define more specific class calledindex_out_of_rangederiving fromstd::out_of_range.Yes, it does matter. For example, it increases readability of your code. If you throw
std::logic_errorwhen an invalid index is encountered, then well, it doesn’t add much to the readability, but instead of that if you throwstd::out_of_range, then it greatly increases the readability. And if you throwindex_out_of_range, it increases even more, as it’s more specific.