3

I think an example would describe my problem the best.

struct Base {
    Base() = delete;
    Base(int x) : x(x) {}
    int x;
};

struct Derived1 :  virtual Base {
    Derived1(int y) : Base(5), y(y) {}
    int y;
};

struct Derived2 :  virtual Base {
    Derived2(int z) : Base(10), z(z) {}
    int z;
};

struct Derived3: Derived1, Derived2 {
public:
    Derived3(int y, int z) : Derived1(y), Derived2(z) {}

};

And an error I get: In constructor ‘Derived3::Derived3(int, int)’: error: use of deleted function ‘Base::Base()’ Derived3(int y, int z) : Derived1(y), Derived2(z) {}

I do not understand why this error occurs. In my opinion all base classes are actually get initialized in this example via their constructors (explicitly Derived1 and Derived2 and implicitly Base through Derived2 (I am not sure here, maybe through Derived1)). Well, let's do what compiler tells me.

struct Derived3: Derived1, Derived2 {
public:
    Derived3(int y, int z) : Base(-1), Derived1(y), Derived2(z) {}

};

It compiles and if I do now this:

Derived3 d = Derived3(7, 9);
std::cout << d.x << std::endl;
std::cout << d.y << std::endl;
std::cout << d.z << std::endl;

I get -1, 7, 9. And it is not what I wanted at all. An idea was to initialize base class with one of its derived classes and I was expecting the first number to be 5 or 10.

So, here is my question: Why I am forced to explicitly call Base constructor when It is already done in one of the derived classes?

More specifically, as I have multiple inheritance and virtual inheritance, I believe that any instance of Derived3 has exactly one copy of instance of Base class. And I was expecting that this copy of Base is initialized in the most derived class of it (Derived1 or Derived2), but as I clearly can see it does not work in this way =( Where am I wrong?

antonpp
  • 2,333
  • 23
  • 28
  • Virtual inheritance is tricky. The key is that the virtual base subobject is "owned" by the most-derived object, which must also initialize it. – Kerrek SB Jan 20 '17 at 18:33
  • You're correct in that `Base` is initialised in the most derived class, but that class is `Derived3`. – molbdnilo Jan 20 '17 at 18:38
  • @molbdnilo, thats seems logical. Maybe you know any way how I can make one of the classes `Derived1` and `Derived2` the most derived so I will not have to call `Base(int)` in `Derived3`? I tried to make a longer chain of subclasses but it did not work out. – antonpp Jan 20 '17 at 18:45
  • Well, that's sad that my question was marked as duplicate. I checked the referenced question before I asked my own and it did not helped me so I decided to be more specific. – antonpp Jan 20 '17 at 18:52
  • @antonpp "Most derived class" is a property of an object, not of a type. – molbdnilo Jan 20 '17 at 20:05

1 Answers1

6

When you use virtual inheritance, there is only 1 copy of Base. Who should initialize that copy, Derived 1 or Derived 2? There is no way to know. That is why you are forced to do it yourself in Derived 3, so there can be no ambiguity. That is also why you get the output you get instead of 5 or 10.

Without virtual inheritance both Derived 1 and Derived 2 would have their own copies of Base that they would be responsible for, therefore there is no ambiguity. When you force them to inherit from the same base Derived 3 has to take ownership of Base in order to resolve the ambiguities... virtual inheritance is weird at best.

RyanP
  • 1,898
  • 15
  • 20
  • Yeah, thank you, I got it. But maybe there is any way how I can remove ambiguity and tell the compiler which of the derived classes must initialize the Base? – antonpp Jan 20 '17 at 18:48
  • @antonpp Not that I'm aware of, but I'm hardly an expert user for virtual inheritance so that doesn't mean none exist. Truth is though, usually when you reach for virtual inheritance, you're trying to make a bad design work. There are some legitimate use cases, but not many. – RyanP Jan 20 '17 at 18:54
  • @antonpp: No, because the rule is that "the most-derived object initializes the virtual base", not "you get to decide who initializes the virtual base". – Kerrek SB Jan 20 '17 at 23:13