Q:

c++ virtual inheritance: Implementation difference

I know the usage of virtual inheritance:
class A { public: void Foo() {} };
class B : public virtual A {};
class C : public virtual A {};
class D : public B, public C {};

What I want to know is the difference between 
class X { public: void Bar() {} };
class Y : public virtual X {};

and
class X { public: void Bar() {} };
class Y : public X {};

mainly from the implementation perspective. I mean when would I not want to use virtual inheritance?

A:

Firstly, virtual inheritance will "merge" all identically-typed virtual bases into a single base subobject, shared by all derived types in the complete object. Do you want that to happen? If you want such bases to be represented by separate base subobjects, then you can't use virtual inheritance. So, there is an obvious matter of your intent.
In your first example, the same single A subobject will be shared by classes B, C and D within a complete object of type D. If inheritance was non-virtual, then B would have its own separate A and C would have its own separate A. This would obviously affect the behavior of any code that relies on As object identity.
So, from this point of view it is really a question to you: what do you want to implement? A single shared base subobject? Or multiple independent base subobjects?
(Your X and Y example is non-representative. The above properties of virtual inheritance only reveal itself in multiple-inheritance configurations. In single-inheritance situation virtual inheritance achieves nothing, besides imposing potential performance/space overhead.)
Secondly, in order to provide access from all derived classes to a single shared base class subobject (in case of virtual inheritance) the compiler will use run-time implementation structures. Typically derived classes will access their virtual bases through pointers embedded into each object with virtual base. This imposes a performance penalty and requires additional space in object's layout.
Meanwhile, "normal" (non-virtual) inheritance produces a fixed compile-time layout, which means that all conversions between classes are performed by adding or subtracting a fixed offset, immediately known to the compiler. This is faster and requires no additional run-time information.

