i have the following scenario:
class A
{
public:
A(std::string id);
};
class B : public virtual A
{
public:
B();
};
class C : public virtual A
{
public:
C();
};
class D : public B, public C
{
public:
D(std::string id);
};
D::D(std::string id) : A(id), B(), C()
{
}
class X : public D
{
public:
X(std::string id);
}
X::X(std::string id) : D(id)
{
}
Now, if i create an instance of D everything works fine. However if i create an instance of X i get a compiler error which tells me that something tries to call the default constructor of A - which does not exist. If i create it, it compiles but only the default constructor is called and accordingly, id is not correctly set/initialized.
This can be fixed by implementing the constructor of X like so:
X::X(std::string id) : A(id), D(id)
{
}
But my understanding is, that this should be unnecessary. So where's my error ?
You need to make all your constructors public
and define a default constructor for A
because the string constructor will mark the default constructor as =delete
. Furthermore, the most derived class will initialize any virtual base class, quoting from the draft Standard:
12.6.2 Initializing bases and members [class.base.init]
10 In a non-delegating constructor, initialization proceeds in the following order: — First, and only for the constructor of the most derived class (1.8), virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.
In this case that means that X
must indeed initalize A
.
#include <iostream>
#include <string>
class A
{
public:
A() { std::cout << "A\n"; }
A(std::string id) { std::cout << id << " A(id)\n"; }
};
class B : public virtual A
{
public:
B() { std::cout << "B\n"; }
};
class C : public virtual A
{
public:
C() { std::cout << "C\n"; }
};
class D : public B, public C
{
public:
D(std::string id): A(id) { std::cout << id << " D(id)\n"; }
};
class X : public D
{
public:
X(std::string id): A(id), D(id) { std::cout << id << " X(id)\n"; }
};
int main()
{
X x("bla");
x;
}