Advertisement Jump to content
Sign in to follow this  
blueskies9041

C++ Constructors vs. Init() Functions

This topic is 1790 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm learning game programming at AIE US - I've reviewed a lot of source code while developing my projects, I've noticed that some people use either a constructor or a plan old void (or bool) Init() function to initialize their object's member variables.

 

Is there a good reason to use one or the other? I know constructors can use initialization lists which has a few benefits that I don't fully understand yet .

 

Thanks :]

Share this post


Link to post
Share on other sites
Advertisement

The difference between them (obvious example inc!):

class MyClassCons
{
    public:
        MyClassCons()
        {
            Pointer* p = new Pointer();
        }
};

class MyClassInit
{
    public:
        MyClassInit();
        void Init()
        {
            Pointer* p = new Pointer();
        }
};

int main()
{
    MyClassConsc aClass;
    //p* already exists!

    MyClassInit bClass;
    //p* doesn't exist yet!
};

The problem with this is that sometimes p* could be a variable that depends on something ELSE to work.

Using a really bad example, say you put some OpenGL commands in your class' default constructor. Just by definining the class somewhere you'll get a runtime error because when the variable was created, right at the start of your program, the OpenGL context which is required before issuing glCommands wasn't active/didn't exist.

 

But you do could use Init(); since it would ONLY be called when you explicitly say so:

int main()
{
    MyClassInit aClass; //it's okay

    InitOpenGL();
    aClass.Init(); //okay, no runtime error
}

But you couldn't do the otherway around:

int main()
{
    InitOpenGL(); 

    MyClassCons aClass; //Still runtime error
}

Other than this situation (which I found to be sorta common), I think everything else is due preference...

Share this post


Link to post
Share on other sites


The problem with this is that sometimes p* could be a variable that depends on something ELSE to work.

 

Especially if you have static objects form "MyClass". You cant really solve that by creating the objects in the right order.

Share this post


Link to post
Share on other sites


Well, constructor's don't have any kind of return value, so, many people use an Init() type function that returns an error code of some sort.

 

The standard way would be to throw an exception from the constructor. (I dont do that either.)

Share this post


Link to post
Share on other sites
A few other remarks on this choice:
- if you define your own constructor, the 'default' constructor, destructor and assignment operator are no longer applied from the compiler, meaning you need to write them yourself to (look up "the rule of three")
- when deciding this you should also think ahead if you want objects of the class to be reinitialized/ reused later and how you'll handle this (doing a own init function might need a cleanup partner :))

Share this post


Link to post
Share on other sites

In C++, constructors are really important for RAII. Note that they are required if you wish to follow the objects-are-never-in-an-invalid-state thought process.

 

Personally, if I have to have confirmation that "initialization was a success", I'll add an IsInit or IsValid function. These cases are very, very rare in real life situations. Also... once you start using smart pointers it will be silly to explicitly Init after creating the object...

Share this post


Link to post
Share on other sites

One setup I see often is having a private constructor and then some sort of static create function that returns a pointer to the class.

Share this post


Link to post
Share on other sites

- if you define your own constructor, the 'default' constructor, destructor and assignment operator are no longer applied from the compiler, meaning you need to write them yourself to (look up "the rule of three")

 

Unless somebody made really weird changes to the language, that's simply not true. Creating your own constructor will never prevent default implementations of anything but the default constructor.

 

The "Rule of Three " doesn't say "you must implement all of them, because the compiler doesn't create them", it says "if you need one, you probably need all three". In fact, the big problem IS that the default implementations don't do everything they should in that case.

 

Obvious example:

 


class Demo()

{

    Demo() : ptr(new Thing) {}

    ~Demo() { delete ptr; }

 

    Thing* ptr;

}

 

And you probably don't want to know how often I'm seeing this kind of thing, always hand-waved away with "nah, it's never going to be copied anyway". Unless it suddenly is and "someone" (typically me) gets to spend hours debugging and tracking down the double delete introduced months ago.

 

If the compiler actually would stop creating defaults for assignment and _copy_ constructor (which is the one relevant to the Rule of Three) the code would have the decency to stop compiling. You'd also have an army of C++ coders lynching the person that came up with it.

 

 

Another common rule is that the constructor should only do minimal work to get the object in a valid state. Any heavy lifting that isn't absolutely needed would then go into an init() function.

Edited by Trienco

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!