Reputation: 13575
There are all kinds of cases from simple to complex structures of virtual functions. What factor determines the number of extra memory it required? For example
class A {virtual void F() {} };
class B : public A {virtual void F() {} };
How many more memory does A and B require compare to classes without virtual functions? Another example with 2 virtual functions,
class A {virtual void F() {} virtual void G() {} };
class B : public A {virtual void F() {} virtual void G() {} };
and example 3
class A {virtual void F() {}; virtual void G() {} };
class B : public A {virtual void F() {} };
[--------------- Add More Interesting questions ------------------]
Does every virtual method have a virtual method table? If so, I think for a class (not object, right? I think the VPTR is static.) with a number of virtual method requires a number of VPTRs, each for a virtual method. Right?
Is it possible to build just one table for all virtual methods and put only one VPTR in a class?
And I think the calling speed of virtual functions should be faster than manual ifs since the direct VPTR is used. Right?
[--------------- A Test ----------------]
I did a test and show my results with both VS2010 and intel c++ compiler.
struct A
{
static int s_i;
int i;
virtual void F() {i+=1;}
virtual void G() {i+=2;}
};
struct B
: public A
{
int j;
virtual void F() {i+=3;}
virtual void G() {i+=4;}
virtual void H() {i+=5;}
};
struct C
: public B
{
virtual void F() {i+=6;}
virtual void H() {i+=7;}
};
TEST(MemoryForVirtualMethod)
{
CHECK_EQUAL(sizeof(A), 8);
CHECK_EQUAL(sizeof(B), 12);
CHECK_EQUAL(sizeof(C), 12);
}
From the results, my conclusions are
(1) For each object with virtual functions, one (hidden pointer of) VPTR is added.
(2) Foe each class, a virtual method table is built for all virtual methods of the class.
(3) Putting the VPTR in object is to implement the dynamic dispatch since the class referred may not be the dynamic class.
(4) The implementation is efficient in calling (faster than manual ifs) but sacrifices some memory.
Thanks a lot!
Upvotes: 2
Views: 1240
Reputation: 31952
Since virtual functions are typically implemented as a virtual method table (vtable), I am guessing O(number of virtual functions)
per class
and 1 extra pointer per object
. Not as exact as you want, but should give a rough idea.
As @AlokSave mentions, there are many other subtleties which are very compiler specific and may not be consistent enough to estimate.
Typically, the compiler creates a separate vtable for each class. When an object is created, a pointer to this vtable, called the virtual table pointer, vpointer or VPTR, is added as a hidden member of this object
Source : Wikipedia
The number of functions you override (as in your examples) is (im guessing) irrelevent, except when the function to be called can safely be determined at compile time, in which case it might be treated as a static dispatch function (G()
in your 2nd example). This is also up to the compiler.
compilers usually avoid using vtables whenever the call can be resolved at compile time.
Finally, The cost of virtual function is likely to be harder on speed than memory..
Upvotes: 3