How to use the vtable to determine class type

2019-04-26 19:06发布

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?

标签: c++ vtable
4条回答
别忘想泡老子
2楼-- · 2019-04-26 19:30
淡お忘
3楼-- · 2019-04-26 19:33

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.

查看更多
虎瘦雄心在
4楼-- · 2019-04-26 19:41

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<<"ffffd"<<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.

查看更多
Anthone
5楼-- · 2019-04-26 19:46

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.

查看更多
登录 后发表回答