C++ Derived polymorphic class - does it contain an entire instance of Base, including a vptr?

StackOverflow https://stackoverflow.com/questions/7529728

Pergunta

Say we have

Class A
{
   public:
   int _i;
   virtual int getI();
};
class B : public A
{  
   public:
   int _j;
   virtual int getI();
};

So assuming that the size of a class in memory is the sum of its members (i.e. ignoring padding or whatever might actually happen), what is the size of a B instance? Is it sizeof(A) + sizeof(int) + sizeof(vptr)? Or does a B instance not hold an A vptr in it's personal A instance, so that sizeof(b) would be sizeof(int) + sizeof(int) + sizeof(vptr)?

Foi útil?

Solução

It's whatever the implementation needs to make the code work. All you can say is that it is at least 2 * sizeof(int), because objects of type B contain two ints (and possibly other things). In a typical implementation, A and B will share a vptr, and the total size will be just one pointer more than the two ints (modulo padding for alignment, but on most implementations, I don't think that there will be any). But that's just a typical implementation; you can't count on it.

Outras dicas

Any talk of a vtable is going to be specific to a certain implementation, since even the existance of a vtable isn't specified by the C++ standard - it's an implementation detail.

Generally an object will only have one pointer to a vtable, and that vtable will be shared among all objects of that type. The derived class will contain pointers in the table for each virtual function of the base classes plus each new virtual function that it didn't inherit, but again this is a static table and it is not part of the object.

To actually answer the question, the most likely outcome is sizeof(B) == sizeof(A::_i) + sizeof(B::_j) + sizeof(vptr).

Why would you want to know? If you are going to use that in your program, I'd try to look for a more portable way than calculate it and either add a virtual function that returns the size, or perhaps use the runtime type infomration to get the correct type and then return the size.

(if you vote up or add comments I'll start decorating the answer)

In addition to what James Kanze said, it is perhaps worth mentioning that (on a typical implementation) the B's virtual table will contain A's virtual table at its beginning.

For example:

class A {
    virtual void x();
    virtual void y();
};

class B : A {
    virtual void y();
    virtual void z();
};

A's virtual table:

  • A:x()
  • A:y()

B's virtual table:

  • A:x()
  • B:y()
  • B:z()

That's why an instance of B can get away with just one virtual table pointer.

BTW, multiple inheritance can complicate things quite a bit and introduce multiple virtual table pointers per object.

Always keep in mind that all this is an implementation detail and you should never write code that depends on it.

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