views:

344

answers:

6

What is the size of virtual pointer(VPTR) for a virtual table in C++? Also this is not a homework question...just a question that came to my mind while I was reading a C++ book.

+1  A: 

Probably the same size as a normal pointer... generally 4 bytes on 32-bit machines. But this would be compiler-dependent, some compilers may do things differently.

Artelius
+1  A: 

Most likely the size of any other pointer. Try something like this to find out for your compiler and machine:

#include <iostream>
struct base {
    base() {}
    virtual ~base() {}
};
int main( int argc, char **argv ) {
    std::cout << sizeof( base ) << std::endl;
}
Boojum
+2  A: 

Note that in order to gracefully handle multiple inheritance, there can be more than one VPTR in an object, but in general each is likely to be a simple architecture dependent pointer.

Try running something like this to see how your compiler lays things out:

#include <iostream>
using namespace std;

struct Base
{
    int B;
    virtual ~Base() {} 
};

struct Base2
{
    int B2;
    virtual ~Base2() {} 
};

struct Derived : public Base, public Base2
{
    int D;
};

int main(int argc, char* argv[])
{
    cout << "Base:" << sizeof (Base) << endl;
    cout << "Base2:" << sizeof (Base2) << endl;
    cout << "Derived:" << sizeof (Derived) << endl;

    Derived *d = new Derived();
    cout << d << endl;
    cout << static_cast<Base*>(d) << endl;
    cout << &(d->B) << endl;
    cout << static_cast<Base2*>(d) << endl;
    cout << &(d->B2) << endl;
    cout << &(d->D) << endl;
    delete d;
    return 0;
}

On my 32-bit compiler, this give 8 bytes for both Base classes, and 20 bytes for the Derived class (and double those values when compiled for 64 bits):

4 bytes Derived/Base VPTR
4 bytes int B
4 bytes Derived/Base2 VPTR
4 bytes int B2
4 bytes int D

You can see how by looking at the first 8 bytes, you can treat a Derived as a Base, and how by looking at the second 8 bytes, you can treat it as a Base2.

Eclipse
+1  A: 

The pointers in the virtual function table are generally the same size as regular pointers in the system. Typically a virtual function table is calculated for every type, and each object instance will contain a pointer to its type's table, so instances of objects containing virtual functions will use sizeof(void *) bytes more per instance than ones that don't. Types deriving from multiple base types must be castable to any base type so may contain multiple pointers to the base types' virtual function tables as necessary. All of this is compiler dependent of course.

moonshadow
+4  A: 

An excellent article related to this topic is Member Function Pointers and the Fastest Possible C++ Delegates. This article delves deeply into the implementation of member function pointers for many different compilers. This article talks about all the nuances of vtable pointers particularly in light of multiple (and virtual) inheritance.

Greg Hewgill
A: 

That depends on your implementation, but it's easy to find out. For this program

#include <iostream>

struct virtual_base {
    int data;
    virtual_base() {}
    virtual ~virtual_base() {}
};

struct non_virtual_base {
    int data;
    non_virtual_base() {}
    ~non_virtual_base() {}
};

int main() {
    std::cout << sizeof( virtual_base ) - sizeof( non_virtual_base ) << '\n';
    return 0;
}

mine (VC 2008) will print 4, so the cost of polymorphism is, in this case, 4 byte.

sbi