c++ - virtual inheritance constructor order -


i trying understand better concept of virtual inheritance, , perils.

i read in post (why default constructor called in virtual inheritance?) (= virtual inheritance) changes order of constructor call (the "grandmother" called first, while without virtual inheritance doesn't).

so tried following see got idea (vs2013):

#define tracefunc printf(__function__); printf("\r\n") struct {     a(){ tracefunc; }  };  struct b1 : public {     b1(){ tracefunc; }; };  struct b2 : virtual public {     b2() { tracefunc; }; };  struct c1 : public b1 {     c1() { tracefunc; }; };  struct c2 : virtual public b2 {     c2() { tracefunc; }; };  int _tmain(int argc, _tchar* argv[]) {     a* pa1 = new c1();     a* pa2 = new c2(); } 

the output is:

a::a b1::b1 c1::c1 a::a b2::b2 c2::c2 

which not expected (i expected order of 2 classes different).

what missing? can explain or direct me source explains better?

thanks!

in example, output expected. virtual inheritance comes play in instance when have class multiple inheritance who's parent classes inherit same class/type (i.e. "diamond problem"). in example, classes might set virtually inherit (if needed elsewhere in code), don't 'virtually inherit' based on example since none of derived classes (b1/b2/c1/c2) more inherit directly a.

to expand, i've tweaked example explain little more:

#include <cstdio>  #define tracefunc printf(__function__); printf("\r\n") struct {     a() { tracefunc; }     virtual void write() { tracefunc; }     virtual void read() { tracefunc; } };  struct b1 : public {     b1() { tracefunc; };     void read(){ tracefunc; } };  struct c1 : public {     c1() { tracefunc; };     void write(){ tracefunc; } };  struct b2 : virtual public {     b2() { tracefunc; };     void read(){ tracefunc; } };  struct c2 : virtual public {     c2() { tracefunc; };     void write(){ tracefunc; } };  // z1 inherits b1 , c1, both of inherit a; when call made // of base function (i.e. a::read or a::write) derived class, call // ambiguous since b1 , c1 both have 'copy' (i.e. vtable) parent class. struct z1 : public b1, public c1 {     z1() { tracefunc; } };  // z2 inherits b2 , c2, both of inherit virtually; note z2 doesn't // need inherit virtually b2 or c2. since b2 , c2 both virtual inherit a, when // constructed, 1 copy of base class made , vtable pointer info // "shared" between 2 base objects (b2 , c2), , calls no longer ambiguous struct z2 : public b2, public c2 {     z2() { tracefunc; } };   int _tmain(int argc, _tchar* argv[]) {     // gets 2 "copies" of 'a' base since 'b1' , 'c1' don't virtually inherit 'a'     z1 z1;     // gets 1 "copy" of 'a' base since 'b2' , 'c2' virtualy inherit 'a' , "share" vtable pointer 'a' base     z2 z2;      z1.write(); // ambiguous call write (which 1 .. b1::write() (since b1 inherits a) or a::write() ?)     z1.read(); // ambiguous call read (which 1 .. c1::read() (since c1 inherits a) or a::read() ?)      z2.write(); // not ambiguous: z2.write() calls c2::write() since it's "virtually mapped" to/from a::write()      z2.read(); // not ambiguous: z2.read() calls b2::read() since it's "virtually mapped" to/from a::read()      return 0; } 

while might "obvious" humans call intend make in case of z1 variable, since b1 doesn't have write method, "expect" compiler choose c1::write method, due how memory mapping of objects work, presents problem since base copy of a in c1 object might have different information (pointers/references/handles) copy of a base in b1 object (since there's technically 2 copies of a base); call b1::read() { this->write(); } give unexpected behaviour (though not undefined).

the virtual keyword on base class specifier makes explicit other classes virtually inherit same base type, shall 1 copy of base type.

note above code should fail compile compiler errors explaining ambiguous calls z1 object. if comment out z1.write(); , z1.read(); lines output (for me @ least) following:

a::a b1::b1 a::a c1::c1 z1::z1 a::a b2::b2 c2::c2 z2::z2 c2::write b2::read 

note 2 calls a ctor (a::a) before z1 constructed, while z2 has 1 call a constructor.

i recommend reading the following on virtual inheritance goes more in depth on of other pitfalls take note of (like fact virtually inherited classes need use initialization list make base class ctor calls, or should avoid using c-style casts when doing such type of inheritance).

it explains little more alluding constructor/destructor ordering, , more how ordering done when using multiple virtual inheritance.

hope can clear things bit.


Comments

Popular posts from this blog

angularjs - ADAL JS Angular- WebAPI add a new role claim to the token -

php - CakePHP HttpSockets send array of paramms -

node.js - Using Node without global install -