8.6 — Overlapping and delegating constructors

Constructors with overlapping functionality

When you instantiate a new object, the object’s constructor is called implicitly by the C++ compiler. It’s not uncommon to have a class with multiple constructors that have overlapping functionality. Consider the following class:

This class has two constructors: a default constructor, and a constructor that takes an integer. Because the “code to do A” portion of the constructor is required by both constructors, the code is duplicated in each constructor.

As you’ve (hopefully) learned by now, having duplicate code is something to be avoided as much as possible, so let’s take a look at some ways to address this.

The obvious solution doesn’t work

The obvious solution would be to have the Foo(int) constructor call the Foo() constructor to do the A portion.

However, if you try to have one constructor call another constructor in this way, it will compile and maybe cause a warning, but it will not work as you expect, and you will likely spend a long time trying to figure out why, even with a debugger. What’s happening is that Foo(); instantiates a new Foo object, which is immediately discarded, because it’s not stored in a variable.

Delegating constructors

Constructors are allowed to call other constructors. This process is called delegating constructors (or constructor chaining).

To have one constructor call another, simply call the constructor in the member initializer list. This is one case where calling another constructor directly is acceptable. Applied to our example above:

This works exactly as you’d expect. Make sure you’re calling the constructor from the member initializer list, not in the body of the constructor.

Here’s another example of using delegating constructors to reduce redundant code:

This class has 2 constructors, one of which delegates to Employee(int, const std::string &). In this way, the amount of redundant code is minimized (we only have to write one constructor body instead of two).

A few additional notes about delegating constructors. First, a constructor that delegates to another constructor is not allowed to do any member initialization itself. So your constructors can delegate or initialize, but not both.

Second, it’s possible for one constructor to delegate to another constructor, which delegates back to the first constructor. This forms an infinite loop, and will cause your program to run out of stack space and crash. You can avoid this by ensuring all of your constructors resolve to a non-delegating constructor.

Best practice

If you have multiple constructors that have the same functionality, use delegating constructors to avoid duplicate code.

Using a separate function

Relatedly, you may find yourself in the situation where you want to write a member function to re-initialize a class back to default values. Because you probably already have a constructor that does this, you may be tempted to try to call the constructor from your member function. However, trying to call a constructor directly will generally result in unexpected behavior as we have shown above. Many developers simply copy the code from the constructor into the initialization function, which would work, but lead to duplicate code. The best solution in this case is to move the code from the constructor to your new function, and have the constructor call your function to do the work of “initializing” the data:

Constructors are allowed to call non-constructor functions in the class. Just be careful that any members the non-constructor function uses have already been initialized. Although you may be tempted to copy code from the first constructor into the second constructor, having duplicate code makes your class harder to understand and more burdensome to maintain.

We say “initialize”, but it’s not real initialization. By the time the constructor calls init(), the members already exist and have been default initialized or are uninitialized. The init function can only assign values to the members. There are some types that cannot be instantiated without arguments, because they don’t have a default constructor. If any of the class members has such a type, the init function doesn’t work and the constructors have to initialize those members themselves.

It is fairly common to include an init() function that initializes member variables to their default values, and then have each constructor call that init() function before doing its parameter-specific tasks. This minimizes code duplication and allows you to explicitly call init() from wherever you like.

One small caveat: be careful when using init() functions and dynamically allocated memory. Because init() functions can be called by anyone at any time, dynamically allocated memory may or may not have already been allocated when init() is called. Be careful to handle this situation appropriately -- it can be slightly confusing, since a non-null pointer could be either dynamically allocated memory or an uninitialized pointer!

8.7 -- Destructors
8.5b -- Non-static member initialization

