【发布时间】:2010-11-21 13:43:19
【问题描述】:
我刚开始了解 Virtual 和 Override 是用于(我找不到这么久的用途)。 现在我在工厂模式中使用它们。所以我的问题是 Virtual 和 Override 在幕后做了什么?我愿意研究 IL 和机器代码。
【问题讨论】:
标签: c# virtual overriding
我刚开始了解 Virtual 和 Override 是用于(我找不到这么久的用途)。 现在我在工厂模式中使用它们。所以我的问题是 Virtual 和 Override 在幕后做了什么?我愿意研究 IL 和机器代码。
【问题讨论】:
标签: c# virtual overriding
我无法为您提供关于它是如何在 IL 中完成的任何见解,但基本理论很简单。
当编译器看到 virtual 方法声明时,它不会将该方法附加到类,而是将其添加到所谓的 vtable(虚拟方法Table) 用于该类,其中包含指向函数的指针。
现在由于 vtable 是类的一部分,它被其子类继承,因此虚方法也被继承。现在是覆盖位。当编译器在方法声明中看到 override 时,它会查找 vtable,找到要覆盖的方法并更改函数指针以使其指向新的定义。
因此,您既可以继承父类的方法,也可以在子类中更改它们的定义。
有关更多信息,请参阅Virtual Method Table 上的维基百科文章。
【讨论】:
base.Foo() 不涉及任何进一步的 vtable 查找。为什么会这样 - 类总是知道它的基类,所以它确切地知道在编译时在基调用中调用哪个方法。
您无需进入 IL - virtual 和 override 包含一个众所周知的面向对象概念,称为 polymorphism。实际上,当访问多态方法或属性时,实际应用的方法/属性仅在运行时确定。在引擎盖下,基本上,正确的方法(在属性的情况下,它也是一种方法)是通过访问一个虚拟方法表来确定的 - 一个用于查找正确方法的查找表,基于运行时类型。
【讨论】:
如果您对 IL 感兴趣,请使用 ildasm.exe 查看已编译的程序(DLL 或 EXE)。您会看到标记为“虚拟”的方法在 IL 中只是简单地标记为“虚拟”。
奇迹发生在运行时。 CLR 构建一个“方法分派表”(或“虚拟方法表”),用于在内存中定位类的方法。为了允许多态性,其中相同的方法名称根据运行时类型表示不同的东西,虚拟方法需要一些额外的查找。 (人们可以说它们被称为“虚拟”方法正是因为它们是“凭借”它们所操作的内容而被选中的——但请参阅@Pavel 的 cmets。)Joe Duffy 这样说:
虚方法调用非常多 像一个普通的电话,除了它 必须查找调用的目标 基于“this”对象的运行时。
这些是基础。如果您真的想更进一步,Don Box 是一本不错的读物。
【讨论】:
virtual 的一个有趣的词源,但我会很好奇这是否是一个回顾性解释(就像 VB 的 Dim 被解释为 Declare In Memory 这些天 - 最初它来自 @ 987654326@,仅用于数组),或者真实的东西;如果是后者,你有什么参考资料吗?我知道virtual 在这个精确意义上首先出现在第一个面向对象语言 Simula-67 中。但我不记得在语言参考中看到该关键字的解释......