
On Wed, Jan 31, 2018 at 8:24 PM, Gavin Lambert via Boost < boost@lists.boost.org> wrote:
On 1/02/2018 15:38, Emil Dotchevski wrote:
My question still stands though. If you don't use exceptions, in C++, how
do you protect users from calling member functions on objects that have not been initialized?
I mean haven't been initialized or failed to initialize.
The usual technique to manage that is to separate no-fail construction (constructor) from fail-possible initialisation (an init() method).
This does not protect users from calling member functions on objects that have not been initialized: foo a; a.bar(); //forgot to call init, now what? or that have failed to initialize: foo a; a.init(); //failed, but nobody noticed a.bar();
Sometimes this requires weaker invariants than otherwise (eg. allowing an empty state).
I can state this more precisely: it _always_ requires no-fail partial initialization with boolean semantics (e.g. a private bool member), which member functions can use as a base to build the logic needed to detect failures to establish the "real" invariants of the object, except in the case when the type has a natural no-fail empty state, in which case yes, member functions can safely assume all is good. The common trend you'll notice is that you'll be writing code which is either automatic or unnecessary if you use excptions to report failures. Of course, people who don't use exception handling don't always write this code (not to mention, writing it is prone to errors, especially under maintenance), which is to say they have no defense against this type of logic errors.
The factory method technique also allows somewhat restoring a stronger invariant -- only the constructor and destructor need to cope with empty or otherwise uninitialised instances; other methods can be reasonably assured that no such instances escaped the factory method.
This is true only if you use exceptions to report errors from the factory. Otherwise it is most definitely NOT reasonable for member functions to assume that the object has been initialized, because nothing guarantees that an error reported by the factory wasn't ignored. Emil