Given the code:
#include <cassert>
struct X {};
struct Y1: virtual X {};
struct Y2: virtual X {};
struct Y3: virtual X {};
struct Y4: virtual X {};
struct Z1: Y1, Y2 {};
struct Z2: Y3, Y4 {};
struct XYZ: Z1, Z2 {};
int main() {
XYZ xyz;
X *x1 = static_cast<Y1*>(&xyz);
X *x2 = static_cast<Y2*>(&xyz);
X *x3 = static_cast<Y3*>(&xyz);
X *x4 = static_cast<Y4*>(&xyz);
assert( x1 == x2 ); //first pair, ok
assert( x2 == x3 ); //can we make this one fail?
assert( x3 == x4 ); //second pair, ok
return 0;
}
can we make the second assert fail?
In other words, this is the case when we have a two-diamond inheritance graph and would like to have separate subobjects for both diamonds' tops in the most derived object.
The standard (2003, 10.1.4) wording seems to prohibit this, and if really so, the follow-up question is: are we given no means of precise virtual-over-multiply-included subobject structure manipulation, and why?
Once a base is declared virtual, all sources of that virtual base are collapsed into one base of that type, it won't let you split it off halfway up the hierarchy (there's nothing you can say at a child to de-virtual a parent). Just to be clear, inheriting from a different class that non-virtually inherited the base would result in another instance. You could use composition in
XYZ
to create the two instances instead of inheritance, and then use a normal interface to delegate as appropriate.