What are the disadvantages of using return codes for error handling?
They don't separate exceptional logic from normal logic as well as exceptions do, they impose avoidable overhead, and they can't be used in constructors.
Return codes are a nice-guy approach; they allow the caller to do something when an error occurs but they don't require the caller to do anything or even notice that the error has occurred.
Return codes require an explicit if-check after every function call. This spreads the error-handling code into every caller of every function rather than focusing it on the relatively few routines that can actually correct the problem. Return codes therefore create a complex chain that is hard to test and maintain everyone percolates the error information backward until finally someone is capable of handling it.
Since testing for return codes requires a conditional branch in the normal execution path, it imposes runtime costs for situations that rarely occur. When functions were hundreds of lines long, checking for return codes was a small percentage of the executable code. But with OO, where member functions often have less than ten lines of code, return codes would impose an unnecessary performance penalty.
Return codes can't be returned from constructors. Fortunately constructors can (and should) throw exceptions. So using return codes with constructors can be disastrous since return codes allow errors to remain uncorrected. For example, if a hash table can't allocate memory for its hash buckets, it might set an error flag within its object, hoping the caller will check this flag and do the right thing. Thus all the object's callers are expected to check this flag (presumably another member function that would have to be added), and all the object's member functions would also have to check the flag. This adds a lot of unnecessary decision logic as well as overhead.