Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice for deferred initialization of private class members

Is there a best practice for deferred initialization of a private class member M of class C? For example:

class C {
public:
    C();

    // This works properly without m, and maybe called at any time,
    // even before startWork was called.
    someSimpleStuff();

    // Called single time, once param is known and work can be started.
    startWork(int param); 

    // Uses m. Called multiple times.
    // Guaranteed to only be called after startWork was called 
    doProcessing(); 

private:
    M m;
};

class M {
    M(int param);
};

Objects of class C can't be constructed because M doesn't have a default initializer.

If you can modify M's implementation, it's possible to add an init method to M, and make its constructor accept no arguments, which would allow constructing objects of class C.

If not, you can wrap the C's member m in std::unique_ptr, and construct it when it becomes possible.

However, both these solutions are prone to errors which would be caught in run-time. Is there some practice to make sure at compile-time that m is only used after its been initialized?

Restriction: An object of class C is handed to external code which makes use of its public interface, so C's public methods can't be split into multiple classes.

like image 418
Danra Avatar asked Feb 17 '16 14:02

Danra


1 Answers

The best practice is to never used deferred initialisation.

In your case, ditch the default constructor for C and replace it with C(int param) : m(param){}. That is, class members get initialised at the point of construction using base member initialisation.

Using deferred initialisation means your object is potentially in an undefined state, and achieving things like concurrency is harder.

like image 173
Bathsheba Avatar answered Oct 11 '22 15:10

Bathsheba