C++ Exceptions; int or std::exception?
I would throw an exception based on std::exception
.
throw std::runtime_error("unexpected end of stream")
I find this easier to catch
, log, et cetera. It also allows the removal of a comment and a magic number from the code.
This message can then be sent to the end-user to give them a hope of fixing the problem.
Users and library consumers can't read the comments in code, and they are unlikely to know what '-2' means.
Exception are for exceptional behaviour. They're the last thing that you should worry about optimizing!
Donald Knuth said:
We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil
Also, an object as exception may carry information about the error.
For example, you have an exception that means that a file cannot be read. If you throw an object exception, the object may carry the file name, which you cannot have with ints.
If the exception origin is unknown (deep in your stack) and no one catches it, it will be easier to debug the program if the exception is an object with proper information.
My question is, is this method OK?
Think about the readability. Wouldn't
throw CUnexpectedEndOfStream();
be more readable than
throw -2
?
And in a lot of cases wouldn't seeing an instance of CUnexpectedEndOfStream thrown in the debugger mean TONS more than -2. That's not to mention that CUnexpectedEndOfStream could store gobs of useful information about the problem such as say the file that couldn't be read and maybe more info on the nature of the problem.
Or should I throw a exception derived from std::exception?
Inheriting from std::exception
may be helpful if that's how you choose to organize your other exceptions. It a convenient base class that client code can use. Also depending on the exception you may want to use std::runtime_error.
Is throwing int exceptions bad practice? (all throw int values are documented in doxygen comments)
Who said it was bad practice? Throwing exceptions is a great way to handle exceptional situations. Most of the exceptions I throw are because of something that could have been prevented by the client code doing what it was supposed to-- the user of my code violated the contract. But many other exceptional non-normal cases also exist like OS errors, disks filling up, etc. All the things that aren't part of your programs normal flow. More importantly, since they're not part of your program's normal flow, you don't need to worry about performance.
As an example, I once used exceptions to trigger that a certain message parsing failure occurred. However, I found that these parsing errors occurred frequently to the point where I started handling exceptions and fixing the problem input and reparsing. After a while, I realized that a more readable solution would be to fix the problem directly in the parsing code and stop treating it like an exceptional case. All the code that made parsing decisions was put back in one place and I wasn't throwing exceptions like a drunken sailor throws out curse words.