Consider a diamond inheritance graph (i.e., virtual base class). We know from previous questions that on construction the most derived class directly calls the default (0-arg) constructor of the (virtual) base.
But we also know from answers to the previous question (e.g., here that if the "middle" classes in the diamond have constructors that are used by the most-derived class and those constructors "call" non-default constructors of their (virtual) base class (via the initialization list) then that is not respected … though the bodies of the "middle" classes' constructors are executed.
Why is that? I would have thought it should be a compile error. (Detected, of course, when the most-derived class is declared and the diamond is created.)
I'm looking for two things:
- where in the standard is this specified?
- does this kind of explicit-yet-ignored code happen anywhere else in the language?
Code sample of what I'm talking about follows its actual and expected outputs below:
B 0arg-ctor
Mf 0arg-ctor
Mt 0arg-ctor
useD
expected output:
ERROR: (line 19) struct `D` creates a diamond inheritance graph where an explicitly
written invocation of a virtual base class constructor is ignored (for base
classes `Mf`and `Mt` and ancestor virtual base class `B`
code:
#include <iostream>
using namespace std;
struct B {
B() noexcept { cout << "B 0arg-ctor" << endl; };
B(bool) noexcept { cout << "B 1arg-ctor" << endl; };
};
struct Mf : public virtual B
{
Mf() : B(false) { cout << "Mf 0arg-ctor" << endl; }
};
struct Mt : public virtual B
{
Mt() : B(true) { cout << "Mt 0arg-ctor" << endl; }
};
struct D : public Mf, public Mt { };
void useD(D) { cout << "useD" << endl; }
int main()
{
D d;
useD(d);
return 0;
}
language-lawyer
tag. – EljaySub
direct subobject (T::T() : Sub() { ... }
) of class type is exactly the same as not mentioning it at all (T::T() { ... }
). – curiousguy