English 中文(简体)
在下面的示例中,`vcall {0,{flat}}`代表什么?
原标题:
  • 时间:2009-03-13 17:22:15
  •  标签:

我不确定这个问题是否已经得到解决。我正在检查Stack overflow函数中的一个,并产生了这个疑问。

让我们先检查代码:

#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 值时,发现以下数值:

在pMC2上调用p.Process("Func");

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

在p.Process(pMC2, "Func2")中调用

memFunc 0x0040118b MyClass::Func2(void)

I didn t understand thunk and flat in "[thunk]:`vcall {0,{flat}}" ? Can anyone help me to understand the internals here ?

最佳回答

在维基百科上,有一个相当详细的解释,解释了thunk的含义。

将此翻译成中文:http://en.wikipedia.org/wiki/Thunk

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

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

  • 0: Offset in the vtable
  • {flat}: inheritance hierarchy is flat not multiple
问题回答

不同的符号表示是因为成员函数指针需要能够处理各种虚拟和非虚拟成员函数(尽管不是静态成员函数),并且需要能够处理属于该类的成员函数通过各种形式的继承(公有、私有和/或虚拟)。

我看过的最好的文章,解释了成员函数指针的工作原理,是Doug Clugston在The Code Project上的“成员函数指针和最快速的C++委托”。

你可能会猜测,“成员函数指针”和普通函数指针一样,只持有一个代码指针。但你会错。在几乎所有的编译器中,成员函数指针比函数指针更大。最令人不可思议的是,在Visual C++中,成员函数指针的长度可能是4、8、12或16个字节,这取决于它所关联的类的性质,以及使用的编译器设置!成员函数指针比你想象的更复杂。

这并不容易阅读,但是非常有价值——这些信息难以在其他地方找到。认真阅读那篇文章可能会让你深入了解调试器在向你展示例如……等内容时真正想表达什么。

[thunk]:`vcall {0,{flat}} 

JaredPar的答案可能基本上很中肯 - Clugston的文章将为您提供故事的其余部分。





相关问题
热门标签