【问题标题】:What does `vcall'{0,{flat}}' signify in below example?`vcall'{0,{flat}}' 在下面的示例中表示什么?
【发布时间】:2010-10-13 05:24:32
【问题描述】:

我不确定问题是否已经解决。我正在检查堆栈溢出功能之一,并得到了这个疑问。

让我们先检查代码:

#include <string>
#include <map>
#include <iostream.h>

class MyClass
{
public:

    virtual  int Func()
    {
        return 0;
    }

    int Func2()
    {
        return 0;
    }

};

class MyClass2 :  public MyClass
{
public:

    int Func( )
    {
        return 1;
    }

    int Func2()
    {
        return 1;
    }

};

class Processor
{
 private:
      typedef int (MyClass::*MemFuncGetter)();
      static std::map<std::string, MemFuncGetter> descrToFuncMap;

 public:
        static void Initialize();
        void Process(MyClass* m, const std::string&);

};

std::map<std::string, Processor::MemFuncGetter> Processor::descrToFuncMap;
void Processor::Initialize()
{

     descrToFuncMap["Func"]=&MyClass::Func;
     descrToFuncMap["Func2"]=&MyClass::Func2;
};

void Processor::Process(MyClass* ms, const std::string& key)
{
    std::map<std::string, MemFuncGetter>::iterator found = descrToFuncMap.find(key);
     if(found != descrToFuncMap.end())
     {
        MemFuncGetter memFunc = found->second;
        int dResult = (ms->*memFunc)();
        cout << "Result is : "<< dResult <<endl;
      }
 }


int main(int argc, char* argv[])
{
    Processor::Initialize();
    Processor p;

    MyClass *pMC2 = new MyClass2;
    p.Process(pMC2, "Func");
    p.Process(pMC2, "Func2");

    delete pMC2;
    pMC2 = NULL;

    return 0;
}

在这个例子中,结果如预期:

Result is : 1
Result is : 0

但是,当我使用 VC 6 调试器进行调试并观察 Processor::Process 中 memFunc 的值时,发现以下值:

在 p.Process(pMC2, "Func");打电话

memFunc 0x004011bd [thunk]:`vcall'{0,{flat}}' 

在 p.Process(pMC2, "Func2");打电话

memFunc 0x0040118b MyClass::Func2(void)

我不明白 "[thunk]:`vcall'{0,{flat}}" 中的 thunkflat 吗? 谁能帮我理解这里的内部原理?

【问题讨论】:

    标签: c++ visual-c++


    【解决方案1】:

    维基百科上对 thunk 的含义有相当详尽的解释

    http://en.wikipedia.org/wiki/Thunk

    thunk 的要点是在运行时访问 C++ 虚拟表的机制。它被设置为为对象的运行时类型调用适当的虚函数。

    至于 vcall{0,{flat}} 的含义,我不是 100% 确定的。我的 猜测 是它报告 thunk 访问该方法的值。

    • 0:vtable 中的偏移量
    • {flat}:继承层次是扁平的而不是多重的

    【讨论】:

    • 我不认为{flat} 表示继承层次结构。我做了一些多重继承测试,它总是{flat}。不知道它是干什么用的。
    【解决方案2】:

    不同的符号是因为成员函数指针需要能够处理各种虚拟和非虚拟成员函数(虽然不是静态成员函数),并且它需要能够以各种形式处理属于类的成员函数继承(公共、私有和/或虚拟)。

    我遇到的解释成员函数指针如何工作的最佳文章是 Doug Clugston 在 The Code Project 上的 "Member Function Pointers and the Fastest Possible C++ Delegates"

    您可能会猜到,“成员函数指针”与普通函数指针一样,只包含一个代码指针。你会错的。在几乎所有编译器上,成员函数指针都比函数指针大。最奇怪的是,在 Visual C++ 中,成员函数指针的长度可能是 4、8、12 或 16 个字节,具体取决于与其关联的类的性质,以及使用的编译器设置!成员函数指针比你想象的要复杂。

    阅读起来并不容易,但值得一读——这些信息在其他任何地方都很难找到。好好阅读那篇文章可能会让您深入了解调试器在向您显示诸如

    之类的内容时真正在说什么
    [thunk]:`vcall'{0,{flat}}'
    

    JaredPar's answer 可能非常符合要求 - Clugstons 的文章将为您提供故事的其余部分。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多