Pregunta

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 ?

¿Fue útil?

Solución

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;       
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top