Take C++ constructors for example, we know they don't return values. Why did Bjarne Stroustrup in the beginning decide not to allow constructor returning 'false' to indicate it fails, so that the run time system can destruct its constructed members just like throwing an exception? What are the concerns that make OO language designers decide not to do so? The "new" operator can therefore return "nullptr" if it see constructor returns false. For static objects (in .data/.bss area or on .stack) the compiler generated construction code can still detect and signal, abort or exit accordingly.
Consider the following two coding paradigms, using dynamic allocation as an example:
objp = new object; // constructor returns 'false', 'new' returns 'nullptr'.
if (objp != nullptr) {
do_something(objp);
} else {
error_handling();
}
compare to:
try {
objp = new object; // object throw exception when construction failed
do_something(objp);
} catch (const typedException &e) {
error_handling();
}
If we need to encode the reason of construction failure, the latter using exception is of course more helpful as we can't use 'objp' to pass any information once construction failed. But if the reason is simple (say 'out of memory'), or when skipping error handling does no harm (do_something() might just do decorating), do we really need to involve exception handling in such simple cases? How about allowing both paradigms exist in C++?
(Another example is, for small embedded C++ compilers if they don't support exceptions, they can still support "construction fail" handling in this way.)
Well, maybe my comparison is misleading, I am not against structural exception handling, on the contrary, I LOVE exceptions especially for big systems. But when it comes to small embedded systems where both code and data space are scarce, I think twice.
The exception handling frames are things similar to setjmp() and longjmp() which are quite expensive in both execution time and memory use; while the (objp==nullptr) comparison takes only a comparison and a jump. Not to mention some of the compilers don't even support exception handling. In those cases, construction fail can only be dealt with other methods. That reminds me in the old days Turbo Pascal 5.5 OOP can call "Fail" on construction fail, and the newly allocated object will be null.
What about other languages? Does all OOP languages use exception on construction fail cases?
Actually, at the time I learnt C++ there is no exception handling available at all (Turbo C++ 3.0/Borland C++ 3.1). Before that I learnt Turbo Pascal 5.5 which supported "Fail" on dynamic construction fail. But when I move to C++ at that time this make me a bit upset since there is no way to test construction fail without defining an Init() function that actually do the inits. Since then I wondered, why can't constructors return values?
Now I think maybe returning a value from constructor will make the language "inconsistent". If we return a value from a constructor and the runtime system test it, this kind of behavior is a lot different from a normal function call since our code can test it. Maybe this kind of inconsistency is not a good idea when designing a programming language? What do you think?
In the early days of C++ there was no exception handling, yet Bjarne Stroustrup still didn't let constructors to return error conditions. Same did the other OO languages at that time (correct me if I am wrong). Therefore, using exception handling was not their original intention to take care of constructor fails. Then why? I think I found the answer, please refer to my own answer here. Thanks.
new
? For those objects, constructors also get called, but you won't have any pointer to them that could be tested._exit()
, why not do that generally? Then you don't need return values.