C++ Derived polymorphic class - does it contain an entire instance of Base, including a vptr?
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)?
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 int
s (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.
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.
精彩评论