39

I am confused as to what the problems could be if a constructor was inherited from a base class. Cpp Primer Plus says,

Constructors are different from other class methods in that they create new objects, whereas other methods are invoked by existing objects. This is one reason constructors aren’t inherited. Inheritance means a derived object can use a base-class method, but, in the case of constructors, the object doesn’t exist until after the constructor has done its work.

I understand the constructor is called before object construction is completed.

How can it lead to problems if a child class inherits (By inheriting I mean the child class is able to override the parent class method etc. Not just accessing the parent class method) the parent constructor?

I understand there is no necessity of explicitly calling a constructor from within a code[not that I am aware of as yet.] except while creating objects. Even then you can do so using some mechanism to invoke the parent constuctor [ In cpp, using :: or using member initialiser list, In java using super]. In Java there is an enforcement to call it in the 1st line, I understand that is to ensure the parent object is created first and then the child object construction proceeds.

It can overrride it. But, I can't come up with situations where this can pose a problem. If the child does inherit the parent constructor what can go wrong?

So is this just to keep away from inheriting unecessary functions. Or is there more to it?

4
  • Not really up to speed with C++11, but I think there's some form of constructor inheritance in it.
    – yannis
    Commented May 13, 2013 at 8:56
  • 3
    Keep in mind that whatever you do in constructors, you have to take care in destructors.
    – Manoj R
    Commented May 13, 2013 at 9:43
  • 3
    I think you need to define what is meant by "inheriting a constructor". All the answers seem to have variations on what they think "inheriting a constructor" means. I don't think any of them match my initial interpretation. The description "in the grey box" from above "Inheritance means a derived object can use a base-class method" implies that constructors are inherited. A derived object most certainly can and does use base-class constructor methods, ALWAYS.
    – Dunk
    Commented May 13, 2013 at 19:27
  • 1
    Thanks for the clarification of inheriting a constructor, now you can get some answers.
    – Dunk
    Commented May 14, 2013 at 13:57

7 Answers 7

44

There can't be any proper inheritance of constructors in C++, because the constructor of a derived class needs to perform additional actions that a base-class constructor does not have to do and does not know about. These additional actions are the initialisation of the data members of the derived class (and in a typical implementation, also setting the vpointer to refer to the derived classes vtable).

When a class gets constructed, there are a number of things that always need to happen: The constructors of the base class (if any) and the direct members need to be called and if there are any virtual functions, the vpointer must be set correctly. If you don't provide a constructor for your class, then the compiler will create one that performs the required actions and nothing else. If you do provide a constructor, but miss out on some of the required actions (for example, the initialisation of some members), then the compiler will automatically add the missing actions to your constructor. This way, the compiler ensures that each class has at least one constructor and that each constructor fully initializes the objects it creates.

In C++11, a form of 'constructor inheritance' has been introduced where you can instruct the compiler to generate a set of constructors for you that take the same arguments as the constructors from the base class and that just forward those arguments to the base class.
Although it is officially called inheritance, it isn't truly so because there still is a derived-class specific function. Now it just gets generated by the compiler instead of explicitly written by you.

This feature works like this:

struct Base {
    Base(int a) : i(a) {}
    int i;
};

struct Derived : Base {
    Derived(int a, std::string s) : Base(a), m(s) {}

    using Base::Base; // Inherit Base's constructors.
    // Equivalent to:
    //Derived(int a) : Base(a), m() {}

    std::string m;
};

Derived now has two constructors (not counting copy/move constructors). One that takes an int and a string and one that takes just an int.

5
  • So this is assuming, the child class won't have its own constructor? and the inherited constructor obviously is unaware of the child members and initialisations to be done Commented May 13, 2013 at 10:29
  • C++ is defined in such a way that it is impossible for a class not to have its own constructor(s). That is why I don't consider 'constructor inheritance' to actually be inheritance. It is just a way to avoid writing tedious boilerplate. Commented May 13, 2013 at 11:18
  • 2
    I think the confusion stems from the fact that even an empty constructor does behind-the-scenes work. So the constructor really has two parts: The internal works and the part you write. Since they are not well separated constructors are not inherited.
    – Sarien
    Commented May 13, 2013 at 13:43
  • 1
    Please consider indicating where m() comes from, and how it would change if its type was for example int. Commented Dec 1, 2015 at 17:22
  • Is it possible to do using Base::Base implicily? It would have large consequences if I forgot that line on a derived class and I need to inherit the constructor in all derived classes
    – Post Self
    Commented Mar 12, 2017 at 18:11
7

It's not clear what you mean by "inheriting the parent constructor". You use the word overriding, which suggests you may be thinking about constructors that behave like polymorphic virtual functions. I deliberately do not use the term "virtual constructors" because that is a common name for a code pattern where you actually require an already existing instance of an object to create another one.

There is little utility to polymorphic constructors outside of the "virtual constructor" pattern, and it's difficult to come up with a concrete scenario where an actual polymorphic constructor might be used. A very contrived example that is in no way even remotely valid C++ :

