C++11: delegating constructors

Too many initializers/constructors

It’s fairly common to write classes with multiple constructors, but they tend to get messy very soon. One of the biggest problems is initialization of the member variables. You, as programmer, need to ensure that member variables are initialized correctly in each constructor. Ensuring this consistency is quite tedious, boring and very easy to get wrong.

For example consider the class Sample:

class Sample
{
public:
    //
    //
    Sample() : r(0), i(0)
    {

    }
    //
    //
    Sample(double real) : r(real), i(0)
    {

    }
    //
    //
    Sample(double real, double img) : r(real), i(img)
    {

    }
    //
    //
    Sample(double data[2]) : r(data[0]), i(data[1])
    {

    }
    //
    //
    Sample(const Sample&) = default;
    Sample& operator=(const Sample&) = default;
    ~Sample() = default;
    //
private:
    double r;
    double i;
};

Sample class has 4 constructors each initializing member variables r and i. It’s quite easy to forget to initialize these. Also the initializer code is also fairly repetitive, following the DRY (Don’t Repeat Yourself) principle it would be nice to abstract it out into a initializer method and then call this inside each constructor:

class Sample
{
private:
    void Init(double real, double img)
    {
        this->r = real;
        this->i = img;
    }
public:
    //
    //
    Sample()
    {
        Init(0,0);
    }
    //
    //
    Sample(double real)
    {
        Init(real,0);
    }
    //
    //
    ...
    //
    //
};

This works and has been used by many C++ developers over decades however it gives up the benefits of initializing members in initializer list of constructor.

delegating constructors

In previous code sample the concise way of initializing objects of a class is to use a init method or to delegate the initialization of the member variables to a method but losing out on the initializer list benefits. This pattern is so useful that various new languages support this delegating construction out of box (C# has similar concept named Constructor Chaining). C++11 also voted on similar proposal of delegating constructors. With delegating constructors above code will look like:


class Sample
{
private:
    //
    // delegated constructor
    // it should cover the most general initialization
    // case and all other constructors will then call
    // this one to initialize the object
    //
    Sample(double real, double img) : r(real), i(img)
    {
    }
public:
    //
    //
    Sample() : Sample(0.0)
    {
    }
    //
    //
    Sample(double real) : Sample(real,0)
    {
    }
    //
    //
    Sample(double data[2]): Sample(data[0], data[1])
    {
    }
    //
    //
    Sample(const Sample&) = default;
    Sample& operator=(const Sample&) = default;
    ~Sample() = default;
    //
private:
    double r;
    double i;
};

Constructor defined at Line 10 is the delegated constructor. And it is being delegated the task of constructing object by various constructors at line: 16, 21 and 26.

Default Constructor at Line 16 delegates construction to Constructor with one parameter, Line 21, which then delegates the construction to the private constructor with two parameters at Line 10.

Few things to note about delegating constructors (please refer the paper N1986 for details):

  1. you cannot initialize any member variable along with delegating constructor
  2. delegating constructor can delegate to other constructor as well, however it is developer’s responsibility to ensure there are no cycles in delegation
  3. behaviour while failure to construct object will remain unchanged, as we are initializing any member variable only once (pt 1)

Summary

Concept of delegating constructor is very simple to understand and use. This feature is mostly syntactic sugar with some validation, but a big win when it comes to usability and writing cleaner code with C++ language.

Sharing Options:

2 thoughts on “C++11: delegating constructors

Leave a Reply

Your email address will not be published. Required fields are marked *

* Copy This Password *

* Type Or Paste Password Here *