I have a struct with several (virtual) bases. From one of these bases' constructor I static_cast to the most derived type, and from there try access a member of another base (which has been initialised before). The adress doesn't match with the result when accessing from the most derived struct's constructor directly. Weirdly (at least to me) the problem only appears if another base (the direct base of the struct where the static_cast originates)is empty.
I recreated the problem in the below example (tested with GNU 9.3.0 on ubuntu linux)
#include <iostream>
#include <string>
/* --: virtual inheritance
* ==: non-virtual inheritance
* BB
* / \
* LB RB
* | \ / |
* | B |
* LD || RD
* \\ || //
* D
*/
struct BaseBase
{
BaseBase() { std::cout << "BaseBase" << std::endl; }
int iBB=1;
};
struct LeftBase : public virtual BaseBase
{
LeftBase() { std::cout << "LeftBase" << std::endl; }
int iLB=2;
};
struct RightBase : public virtual BaseBase
{
RightBase() { std::cout << "RightBase" << std::endl; }
//int iRB=3; //--> uncomment here to resolve? problem
};
struct Base : public virtual LeftBase, public virtual RightBase
{
Base() { std::cout << "Base" << std::endl; }
int iB=4;
};
struct LeftDerived : public virtual LeftBase
{
LeftDerived() { std::cout << "LeftDerived " << std::endl; }
int iLD=5;
};
template<typename DerivedType>
struct RightDerived : public virtual RightBase
{
RightDerived() { std::cout << "RightDerived " << &( static_cast<DerivedType*>(this)->iLB ) /*<< " " << static_cast<DerivedType*>(this)->iLB*/ << std::endl; }
int iRD=6;
};
struct Derived : public Base, public LeftDerived, public RightDerived<Derived>
{
Derived() { std::cout << "Derived " << &(iLB) << std::endl; }
int iD=7;
};
int main()
{
Derived MyDerived;
}
I get the following output (printing from all constructors to show the order in which the bases are initialised):
BaseBase
LeftBase
RightBase
Base
LeftDerived
RightDerived 0xd5957b646068
Derived 0x7ffd19379408
while if I uncomment the int in 'RightBase' I get:
BaseBase
LeftBase
RightBase
Base
LeftDerived
RightDerived 0x7ffebf1fb948
Derived 0x7ffebf1fb948
More so than finding a solution (having the base non-empty is sort of one), I would like to learn why the above code is wrong, and in which situation I can possibly expect similar problems.