Avoid biphasic initialization

I was doing the reading, and it seems that the general consensus is that biphasic initialization should be avoided whenever possible. I agree with what he said. But I do not find it so easy to fix.

Here is a fully compiled example, although it is heavily based on some kind of real code -

Imagine I'm building a game. The main class of the game is to build a "RenderDevice" object that performs 3D rendering. But to create it, you need some parameters to load from the configuration file. And a Window object for drawing. Both the log object and the memory pool. My code now puts all these things as members of a class where the constructor does little, and then calls the init function for each object with the appropriate parameters, for example: -

// Much simplified code to make a point Game::Game() { memoryPool_.init(10000000); // Amount of memory to allocate logger_.init("logfile.txt", memoryPool_); window_.init(2000, 1000); // Make a nice big window renderDevice_.init(window_, logger_, memoryPool_); } 

What seems to me to work quite well. But these are two phases. Each object is only partially constructed by the constructor. So I have to do something like this instead of making the code β€œclean”.

 Game::Game() : memoryPool_(1000000), logger_("logfile.txt", memoryPool_), window_(2000, 1000), renderDevice_(window_, logger_, memoryPool) { } 

Now this code looks pretty ugly to me, but also pretty fragile as the initialization order depends on the order they declare in the class, and not in the order specified here. As additional data is added to the class, it gets even worse. Objects here require only a few parameters, but if they need more data, it will quickly get out of hand.

The advantage is that every object is designed to do the job, but it looks ugly to me and seems rather fragile and error prone ...

So my question is: did I miss this? Is there a better way to do this? Should I stop worrying and just do it, or use the original code? Or is my design incorrect at a higher level in some way, and therefore the question is not useful?

Basically, what is best practice?

0
source share
2 answers

Now this code looks pretty ugly to me

For me it does not look. Maybe you're just not used to it?

rather fragile, since the initialization order depends on the order they declare in the class, and not in the order specified here

Turn on the warnings of your compiler, it should tell you about the discrepancy between these two orders. (I know the Clan has this warning, and I'm sure the GCC has it too. Not quite sure about MSVC.)

Objects here require only a few parameters, but if they need more data, it will quickly get out of hand.

I do not see how this happens when using init() .

+8
source

In my experience, init functions are used in places where errors are possible, and exceptions cannot be used / thrown. The examples you mention have errors and seem to just throw an exception because the return value has not been verified.

I believe that it is good practice to call the inits set from the init function in the game, rather than calling inits from the constructor itself.

0
source

All Articles