如何使用vtable来确定类类型

发布于 2024-09-05 03:16:35 字数 428 浏览 7 评论 0原文

我最近接受了一个职位的面试,其中 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 实例的指针?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

Hello爱情风 2024-09-12 03:16:35

这显然取决于实现,但在大多数实现中,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 代替。

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.

半城柳色半声笛 2024-09-12 03:16:35

是的,这是很有可能的——使用dynamic_cast。这是一个相当蹩脚的问题 - 一个稍微好一点的问题可能是“dynamic_cast 是如何实现的?”但实际上,如果在面试中被问到,我不得不怀疑面试官的理智。作为一个优秀的、甚至是伟大的 C++ 程序员并不依赖于了解像这样挑剔的实现细节,但这些对于二流的人来说当然是很容易问的问题。

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.

怀中猫帐中妖 2024-09-12 03:16:35

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

示例:

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

在 main 中调用

A a;

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

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

另请注意按照已经建议的方式使用 RTTI。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文