繁体   English   中英

void(** vt)()= *(void(***)())ptr; c ++中虚拟表的辅助变量

[英]void (**vt)() = *(void (***)())ptr; a helper variable for virtual table in c++

我在以下链接中找到了这种技术: http//www.codeproject.com/Tips/90875/Displaying-vtable-when-debugging

在那里,他使用一个辅助变量

void (**vt)() = *(void (***)())ptr;

帮助显示虚拟功能表。

但如果我把它改成

void (**vt)() = (void (**)())ptr;

它不像以前的那样工作。

有人可以帮我解释一下这里有什么魔法吗?

我们为了清晰起见介绍一个typedef。

typedef void (**thing)();

然后第一个代码是

thing vt = *(thing*) ptr;

第二个

thing vt = (thing) ptr;

也就是说,第一个说“将ptr视为指向某个东西的指针,然后给我指出的东西”,第二个“将ptr视为一个东西”。
差异应该是显而易见的。

在所有工作的原因是非常具体的,以双方的Visual C ++编译器和Visual Studio调试器。

如果调试器不知道对象到底是什么类型,它会显示它所知道的内容,即它是基类的实例,它只知道基类的vtable有多少条目。

(你在这里省略了一个关键部分,即在观察窗口中向项目添加预期数量的表项。这使得调试器将该内存显示为一个包含所述元素的数组。)

因此,技巧包括为vtable创建一个名称,并告诉调试器从表中显示多少元素。

许多C ++实现中的虚拟表指针是对象的第一个sizeof(void (**)())字节。 当您取消引用该指针时,您将获得真实虚拟表的起始地址。 这就是工作代码的含义。

cdecl程序在这里可能有点帮助:

cdecl> explain void (***foo)()
declare foo as pointer to pointer to pointer to function returning void
cdecl> explain void (**foo)()
declare foo as pointer to pointer to function returning void

第一个代码将指向对象的指针转换为正确的可解除引用的指针( 指向指向函数的指针的指针void (***)() ),然后取消引用它以获取虚拟表的起始地址,该表是类型void (**)()指向函数的指针 ),它指向虚拟表的开头,类型为void (*[])()指向函数的指针数组 )。

第二个只是将指向对象的指针强制转换为指向返回void的函数的指针; 存储在变量vt中的地址只是对象的地址。

class Object {
public:
    virtual void foo() {};
};

Object x;

// is approximately equivalent to 

struct Object {
    void (**_vtable)();
};

void _Object_foo(Object this) {
}

// this does not really compile, however,
// because a pointer mismatch
void (*_vtable_for_Object[])() = {
    _Object_foo
};

Object y;
y._vtable = _vtable_for_Object;

因此有了

Object *ptr = new Object();
// x now points to a block of memory,
// whose first bytes are void (**_vtable)()

// then
void (**vt)() = *(void (***)())ptr;

// is equivalent in our analogy to
void (**vt)() = ptr->_vtable;

// except that the C++ does not allow you to
// access the virtual table directly without
// the trickery of the former

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM