struct X { int i; }; struct Y : X { Y(); }; // non-trivial struct A { int a; }; struct B : public A { int j; Y y; }; // non-trivial extern B bobj; B* pb = &bobj; // OK int* p1 = &bobj.a; // undefined behavior: refers to base class member int* p2 = &bobj.y.i; // undefined behavior: refers to member's member A* pa = &bobj; // undefined behavior: upcast to a base class type B bobj; // definition of bobj extern X xobj; int* p3 = &xobj.i; // OK, X is a trivial class X xobj;
struct W { int j; }; struct X : public virtual W { }; struct Y { int* p; X x; Y() : p(&x.j) { // undefined, x is not yet constructed } };
struct C; void no_opt(C*); struct C { int c; C() : c(0) { no_opt(this); } }; const C cobj; void no_opt(C* cptr) { int i = cobj.c * 100; // value of cobj.c is unspecified cptr->c = 1; cout << cobj.c * 100 // value of cobj.c is unspecified << '\n'; } extern struct D d; struct D { D(int a) : a(a), b(d.a) {} int a, b; }; D d = D(1); // value of d.b is unspecifiedβ end example
struct A { }; struct B : virtual A { }; struct C : B { }; struct D : virtual A { D(A*); }; struct X { X(A*); }; struct E : C, D, X { E() : D(this), // undefined behavior: upcast from E* to A* might use path E* β D* β A* // but D is not constructed // βD((C*)this)β would be defined: E* β C* is defined because E() has started, // and C* β A* is defined because C is fully constructed X(this) {} // defined: upon construction of X, C/B/D/A sublattice is fully constructed };β end example
struct V { virtual void f(); virtual void g(); }; struct A : virtual V { virtual void f(); }; struct B : virtual V { virtual void g(); B(V*, A*); }; struct D : A, B { virtual void f(); virtual void g(); D() : B((A*)this, this) { } }; B::B(V* v, A* a) { f(); // calls Vβ::βf, not Aβ::βf g(); // calls Bβ::βg, not Dβ::βg v->g(); // v is base of B, the call is well-defined, calls Bβ::βg a->f(); // undefined behavior: a's type not a base of B }β end example
struct V { virtual void f(); }; struct A : virtual V { }; struct B : virtual V { B(V*, A*); }; struct D : A, B { D() : B((A*)this, this) { } }; B::B(V* v, A* a) { typeid(*this); // type_Βinfo for B typeid(*v); // well-defined: *v has type V, a base of B yields type_Βinfo for B typeid(*a); // undefined behavior: type A not a base of B dynamic_cast<B*>(v); // well-defined: v of type V*, V base of B results in B* dynamic_cast<B*>(a); // undefined behavior: a has type A*, A not a base of B }β end example