869

What are the C++ rules for calling the base class constructor from a derived class?

For example, I know in Java, you must do it as the first line of the subclass constructor (and if you don't, an implicit call to a no-arg super constructor is assumed - giving you a compile error if that's missing).

3
  • 21
    Just nitpicking: There is no "super class" in C++, in fact, the standard does not mention it at all. This wording stems from Java (most probably). Use "base class" in C++. I guess that super implies a single parent, while C++ allows for multiple inheritance.
    – andreee
    Commented Jun 11, 2018 at 12:44
  • @andreee I red that a super class is also called base class and also f.e. in the qt toolkit parent class - in that order a sub class is also called child class Maybe that helps to combat some potential confusion in terminology
    – Ingo Mi
    Commented Jun 15, 2020 at 14:31
  • @IngoMi, it's just terminology of other languages, Java and I think, Python. Those languages have exclusive relationship between classes while C++ allows quite complex "families". Commented Oct 16, 2022 at 23:39

10 Answers 10

1165

Base class constructors are automatically called for you if they have no argument. If you want to call a superclass constructor with an argument, you must use the subclass's constructor initialization list. Unlike Java, C++ supports multiple inheritance (for better or worse), so the base class must be referred to by name, rather than "super()".

class SuperClass
{
    public:

        SuperClass(int foo)
        {
            // do something with foo
        }
};

class SubClass : public SuperClass
{
    public:

        SubClass(int foo, int bar)
        : SuperClass(foo)    // Call the superclass constructor in the subclass' initialization list.
        {
            // do something with bar
        }
};

More info on the constructor's initialization list here and here.

8
  • 57
    I removed 'explicit' from the SuperClass constructor. Despite being a best practice for single-argument constructors, it wasn't germane to the discussion at hand. For more info on the explicit key word, see: weblogs.asp.net/kennykerr/archive/2004/08/31/…
    – luke
    Commented Sep 24, 2008 at 12:38
  • 1
    the colon : operator you used to invoke superclass constructor before instantiating child class constructor, I suppose this is also true for methods?
    – ha9u63a7
    Commented Oct 31, 2014 at 9:33
  • 3
    @hagubear, only valid for constructors, AFAIK
    – luke
    Commented Oct 31, 2014 at 12:24
  • When you instantiate a SubClass object by, say, SubClass anObject(1,2), does 1 then get passed to SuperClass(foo) (becomes the argument to paramater foo)? I have been searching through docs high and low, but none definitively state that the arguments to the SubClass constructor can be passed as arguments to the SuperClass constructor. Commented Nov 24, 2014 at 1:49
  • 2
    @Gnuey, notice the : SuperClass(foo) portion. foo is explicitly being passed to the super class's constructor.
    – luke
    Commented Nov 24, 2014 at 2:27
289

In C++, the no-argument constructors for all superclasses and member variables are called for you, before entering your constructor. If you want to pass them arguments, there is a separate syntax for this called "constructor chaining", which looks like this:

class Sub : public Base
{
  Sub(int x, int y)
  : Base(x), member(y)
  {
  }
  Type member;
};

If anything run at this point throws, the bases/members which had previously completed construction have their destructors called and the exception is rethrown to to the caller. If you want to catch exceptions during chaining, you must use a function try block:

class Sub : public Base
{
  Sub(int x, int y)
  try : Base(x), member(y)
  {
    // function body goes here
  } catch(const ExceptionType &e) {
    throw kaboom();
  }
  Type member;
};

In this form, note that the try block is the body of the function, rather than being inside the body of the function; this allows it to catch exceptions thrown by implicit or explicit member and base class initializations, as well as during the body of the function. However, if a function catch block does not throw a different exception, the runtime will rethrow the original error; exceptions during initialization cannot be ignored.

5
  • 1
    I'm not sure I understand the syntax of your second example... Is the try/catch construct a replacement for the constructor body?
    – levik
    Commented Sep 23, 2008 at 13:47
  • 2
    Yes. I've reworded the section, and fixed a mistake (the try keyword goes before the initialization list). I should have looked it up instead of writing from memory, it's not something that gets used often :-)
    – puetzk
    Commented Sep 23, 2008 at 15:55
  • 133
    Thanks for including the try/catch syntax for the initializers. I've been using C++ for 10 years, and this is the first time I've ever seen that.
    – jakar
    Commented Jun 8, 2012 at 17:23
  • 26
    I got to admit, been using C++ a long time, and that is the first time I have seen that try/catcn on the constructor list.
    – Cameron
    Commented Nov 21, 2013 at 1:29
  • I might say the function body "goes in" the try block - this way any body following the initializers will will have it's exceptions caught as well.
    – peterk
    Commented Jan 16, 2019 at 15:28
64

