Reputation: 69
I was learning more about inheritance, and I came across this issue. I am trying to initialize inherited attributes that were inherited from multiple directions, or however you describe it.
The inheritance structure is: A is root, C is root, E inherits from A and C, then F inherits, from A and C and E.
A and C each have a member called m_x
, which I've labeled m_x
as the actual attribute and x
as a getter/setter function with compile-time polymorphism. I know that's probably not good, but this is just an example I made for this question. E and F don't have their own members, just the inherited ones.
I want to initialize an object of F called f
with these values:
m_x
that it got from A: 1m_x
that it got from C: 2m_x
that it got from E, which E got from A: 3m_x
that it got from E, which E got from C: 4It seems to initialize the values of the first two correctly, but I want to know what I'm doing wrong that makes the last two not match. Is what I am trying to achieve possible without changing the general inheritance structure? Adding classes if needed for some reason is fine.
I don't think the template parameters are the issue because I tried it without them and the same result happened.
Result:
1
2
1
2
Expected:
1
2
3
4
Code:
#include <iostream>
template <class T>
class A
{
protected:
T m_x;
public:
A(T x) : m_x(x) { }
T x() { return m_x; }
};
template <class T>
class C
{
protected:
T m_x;
public:
C(T x) : m_x(x) { }
T x() { return m_x; }
};
template <class T1, class T2>
class E : virtual public A<T1>, virtual public C<T2>
{
public:
E(T1 x_A, T2 x_C)
: A<T1>(x_A)
, C<T2>(x_C)
{ }
};
template <class T1, class T2, class T3, class T4>
class F : virtual public A<T1>, virtual public C<T2>, virtual public E<T3, T4>
{
public:
F(T1 x_A, T2 x_C, T3 x_E_A, T4 x_E_C)
: A<T1>(x_A) //also, is this kind
, C<T2>(x_C) //of indentation a
, E<T3, T4>(x_E_A, x_E_C) //dumb idea?
{ }
};
int main()
{
F<int, int, int, int> f(1, 2, 3, 4);
std::cout << f.A::x() << '\n';
std::cout << f.C::x() << '\n';
std::cout << f.E::A::x() << '\n';
std::cout << f.E::C::x() << '\n';
return 0;
}
Upvotes: 1
Views: 156
Reputation: 2849
You used virtual
inheritance and this is why your expectation is wrong.
For each distinct base class that is specified virtual, the most derived object contains only one base class subobject of that type, even if the class appears many times in the inheritance hierarchy (as long as it is inherited virtual every time).
As for why its "1, 2, 1, 2" and not "3, 4, 3, 4":
All virtual base subobjects are initialized before any non-virtual base subobject, so only the most derived class calls the constructors of the virtual bases in its member initializer list.
Upvotes: 2