struct Base {
  virtual Base(unsigned p1, unsigned p2) {...}
};

struct Derived: public Base {
  Derived(unsigned p1, unsigned p2) : Base(p1, p2) override {...}
};

int main(void) {
  unsigned p1 = 0;
  unsigned p2 = 42;
  Derived *p_d1 = new Base(p1, p2); // This might call Derived(unsigned, unsigned).
  Derived *p_d2 = nullptr;
  p_d2 = new Base(p1, p2); // This might call Derived(unsigned, unsigned) too.
}

In this case the constructor called depends on the concrete type of the variable being constructed or assigned. It is complex to detect during parsing / code generation and has no utility: you know the concrete type you are constructing and you have written a specific constructor for the derived class. The following valid C++ code does exactly the same, is slightly shorter and is more explicit in what it does:

struct Base {
  Base(unsigned p1, unsigned p2) {...}
};

struct Derived: public Base {
  Derived(unsigned p1, unsigned p2) : Base(p1, p2) {...}
};

int main(void) {
  unsigned p1 = 0;
  unsigned p2 = 42;
  Derived *p_d1 = new Derived(p1, p2); 
  Derived *p_d2 = nullptr;
  p_d2 = new Derived(p1, p2);
}


A second interpretation or perhaps additional question is - what if the Base class constructors were automatically present in all derived classes unless explicitly hidden.

If the child does inherit the parent constructor what can go wrong?

You would have to write additional code to hide a parent constructor that is incorrect to use in constructing the derived class. This can happen when the derived class specializes the base class in a way that certain parameters become irrelevant.

The typical example is rectangles and squares (Note that squares and rectangles are generally not Liskov-substitutable so it's not a very good design, but it highlights the issue).

struct Rectangle {
  Rectangle(unsigned width, unsigned height) {...}
};

struct Square : public Rectangle {
  explicit Square(unsigned side) : Rectangle(side, side) {...}
};

If Square inherited the two-value constructor of Rectangle, you could construct squares with a different height and width... That's logically wrong, so you'd want to hide that constructor.

4

Why are constructors not inherited: the answer is surprisingly simple: The constructor of the base class "builds" the base class and the constructor of the inherited class "builds" the inherited class. If the inherited class would inherit the constructer, the constructor would try to build an object of type base class and you wouldn't be able to "build" an object of type inherited class.

Which kind of defeats the purpose of inhereting a class.

4

The most obvious problem with allowing the derived class to override the base class constructor is that the developer of the derived class is now responsible for knowing how to construct its base class(es). What happens when the derived class doesn't construct the base class properly?

Also, the Liskov-Substitution principle would no longer apply as you no longer can count on your collection of base class objects to be compatible with each other, because there's no guarantee that the base class was constructed properly or compatibly with the other derived types.

It is further complicated when more than 1 level of inheritance is added. Now your derived class needs to know how to construct all the base classes up the chain.

Then what happens if you add a new base class to the top of the inheritance hierarchy? You'd have to update all of the derived class constructors.

2

Constructors are fundamentally different from other methods:

  1. They are generated if you do not write them.
  2. All base class constructors are called implicitly even if you don't do it manually
  3. You do not call them explicitly but by creating objects.

So why are they not inherited? Simple answer: Because there is always an override, either generated or written manually.

Why does every class need a constructor? That is a complicated question and I believe the answer is compiler dependent. There is such a thing as a "trivial" constructor for which the compiler does not mandate that it will be called it seems. I think that is the closest thing to what you mean by inheritance but for the three reasons stated above I think comparing constructors to normal methods is not really useful. :)

1

Every class needs a constructor, even the defaults ones.
C++ will create default constructors for you except if you create a specialized constructor.
In case that your base class uses a specialized constructor, you will need to write the specialized constructor on the derived class even if both are the same and chain them back.
C++11 allow you to avoid code duplication on constructors using using:

Class A : public B {
using B:B;
....
  1. A set of inheriting constructors is composed of

    • All non-template constructors of the base class (after omitting ellipsis parameters, if any) (since C++14)
    • For each constructor with default arguments or the ellipsis parameter, all constructor signatures that are formed by dropping the ellipsis and omitting default arguments from the ends of argument lists one by one
    • All constructor templates of the base class (after omitting ellipsis parameters, if any) (since C++14)
    • For each constructor template with default arguments or the ellipsis, all constructor signatures that are formed by dropping the ellipsis and omitting default arguments from the ends of argument lists one by one
  2. All inherited constructors that aren't the default constructor or the copy/move constructor and whose signatures do not match user-defined constructors in the derived class, are implicitly declared in the derived class. The default parameters are not inherited

0

You can use:

MyClass() : Base()

Are you asking why you have to do this?

The sub-class could have additional properties which might need to be initialised in the constructor, or it might initialise the base class variables in a different way.

How else would you create the sub-type object?

1
  • Thanks. Actually, I am trying to figure out why is a constructor not inherited in the child class, like other parent class methods. Commented May 13, 2013 at 9:49

Not the answer you're looking for? Browse other questions tagged or ask your own question.