-->

How to use the vtable to determine class type

2019-04-26 19:35发布

问题:

I was recently on an interview for a position where C/C++ is the primary language and during one question I was told that it's possible to use the vtable to determine which class in a hierarchy a base pointer actually stores.

So if, for example you have

    class A  
    {  
    public:  
    A() {}  
    virtual ~A() {}  
    virtual void method1() {}  
    };

    class B : public A  
    {  
    public:  
    B() {}  
    virtual ~B() {}  
    virtual void method1() {}  
    };

and you instantiate A * pFoo = new B(), is it indeed possible to use the vtable to determine whether pFoo contains a pointer to an instance of A or B?

回答1:

This is obviously implementation dependent but, on most implementations, the in-memory representation of an object of class A or B will start with a pointer to the vtable. You can look at this vtable pointer, compare it to vtable pointers for objects that you know to be of class A or B, and determine the class of the object in that way.

To illustrate (of course this is anything but good style):

A *pFoo=new B(); // pointer to object of unknown class (either A or B)
A a;  // Object known to be of class A
B b;  // Object known to be of class B
void *vptrA=*((void **)&a);  // Pointer to vtable of class A
void *vptrB=*((void **)&b);  // Pointer to vtable of class B
void *vptrFoo=*((void **)pFoo);  // Pointer to vtable of unknown object
if(vptrFoo==vptrA)
    printf("Class A\n");
else
    printf("Class B\n");

Important: This is only an illustration of how most implementations work; besides being implementation dependent, this technique breaks down in the presence of multiple inheritance. You should never do anything like this in production code; use RTTI instead.



回答2:

Yes, it's quite possible to do - use dynamic_cast. This is pretty crappy question - a slightly better one might be "How is dynamic_cast implemented?" but really if asked either at an interview I'd have to wonder about the nous of the interviewer. Being a good, or even a great, C++ programmer does not depend on knowing nitpicking implementation details like this, but these are of course easy questions for second-raters to ask.



回答3:

Check the typeid() function.



回答4:

You can access vpointer and even you can call any virtual method in class through vpointer. But remember this is EVIL.

Example :

class A
{
public:
    void f1()
    {
        cout<<"bbb"<<endl;;
    }
    virtual void f2()
    {
        cout<<"ccc"<<endl;;
    }
    virtual void f3()
    {
        cout<<"ddd"<<endl;;
    }
};

and call in main

A a;

typedef void (__thiscall* foo)();
(*(foo)((void**)(((void**)(&a))[0]))[1])();

It will access vpointer and then will go by index and will execute the second method in vTable which is f3().

Also note to use RTTI as already suggested.



标签: c++ vtable