121 comments to 8.6 — Overlapping and delegating constructors

  • Vuong

    From what I understand, the Init() function is only used to initialize members for that class and can have potential issues with dynamic memory allocation. If so, how about make it "private" so only that class can call its own Init() function? Can you explain to me why you didn't do that? Is there any case when you would have to call Init() function from outside the class?

    • nascardriver

      The `Init` function is meant to be usable to reset an exist object

      • Petter Nybråten

        Is the use of separate Reset() functions in addition to Init() prevalent? Maybe sometimes desired default starter values are different from later reset values? Can't think of any examples, just hypothesizing...

        BTW, capitalization of Init() is norm to point out its constructor-like role?

        • nascardriver

          `Reset` and `Init` functions are rare, you'll generally get away with simply creating a new object and letting the old one die. That's clearer to the reader and probably not more expensive than resetting the object.

          I made `Init` lower case, thanks for pointing out the inconsistency!

  • fxr

    I was messing around with calling a constructor in another constructor and when I tried to do this it gives me nonsense

    Why is that it works when I put the value in as a literal but not while using the member variable. The best guess I have is it goes out of scope but why would it do this if all members of the class have access to the member variables all of the time.

    • nascardriver

      `m_color` only uses its default intializer (The value you defined at the declaration of `m_color`) if it doesn't appear in a member initializer list. But your `Ball` constructor probably initializes `m_color` in the member initializer list, so you end up with

      `m_color` is unintialized, so you get undefined behavior.

  • onionsquonion

    In the Employee example the member list is as follows

    Is there a reason the member list uses () in this example instead of {}?

    • nascardriver

      No reason, it was an old lesson. I gave it a refresh, now it's using list initialization. Thanks for pointing it out!

  • Ian

    \"Make sure you’re calling the constructor from the member initializer list, not in the body of the constructor."
    Is it because when used in the body of the constructor, we might not initialize the right member?
    Can you explain more?

  • salah

    I am confused about calling constructor from another constructor body, why would that create a temporary object and not initialize our current object ?

    • nascardriver

      The sentence in question refers to the first example in section "The obvious solution doesn’t work prior to C++11".
      Constructors create objects. Consider this

      This does what we want. It creates a `Phone` from the value 3. If we don't store the phone in a variable, the object still gets created, but then it gets discarded

      Constructors don't get any special treatment in this matter.

  • gbstrcl

    Grammatical error in the final code example

  • Samira Ferdi

    Hi, Alex and Nascardriver!

    Can we call the method using constructor through initialize list?

  • Nguyen


    I expected to see my output shown as following:
    Employee Alex created.

    But there is no output at all?  Please help.

  • Ganesh Koli

    Hi Alex, Thank you for the article.
    How this will work in inheritance ? and want to initialize super class members as well?

    Class Derive : public B

    It is not allowing the other member initialization with delegate constructor.
    I think this restriction to avoid below situation :

    Class Derive : public Base
      int size;
    public :
      Derive () : Base () {}
      Derive (int s) : Base(s), Derive() {}   // compilation error

    In above code if compilation allow it then Base class constructor could called two times ? (or something danger)

    Please correct me , if i am wrong or understood it wrongly .

  • Jeffrey Liu


    When using a non-constructor function to avoid duplicate code, would this not lead to certain issues (the same as the ones given when not using a member initializer list) because they are assigning values to the member variables, and not actually initializing them?

    Thank you!

  • Dany

    Hello. Can someone clarify which syntax should i prefer upon creation of object (i think {} because we can distinguish initialization from assignment and function call)
    and upon creation of delegating constructor (here i am really confused why both versions are available). Thanks in advance.

    • It's not just the syntax that's different, the 2 forms can do different things.
      Both are direct initialization, but brace initialization (curly braces) enforces stricter type checks and can be used to initialize lists or default-initialize.
      Use brace initialization unless you're constructing a type which has a list constructor and you want to use a non-list constructor.

  • Yaroslav

    (Optional explanation: Prior to C++11, calling a constructor explicitly from another constructor creates a temporary object, initializes the temporary object using the constructor, and then discards it, leaving your original object unchanged)

    May be it will be better to rewrite this because for me (for a noob) it was not clear at all what's going on.

    may be something like:
    prior to c++11 there was no member initializing list so we can't use it then.
    and if we will try to call the first constructor from a body of another constructor it will not call it, it will just simply create another instance of a class (in a form of anonymous object, you will learn it in ...), then it will initialize that copy/instance with the first constructor, and then discard it, leaving our original object unchanged.

  • Alireza

    Why can't I do this way:

    Causes an error:

    What does it mean ?

    • If you delegate construction to another constructor, that constructor call must be the only thing in the constructor initializer list. There can be no other initializations or constructor calls.
      Once you call a constructor, the object is considered initialized. Since an object can only be initialized once, you can't initialize anything else (eg. by calling more constructors).
      Initialize `m_color` and `m_radius` directly.

  • Tommy

    I'm failing to understand your employee example. The delegating constructor (ie. the extension, right?), it looks redundant because it's not adding any new functionality. It seems like it has less functionality actually. Have I missed something? How is the first constructor not enough?

    • Alex

      The first constructor won't let you create Employee("Alex").

      It's not a wonderful example because this could be solved trivially by flipping the order of the id and string fields, but it does at least show the mechanics.

  • NXPY

    When using a seperate function , isn't it better to make it inline to reduce time ?

Leave a Comment

Put all code inside code tags: [code]your code here[/code]