Given the code:
class A{};
class B : public virtual A{};
class C : public virtual A{};
class D : public B,public C{};
int main(){
cout<<\"sizeof(D)
You are making far too many assumptions. This is highly dependent on the ABI, so you should look into the documentation for your platform (my guess is that you are running on a 32bit platform).
The first thing is that there are no virtual functions in your example, and that means that none of the types actually contains a pointer to the virtual table. So where did those 2 pointers come from? (I am assuming you are on a 32bit architecture). Well, virtual inheritance is the answer. When you inherit virtually, the relative location of the virtual base (A) with respect to the extra elements in the derived type (B,C) will change along the inheritance chain. In the case of a B or C object the compiler can lay the types as [A,B'] and [A,C'] (where X' is the extra fields of X not present in A).
Now virtual inheritance means that there will only be one A subobject in the case of D, so the compiler can layout the D type as [A,B',C',D] or [A,C',B',D] (or any other combination, A might be at the end of the object, etc, this is defined in the ABI). So what does this imply, this implies that member functions of B and C cannot assume where the A subobject might be (in the event of non-virtual inheritance, the relative location is known), because the complete type might actually be some other type down the chain.
The solution to the problem is that both B and C usually contain an extra pointer-to-base pointer, similar but not equivalent to the virtual pointer. In the same way that the vptr is used to dynamically dispatch to a function, this extra pointer is used to dynamically find the base.
If you are interested in all this details, I recommend that you read the Itanium ABI, which is widely used not only in Itanium but also in other Intel 64 architectures (and a modified version in 32 architectures) by different compilers.