【问题标题】:Virtual method tables虚拟方法表
【发布时间】:2011-01-25 16:32:51
【问题描述】:

在讨论密封类时,经常提到“虚拟函数表”这个术语。这究竟是什么?不久前我读到了一个方法表(我也不记得这个目的的目的),并且在此处进行谷歌/搜索会显示与 C++ 相关的结果。

谢谢

【问题讨论】:

    标签: c# .net virtual vtable


    【解决方案1】:

    “虚拟函数表”或“虚拟方法表”是每个类拥有的方法指针列表。它包含指向类中虚方法的指针。

    类的每个实例都有一个指向表的指针,当您从实例调用虚方法时会使用该指针。这是因为对虚方法的调用应该调用与实际对象的类相关联的方法,而不是对象引用的类。

    例如,如果您有一个对字符串的对象引用:

    object obj = "asdf";
    

    并调用虚方法ToString:

    string text = obj.ToString();
    

    它将使用 String.ToString 方法,而不是 Object.ToString 方法。它使用的是String类的虚方法表(字符串实例中的指针所指向的),而不是Object类的虚方法表。

    【讨论】:

    • 我是否正确理解“方法表”是针对任何类型创建的。所以该值类型也有一个“方法表”。还有一个问题是如何知道一个类型有一个“方法表”? “方法表”是否存储或引用在类型对象中?但是值类型没有类型对象指针。 :/ 这是一个相关的问题:stackoverflow.com/questions/35185528/…
    • @Spirit:是的,每种类型都有一个方法表(至少在某个阶段以某种形式)。由于对值类型的调用是非虚拟的,因此确切的方法是在编译时确定的,因此它们不需要虚拟方法表,因为它们只需要存在于可执行文件中以用于反射目的。我不知道方法表实际存储在哪里,这将取决于实现,因此您可以查看框架源代码(但是实现的那部分可能不公开)。
    • 谢谢。你的回答很清楚。终于找到了类似的SO讨论:stackoverflow.com/questions/926352/…
    • string text = obj.ToString(); 的 IL 代码是:callvirt instance string [mscorlib]System.Object::ToString(),所以看起来它实际上并没有使用 String.ToString。
    • @HeyJude obj的编译时类型是object。由于 ToString 是虚拟的并且 object 是引用类型,因此调用将使用 callvirt 关键字进行。 Callvirt 会在查看 obj 实例的虚方法表后调用 String.ToString()。看起来它不会调用 String.ToString,但实际上会调用。
    【解决方案2】:

    C# 虚函数表的工作原理与 C++ 表基本相同,因此任何描述 C++ 虚函数表如何工作的资源都应该可以很好地帮助您使用 C# 表。

    比如Wikipedia's description就不错了。

    【讨论】:

    • 通常,答案应该是自包含的,并且不链接到任何第三方文本......尤其是不要链接到维基百科的文章......
    【解决方案3】:

    Virtual Function Table(通常称为 vtable)的定义在 C# 和 C++ 中是相同的。它是运行时内部使用的一个查找表,用于实现抽象/虚拟/覆盖方法的多态行为。

    简单来说,你可以想象一个带有虚方法 A 的基类将有一个包含方法 A 的 vtable。当派生类覆盖methodA时,methodA的vtable继承自父类,但现在将指向派生类中的methodA而不是父类。

    【讨论】:

      猜你喜欢
      • 2013-10-23
      • 2013-05-01
      • 1970-01-01
      • 2011-09-30
      • 2015-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多