Pages

Thursday, July 29, 2010

C++ virtual functions

I did this stuff while understanding virtual functions and polymorphism in C++ for job interviews. And got a chance to clean it up and comment it well (of course to be put on a blog).

This ones on virtual functions, explaining how VPTR and VTABLE work. Code is self explanatory, accompanied by a diagram.

Code example to find out VPTR and VTABLE in C++ class. And use it to probe
class virtual functions.
VPTR and VTABLE usage in C++ Class expalined diagrammatically below.

Test Class Object
     (obj)
       |             VTABLE (vtable)
       v                   |
+------------+             v
| VPTR (vptr)|------>+------------+
+------------+       |  VTEntry1  |------------> +------------+
| DATA1 (a)  |       +------------+              |  func1()   |
+------------+       |  VTEntry2  |-------+      |            |
| DATA2      |       +------------+       |      |            |
+------------+       |      .     |       |      +------------+
|      .     |       |      .     |       |
|      .     |       |      .     |       +----->+------------+
|      .     |                                   |   func2()  |
|      .     |                                   |            |
                                                 |            |
                                                 +------------+

typedef void (*func)(void); // class member function type
typedef int* ptr;           // 32 bit system pointer type

class Test {
public:
    int a; // DATA1

    Test() : a(0) {}

    virtual void func1() {
        cout << "Test::func1" << endl;
    }

    virtual void func2() {
        cout << "Test::func2" << endl;
    }
};

int main(int argc, char * const argv[]) {
    Test obj;
    int  *pdata;
    ptr  vptr, vtable;
    func pfunc = NULL;

    vptr = (ptr)&obj;     // first address of obj (class) points to vptr
    vtable = (ptr)*vptr;  // dereferencing vptr to get vtable
    pdata = (int*)((ptr)&obj+1); // this is 'a', the first member of class Test

    *pdata = 10;
    cout << "pdata (a): " << *pdata << endl;
    cout << "vptr: " << vptr << "   " << "vtable: " << vtable << endl;

    // dereferencing first (VTEntry1) entry in VTABLE
    pfunc = (func)*(vtable+0);
    pfunc();

    // dereferencing second (VTEntry2) entry in VTABLE
    pfunc = (func)*(vtable+1);
    pfunc();

    return 0;
}

Output:
pdata (a): 10
vptr: 0xbfee67d4   vtable: 0x8048a80
Test::func1
Test::func2

virtualtest.cpp file link

No comments:

Post a Comment