Doing things in init functions, rather than constructors

Does anyone use “init” functions, rather than put all the object creation stuff in a Component’s constructor?

I’m finding that it’s difficult to control the order of creation of some components in a complex nested app, and some initializations are performed out of the order I’d like to achieve. One way to deal with this is to leave the constructor basically empty, then create functions such as MyComponent::initialize() that contain all the stuff you’d normally put in the constructor, and then call those in the order that you want, giving you more control over the order in which all the various components are created.

Or is this a bad idea? Bad design?

This is generally considered to be an anti-pattern. In C++, particularly modern C++ with RAII, your constructor should perform any necessary initialization. In the relatively rare cases where you do need a separate init function, you can create some sort of factory method to encapsulate the two-stage creation process.

This question comes up fairly often, so there is a lot of good discussion on StackOverflow and the like that is worth reading:

(this one is tagged Java, but the discussion applies to OO in general).

I know it’s an anti-pattern, but I often do this for Component subclasses to set their options -an init() which returns the object by ref. My reason is that the parent’s constructor needs to call addChildComponent or addAndMakeVisible for all children, and it’s clearer for me to have the children setup there than in a long initializer list. It’s not a conceptually good reason, but it makes my life simpler.

That doesn’t sound unreasonable. I like how the accepted answer in the second StackExchange link puts it:

Yes, it’s a code smell. A code smell isn’t something that necessarily always needs to get removed. It’s something that makes you take a second look.

I’ve got a similar use case where I’ve got a base class for ValueTree-backed models, where the subclasses often expose the underlying tree properties as CachedValues. Each subclass provides a method that “binds” the value members to their respective properties and needs to be called immediately after construction.

Right now I do it in each subclass constructor, and have a macro :grimacing: to generate the special member function boilerplate for subclasses that don’t do anything beyond calling the bind function.

Not totally happy with it design-wise, but it gets the job done at the moment.

1 Like

i do that in my current project. there is an interpolation base class, which inits some stuff right ahead. some interpolation types need to init more depending on additional information that couldn’t have been available yet

If you’re dealing with Components, there’s a virtual function called parentHierarchyChanged() that you can override to call things that already have parents.

As for long initializer lists bodies, the modern convention is to do as much as you can in header files:

struct MyStruct
{
    Object myObject { initArgument, otherInitArgument };
};

From a reader’s perspective, I’m totally fine with a private init() function called from different constructors, say if there are multiple constructors with different initialization logic.

But - a public init() function called from another object is to me a very serious code smell, because it means that the ‘users’ of those objects need to know about two steps of initialization, which now requires more documentation, and leaves more room for bugs.

2 Likes

I think it’s bad for shared code that is or may be worked on by a number of people, or if the codebase is really big. But at that point many other things need to be or be not done, which may imply not only more code, but also code that is more difficult to work with for someone in particular. For example, I follow JUCE formatting in the forum, but I don’t use it in my private projects -it makes too little code visible on my screen for the text size I need to be able to read it. My interfaces are not perfect either -they would need some forwarding and maybe a facade, and I don’t document everything. In this case, I can’t use in-class initializers because I forward arguments from the parent’s constructor. The choice is between initializer lists or init() methods. For shared code, I’d go with the first. For example:

  : min   { lnf.roundedLeft,  1.0,  0.5, 500, 1000 },
    rng   { lnf.roundedRight, 1.0,  0.5, 500, 1000 },
    band  { lnf.roundedLeft,  1.0,  1.0,  96,  144 },
    length{ lnf.roundedRight, 0.1, 0.05, 250,  500 }
{
    addAndMakeVisible (min);
    addAndMakeVisible (rng);
    addAndMakeVisible (band);
    addAndMakeVisible (length);

or

    addAndMakeVisible (min   .init (lnf.roundedLeft,  1.0,  0.5, 500, 1000));
    addAndMakeVisible (rng   .init (lnf.roundedRight, 1.0,  0.5, 500, 1000));
    addAndMakeVisible (band  .init (lnf.roundedLeft,  1.0,  1.0,  96,  144));
    addAndMakeVisible (length.init (lnf.roundedRight, 0.1, 0.05, 250,  500));

Also, with init() I can see what those numbers are by hovering over the method’s name, which can’t be done with initializers.

Thanks for the insights. I guess another way to handle order-dependent creation might be to create objects with a pointer and new, rather than in an initializer list or in the header.

instead of :

class MyClass
{
    Object myObject { initArgument, otherInitArgument };
};

// or:

MyClass::MyClass()
: myObject(initArgument, otherInitArgument)
{
	// myObject is already created, cannot do stuff beforehand
	// that myObject might rely on
}

Use pointers and new:

class MyClass
{
    std::unique_ptr<Object> myObject;
}

// in the constructor
MyClass::MyClass()
{
	// do whatever we want beforehand, set up stuff that myObject relies on, then:

	myObject.reset(new Object (initArgument, otherInitArgument));
}

What about using std::unique_ptr's instead of an init method?

Something like…

addAndMakeVisible(*(min = std::make_unique<MyComponent>(lnf.roundedLeft, 1.0, 0.5, 500, 1000)));

Doesn’t look as pretty but saves the need for an init function in every custom component your write and makes use of RAII.

Well, the main reason for init() was how the code looks anyway. Adding a pointer for no other reason seems worse to me. Also it’s not in every component, just the ones that need a setup. Each property could be set with a separate function -for example for sliders: look and feel, snappings, sensitivities, editable textbox, direction. None of those are necessary for construction, but all my sliders need them, and they’re set once. I just try to keep the bureaucratic code as small as possible, so it’s not a pain to find the actually important parts.

fwiw, I think order of initialization bugs are as big a code smell as multi step initialization. It suggests here’s an inverted hierarchy in the program, usually.

3 Likes