1

While playing around with inheritance, i happened to try this :

class A
{ int i; };

class B : virtual public A
{ int j; };

class C : public B
{ int k; };

int main()
{
    std::cout<<sizeof(C)/sizeof(int);
    return 0;
}

Which gave me the output 6

While the following worked as expected giving the output 3

class A
{ int i; };

class B : public A  // No virtual here
{ int j; };

class C : public B
{ int k; };

int main()
{
    std::cout<<sizeof(C)/sizeof(int);
    return 0;
}

Why this difference ? and, why is it double of the second case ?

curiousguy
  • 8,038
  • 2
  • 40
  • 58
asheeshr
  • 4,088
  • 6
  • 31
  • 50

4 Answers4

2

This is implementation dependent.

However, almost all compilers will use the same mechanism, whenever you have a virtual keyword the compiler needs to do some additional bookkeeping through vptr and vtables. This extra bookkeeping adds to the class size.

Strictly, You should rely on the size to be anything specific and that is the reason why the standard provides sizeof to get the actual size rather than guess-timate it.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
2

Quite simply, virtual inheritance involves extra overhead. A typical implementation would require at least an extra pointer.

See question 4 in Virtual tables and virtual pointers for multiple virtual inheritance and type casting and the answers.

Community
  • 1
  • 1
NPE
  • 486,780
  • 108
  • 951
  • 1,012
1
class A {
    int i;
};

class B : public A {
    int j;
};

In this example, which does not use virtual inheritance, an object of type B can be laid out as if B had been defined like this:

class B0 {
    int i;
    int j;
};

Once you introduce virtual inheritance, this doesn't work:

class C : public virtual A {
    int k;
};

class D : public virtual A {
    int l;
};

class E : public C, public D {
    int m;
};

An object of type C has two int members: k from the definition of C and i from the definition of A. Similarly, an object of type D has two int members, l and i. So far, so good. The tricky part comes with class E: it, too, has one int member i, because both instances of A are virtual bases. So neither C nor D can't be written like B0 above, because then E would end up with two copies of i.

The solution is to add a layer of indirection. Objects of type C, D, and E look something like this (pseudo-code, don't try to compile it):

class C0 {
    int *cip = &i;
    int k;
    int i;
};

class D0 {
    int *dip = &i;
    int l;
    int i;
};

class E0 {
// C0 subobect:
    int *cip = &i;
    int k;
// D0 subobject:
    int *dip = &i;
    int l;
// E data:
    int *eip = &i;
    int m;
    int i;
};

What you're seeing in the size of E is those extra pointers, which make it possible to have a single copy of i regardless of how C and D are combined in a derived class. (In reality, each of those pointers would be a pointer to A, since A can certainly have more than one data member, but that's too hard to represent in this simple pseudo-code).

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • `int *cip = &i;` by this you mean a pointer to the inherited member i in C ? IF so, then in virtual inheritance, practically only the pointers are inherited and not the members having the same name ? – asheeshr Dec 09 '12 at 04:18
  • 1
    @AshRj - this answer is about implementation details. Regardless of how virtual inheritance is implemented, the members of the virtual base are inherited; you can refer to them directly through an object of a derived type without having to know that they come from a base class. – Pete Becker Dec 09 '12 at 15:39
0

It depends on your compiler's implementation. Different compiler has different result. But one is certain, the result must more than three.

CodeSun
  • 17
  • 2