Pergunta

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 ?

Foi útil?

Solução 3

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).

Outras dicas

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.

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.

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top