Search code examples
c++inheritancedefault-constructor

How are constructors with default parameters called in inheritance hierarchy?


I have this simple code:

class C0
{
        public:
                C0(std::string i) : i_(i) {}

        private:
                std::string i_;
};

class C1 : public virtual C0
{
        public:
                constexpr static auto const e{"e"};

                C1(std::string i = e) : C0(i) {}
};

class C2 : public virtual C1
{
        public:
                C2(std::string k) : k_(k) {}

        private:
                std::string k_;
};

Compiled as: [clang++|g++] -std=c++17 example.cpp

I get the following error:

With g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0:

example.cpp: In constructor ‘C2::C2(std::__cxx11::string)’:
example.cpp:23:41: error: no matching function for call to ‘C0::C0()’
                 C2(std::string k) : k_(k) {}
                                         ^
example.cpp:6:17: note: candidate: C0::C0(std::__cxx11::string)
                 C0(std::string i) : i_(i) {}
                 ^~
example.cpp:6:17: note:   candidate expects 1 argument, 0 provided
example.cpp:3:7: note: candidate: C0::C0(const C0&)
 class C0
       ^~
example.cpp:3:7: note:   candidate expects 1 argument, 0 provided
example.cpp:3:7: note: candidate: C0::C0(C0&&)
example.cpp:3:7: note:   candidate expects 1 argument, 0 provided

With clang++ version 6.0.0-1ubuntu2:

example.cpp:23:17: error: constructor for 'C2' must explicitly initialize the base class 'C0' which does not have a default constructor
                C2(std::string k) : k_(k) {}
                ^
example.cpp:3:7: note: 'C0' declared here
class C0
      ^

Why does the compiler complain about missing default constructor in class C0 when the default constructor of class C1 explicitly calls C0 constructor passing the argument?

When I define a default constructor in C0, the call to C0(i) from C1 does not happen. So the member variable C0::i_ is not initialised. Shouldn't there be a call to C0(i) rather than the default constructor of C0 when C2 is instantiated?


Solution

  • The most derived class is the one that is responsible for constructing the virtual bases. To fix this, add : C0(k) to C2.