Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/261.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 虚拟和覆盖在幕后做什么_C#_Virtual_Overriding - Fatal编程技术网

C# 虚拟和覆盖在幕后做什么

C# 虚拟和覆盖在幕后做什么,c#,virtual,overriding,C#,Virtual,Overriding,我刚开始了解虚拟和覆盖的用途(我找不到这么长时间的用途)。 现在我在工厂模式中使用它们。所以我的问题是虚拟和覆盖在幕后做什么?我愿意深入研究IL和机器代码方面的内容。我不能给你任何关于如何在IL中实现的见解,但基本理论很简单 当编译器看到一个virtual方法声明时,它不会将该方法附加到类,而是将其添加到该类的vtable(虚拟方法表),该类包含指向函数的指针 现在,由于vtable是类的一部分,它被其子类继承,因此虚拟方法也被继承。现在是覆盖位。当编译器在方法声明中看到一个重写时,它会查找vt

我刚开始了解虚拟和覆盖的用途(我找不到这么长时间的用途)。
现在我在工厂模式中使用它们。所以我的问题是虚拟和覆盖在幕后做什么?我愿意深入研究IL和机器代码方面的内容。

我不能给你任何关于如何在IL中实现的见解,但基本理论很简单

当编译器看到一个virtual方法声明时,它不会将该方法附加到类,而是将其添加到该类的
vtable
(虚拟方法表),该类包含指向函数的指针

现在,由于
vtable
是类的一部分,它被其子类继承,因此虚拟方法也被继承。现在是覆盖位。当编译器在方法声明中看到一个重写时,它会查找
vtable
,找到要重写的方法并更改函数指针,使其指向新定义

因此,您既可以从父类继承方法,也可以在子类中更改它们的定义


有关更多信息,请参阅上的Wikipedia文章。

您无需进入IL-
virtual
override
包含一个众所周知的面向对象概念,称为。实际上,当访问多态方法或属性时,仅在运行时确定实际应用哪个方法/属性。基本上,在引擎盖下,正确的方法(在属性的情况下,它也是一种方法)是通过访问虚拟方法表来确定的。虚拟方法表是一个查找表,用于根据运行时类型查找正确的方法。

如果您对IL感兴趣,请使用ildasm.exe查看编译程序(DLL或exe)。您将看到,您标记为“virtual”的方法在IL中只是标记为“virtual”

魔法发生在运行时。CLR构建了一个“方法分派表”(或“虚拟方法表”),用于在内存中定位类的方法。为了允许多态性,即根据运行时类型,相同的方法名称表示不同的内容,需要对虚拟方法进行一些额外的查找。(可以说它们被称为“虚拟”方法,正是因为它们是“凭借”它们所操作的对象而被选择的——但请参见@Pavel的评论。)这样说:

虚拟方法调用非常有用 就像一个普通的电话,除了它 必须在以下位置查找呼叫目标: 基于“this”对象的运行时


这些是基础。如果您真的想更进一步,Don Box是一个很好的读物。

是否vtable中的方法实际上是链接的而不是重写的?我的目标是从override方法中我们可以用base调用override方法。我认为这个链是由继承隐含的。当您调用基方法时,实际上是在查找由基类定义的虚拟方法的定义并调用该定义。实际上,您可以查找基类的vtable并使用它。这就是为什么无论如何都需要使用base调用它,以便编译器知道在哪里查找。不,使用
base.Foo()
不涉及任何进一步的vtable查找。为什么会这样-类总是知道它的基类,所以它知道在编译时在基类调用中调用哪个方法。所以只有在基类中声明了virtual,继承的类重写才会被调用,对吗?因为编译器在编译时根本不知道继承的类存在。“当编译器在方法声明中看到重写”这句话是在运行时发生的,那么这是怎么发生的呢?忘记上面的第二个问题,我从@harpoThat的
virtual
有趣的词源中得到了答案,但我想知道这是否是一个回顾性的解释(就像VB的
Dim
最近被解释为
Declare In Memory
——最初它来自
DIMension
,只用于数组),或者是真实的东西;如果是后者,你有什么参考资料吗?我知道这个确切意义上的
virtual
首先出现在最早的OO语言Simula-67中。但我不记得在语言参考资料中看到过对关键字的解释……好吧,所以我有点冒险了……但我觉得很安全。请声明-记忆对我来说是新的——我只知道它是旧的数组标注关键字。无论如何,很高兴听到一位语言学家的消息。我相信我找到了。“虚拟”是“虚拟数量”的简写;他们之所以这样称呼它,是因为他们最初设想了一种主要用于属性的机制。哇,这是一项很好的研究。坦率地说,我觉得这本书目前相当不透明,但我想我理解你的解释。这听起来有点像Dim扩展其声明能力以应用于broade的方式r概念(其中“尺寸标注”不适用)。同时,虚拟函数捕获到的不仅仅是虚拟属性。.NET直到版本2.0才添加虚拟属性