87

I don't understand why in the following code, when I instanciate an object of type daughter, the default grandmother() constructor is called ?

I thought that either the grandmother(int) constructor should be called (to follow the specification of my mother class constructor), or this code shouldn't compile at all because of the virtual inheritance.

Here compiler silently calls grandmother default constructor in my back, whereas I never asked for it.

#include <iostream>

class grandmother {
public:
    grandmother() {
        std::cout << "grandmother (default)" << std::endl;
    }
    grandmother(int attr) {
        std::cout << "grandmother: " << attr << std::endl;
    }
};

class mother: virtual public grandmother {
public:
    mother(int attr) : grandmother(attr) {
        std::cout << "mother: " << attr << std::endl;
    }
};

class daughter: virtual public mother {
public:
    daughter(int attr) : mother(attr) {
        std::cout << "daughter: " << attr << std::endl;
    }
};

int main() {
  daughter x(0);
}
Pubby
  • 51,882
  • 13
  • 139
  • 180
Simon Desfarges
  • 972
  • 1
  • 7
  • 9

1 Answers1

96

When using virtual inheritance, the virtual base class's constructor is called directly by the most derived class's constructor. In this case, the daughter constructor directly calls the grandmother constructor.

Since you didn't explicitly call grandmother constructor in the initialization list, the default constructor will be called. To call the correct constructor, change it to:

daugther(int attr) : grandmother(attr), mother(attr) { ... }

See also This FAQ entry.

interjay
  • 107,303
  • 21
  • 270
  • 254
  • 2
    That totally makes sense, thanks! All constructors in the hierarchy are called from the last class and not by their respective child class. Never thought of that. C++ spec can be tricky sometimes... – Aurelien Ribon Mar 28 '12 at 13:03
  • Thank you ! So in case of virtual inheritance, the best to do is to manually call all the constructors of the chain. – Simon Desfarges Mar 28 '12 at 13:11
  • Does this refers only to virtual parent constructors or every parent constructor? – Xriuk Jan 07 '16 at 13:48
  • 1
    @Xriuk It refers to constructors of classes that were inherited using virtual inheritance. – interjay Jan 08 '16 at 15:34
  • 2
    does that mean grandmother will be called twice? what happens with the call to grandmother inside mother? – Youda008 Apr 09 '16 at 14:14
  • 8
    @Youda008 It will be called once. The call from `mother` will be ignored, unless you directly instantiate `mother` rather than a derived class. – interjay Apr 09 '16 at 16:32
  • @interjay. That was really helpful answer. But can you please elaborate on why and how this behaviour is handled by the compiler. If we do not use the "Virtual" keyword the parametrised constructor will be called without even specifying it explicitly in the daughter class. what does the virtual function do behind the screens that is responsible for this behaviour? – Darshan b Mar 03 '20 at 16:37