In C++ there is a concept of constructor's initialization list, which is where you can and should call the base class' constructor and where you should also initialize the data members. The initialization list comes after the constructor signature following a colon, and before the body of the constructor. Let's say we have a class A:


class A : public B
{
public:
  A(int a, int b, int c);
private:
  int b_, c_;
};

Then, assuming B has a constructor which takes an int, A's constructor may look like this:


A::A(int a, int b, int c) 
  : B(a), b_(b), c_(c) // initialization list
{
  // do something
}

As you can see, the constructor of the base class is called in the initialization list. Initializing the data members in the initialization list, by the way, is preferable to assigning the values for b_, and c_ inside the body of the constructor, because you are saving the extra cost of assignment.

Keep in mind, that data members are always initialized in the order in which they are declared in the class definition, regardless of their order in the initialization list. To avoid strange bugs, which may arise if your data members depend on each other, you should always make sure that the order of the members is the same in the initialization list and the class definition. For the same reason the base class constructor must be the first item in the initialization list. If you omit it altogether, then the default constructor for the base class will be called automatically. In that case, if the base class does not have a default constructor, you will get a compiler error.

4
  • 1
    Wait a second... You say initializers save on the cost of assignments. But don't the same assignments take place inside them if called?
    – levik
    Commented Sep 23, 2008 at 13:39
  • 6
    Nope. Init and assignment are different things. When a constructor is called, it will try to initialize every data member with whatever it thinks is the default value. In the init list you get to supply default values. So you incur initialization cost in either case.
    – Dima
    Commented Sep 23, 2008 at 13:44
  • 1
    And if you use assignment inside the body, then you incur the initialization cost anyway, and then the cost of assignment on top of that.
    – Dima
    Commented Sep 23, 2008 at 13:44
  • 3
    This answer was helpful because it showed the syntax variant where one has a header and a source file, and one does not want the initialization list in the header. Very helpful thank you.
    – Benjamin
    Commented Nov 11, 2014 at 17:17
38

Everybody mentioned a constructor call through an initialization list, but nobody said that a parent class's constructor can be called explicitly from the derived member's constructor's body. See the question Calling a constructor of the base class from a subclass' constructor body, for example. The point is that if you use an explicit call to a parent class or super class constructor in the body of a derived class, this is actually just creating an instance of the parent class and it is not invoking the parent class constructor on the derived object. The only way to invoke a parent class or super class constructor on a derived class' object is through the initialization list and not in the derived class constructor body. So maybe it should not be called a "superclass constructor call". I put this answer here because somebody might get confused (as I did).

4
  • 17
    This answer is somewhat confusing even though I have read over it a couple of times and took a look at the linked to question. I think that what it is saying is that if you use an explicit call to a parent class or super class constructor in the body of a derived class, this is actually just creating an instance of the parent class and it is not invoking the parent class constructor on the derived object. The only way to invoke a parent class or super class constructor on a derived class' object is through the initialization list and not in the derived class constructor body. Commented Apr 19, 2014 at 13:22
  • 1
    @Richard Chambers It maybe confusing since English is not my first language, but you described precisely what I tried to say. Commented Apr 19, 2014 at 23:56
  • "a parent class's constructor can be called explicitly from the derived member's constructor's body" that's patently false for the instance in question, unless you're referring to placement new, and even then it's wrong because you'd have to destruct the instance first. E.g. MyClass::MyClass() { new (this) BaseClass; /* UB, totally wrong */ } - this is the C++ syntax for explicitly invoking a constructor. That's how a "constructor call" looks. So the fact that this absurdly wrong answer is upvoted is a total mystery to me. Commented Nov 25, 2020 at 16:27
  • I consider most answers to that question you link to to be junk, or sidestepping the issue. I wrote the answer that was missing that whole time it seems. I'm not surprised that this anyone could be confused tried to understand anything from your link... I'd have been confused as well. It's easy stuff but people write about it as if it was some magic. Blind leading the blind. Explicit constructor "call" is done with placement new syntax! MyClass() is not any sort of a "call"! It has the same meaning as e.g. int(), and it creates a value! Commented Nov 25, 2020 at 17:03
24

If you have a constructor without arguments it will be called before the derived class constructor gets executed.

If you want to call a base-constructor with arguments you have to explicitly write that in the derived constructor like this:

class base
{
  public:
  base (int arg)
  {
  }
};

class derived : public base
{
  public:
  derived () : base (number)
  {
  }
};

You cannot construct a derived class without calling the parents constructor in C++. That either happens automatically if it's a non-arg C'tor, it happens if you call the derived constructor directly as shown above or your code won't compile.

22

The only way to pass values to a parent constructor is through an initialization list. The initilization list is implemented with a : and then a list of classes and the values to be passed to that classes constructor.

Class2::Class2(string id) : Class1(id) {
....
}

