如何使用vtable来确定类类型

时间:2010-06-09 14:28:05

标签: c++ vtable

我最近正在接受采访,其中C / C ++是主要语言,在一个问题中我被告知可以使用vtable来确定基本指针实际存储的层次结构中的哪个类。

所以,例如,如果你有

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

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

并实例化A * pFoo = new B(),是否确实可以使用vtable来确定pFoo是否包含指向A或B实例的指针?

4 个答案:

答案 0 :(得分:11)

这显然取决于实现,但在大多数实现中,类AB的对象的内存中表示将以指向vtable的指针开始。您可以查看此vtable指针,将其与您知道属于类AB的对象的vtable指针进行比较,并以此方式确定对象的类。

为了说明(当然这不是好的风格):

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");

重要说明:这只是 说明了大多数实现的工作原理;除了依赖于实现之外,这种技术在存在多重继承时会崩溃。您应该从不在生产代码中执行此类操作;改为使用RTTI。

答案 1 :(得分:3)

是的,很有可能 - 使用dynamic_cast。这是一个非常糟糕的问题 - 稍微好一点的可能是“如何实现dynamic_cast?”但是如果在面试中被问到,我真的不得不怀疑面试官的情况。作为一个优秀的,甚至是伟大的C ++程序员,并不依赖于知道这样的挑剔实现细节,但这些对于第二个评估者来说当然是一个简单的问题。

答案 2 :(得分:2)

答案 3 :(得分:1)

您可以访问vpointer,甚至可以通过vpointer调用类中的任何虚拟方法。 但请记住,这是邪恶的。

示例:

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

并在主要

中致电
A a;

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

它将访问vpointer,然后按索引进行,并将在vTable中执行第二个方法,即f3()。

还要注意使用已建议的RTTI。