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