Also remember that if you have a constructor that takes no parameters on the parent class, it will be called automatically prior to the child constructor executing.

0
13

If you have default parameters in your base constructor the base class will be called automatically.

using namespace std;

class Base
{
    public:
    Base(int a=1) : _a(a) {}

    protected:
    int _a;
};

class Derived : public Base
{
  public:
  Derived() {}

  void printit() { cout << _a << endl; }
};

int main()
{
   Derived d;
   d.printit();
   return 0;
}

Output is: 1

1
  • This is just because that particular declaration creates an implicit Base(), which has the same body as Base(int) but plus an implicit initialiser for : _a{1}. It's Base() that always gets called if no specific base constructor is chained in the init-list. And, as mentioned elsewhere, C++11's delegating constructors and brace-or-equal initialisation make default arguments rather less necessary (when they were already code-smell-esque in a lot of examples). Commented Feb 10, 2016 at 23:21
11
CDerived::CDerived()
: CBase(...), iCount(0)  //this is the initialisation list. You can initialise member variables here too. (e.g. iCount := 0)
    {
    //construct body
    }
8

Nobody mentioned the sequence of constructor calls when a class derives from multiple classes. The sequence is as mentioned while deriving the classes.

2
  • 2
    If nobody talked about it, where was it mentioned?
    – user207421
    Commented Feb 12, 2015 at 9:36
  • 3
    @EJP since the question is about calling rules , it is worth mentioning the sequence of calling in the answer
    – krishna
    Commented Feb 12, 2015 at 10:41
8

If you simply want to pass all constructor arguments to the base-class (=parent), here is a minimal example.

This uses templates to forward every constructor call with 1, 2 or 3 arguments to the parent class std::string.

Code

Live-Version

#include <iostream>
#include <string>

class ChildString: public std::string
{
    public:
        template<typename... Args>
        ChildString(Args... args): std::string(args...)
        {
            std::cout 
                << "\tConstructor call ChildString(nArgs="
                << sizeof...(Args) << "): " << *this
                << std::endl;
        }

};

int main()
{
    std::cout << "Check out:" << std::endl;
    std::cout << "\thttp://www.cplusplus.com/reference/string/string/string/" << std::endl;
    std::cout << "for available string constructors" << std::endl;

    std::cout << std::endl;
    std::cout << "Initialization:" << std::endl;
    ChildString cs1 ("copy (2)");

    char char_arr[] = "from c-string (4)";
    ChildString cs2 (char_arr);

    std::string str = "substring (3)";
    ChildString cs3 (str, 0, str.length());

    std::cout << std::endl;
    std::cout << "Usage:" << std::endl;
    std::cout << "\tcs1: " << cs1 << std::endl;
    std::cout << "\tcs2: " << cs2 << std::endl;
    std::cout << "\tcs3: " << cs3 << std::endl;

    return 0;
}

Output

Check out:
    http://www.cplusplus.com/reference/string/string/string/
for available string constructors

Initialization:
    Constructor call ChildString(nArgs=1): copy (2)
    Constructor call ChildString(nArgs=1): from c-string (4)
    Constructor call ChildString(nArgs=3): substring (3)

Usage:
    cs1: copy (2)
    cs2: from c-string (4)
    cs3: substring (3)

Update: Using Variadic Templates

To generalize to n arguments and simplify

        template <class C>
        ChildString(C arg): std::string(arg)
        {
            std::cout << "\tConstructor call ChildString(C arg): " << *this << std::endl;
        }
        template <class C1, class C2>
        ChildString(C1 arg1, C2 arg2): std::string(arg1, arg2)
        {
            std::cout << "\tConstructor call ChildString(C1 arg1, C2 arg2, C3 arg3): " << *this << std::endl;
        }
        template <class C1, class C2, class C3>
        ChildString(C1 arg1, C2 arg2, C3 arg3): std::string(arg1, arg2, arg3)
        {
            std::cout << "\tConstructor call ChildString(C1 arg1, C2 arg2, C3 arg3): " << *this << std::endl;
        }

to

template<typename... Args>
        ChildString(Args... args): std::string(args...)
        {
            std::cout 
                << "\tConstructor call ChildString(nArgs="
                << sizeof...(Args) << "): " << *this
                << std::endl;
        }
1
  • 4
    I do take slight offense that such nice example suggests the use std::endl everywhere. People see that and put it in loops and wonder why writing a bunch of lines to a text file is 5x-20x slower "in C++" than using fprintf. TL;DR: Use "\n" (added to an existing string literal if there's one), and use std::endl only when you need to flush the buffers to the file (e.g. for debugging if the code crashes and you want to see its last words). I think that std::endl was a design mistake of convenience: a cool "gadget" that does way more than the name suggests. Commented Nov 25, 2020 at 16:21

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