如何重载是编译时间和覆盖是运行时?

乡亲

我遇到了许多用于理解多态性的线程(编译时和运行时)。 我很惊讶地看到一些程序员声称重载是Runtime而Overriding是编译时间的链接。

我想从这里知道的是:

  1. 运行时多态性与REAL TIME示例和小代码以及我们应该使用的场景。
  2. 编译时间多态性与REAL TIME示例和小代码以及何时使用。

因为我阅读了许多理论定义,但我对理解这一定义并不满意。

另外,我想一想,我也觉得,重载应该是运行时因为,因为我有一个计算Area的方法,在运行时只根据我传递的参数决定调用哪个重载方法(如果我只通过则说一个参数,它应该触发Square,如果参数是2,它应该触发Rectangle)….所以不是它我可以声称它的运行时? 它的编译时间如何? (大多数人说理论上,重载是编译时间,但他们甚至没有给出一个正确的实时例子……很少有人声称它的运行时间)….

另外,我觉得压倒一切是编译时间,因为在编写代码和编译时,确保使用虚拟关键字并在派生类中覆盖该方法,否则会给出编译时错误。 所以我感觉它的编译时间,就像我在一个线程中看到的那样…..但大多数线程声称它的运行时:D

我很困惑:(这个问题是我的问题1和2的补充。请帮助一个实时的例子..因为我已经知道理论定义…. 🙁

谢谢….

在重载的情况下,您使用静态(编译时)多态,因为编译器确切知道您正在调用哪个方法。 例如:

public static class test { static void Main(string[] args) { Foo(); Foo("test"); } public static void Foo() { Console.WriteLine("No message supplied"); } public static void Foo(string message) { Console.WriteLine(message); } } 

在这种情况下,编译器根据参数的数量/类型确切地知道我们正在调用哪个Foo()方法。

覆盖是动态(运行时)多态的一个例子。 这是因为编译器不一定知道在编译时传递了什么类型的对象。 假设您在库中有以下类:

 public static class MessagePrinter { public static void PrintMessage(IMessage message) { Console.WriteLine(message.GetMessage()); } } public interface IMessage { public string GetMessage(); } public class XMLMessage : IMessage { public string GetMessage() { return "This is an XML Message"; } } public class SOAPMessage : IMessage { public string GetMessage() { return "This is a SOAP Message"; } } 

在编译时,您不知道该函数的调用者是否传入XMLMessage,SOAPMessage或可能在其他地方定义的其他类型的IMessage。 调用PrintMessage()函数时,它根据传入的IMessage类型确定在运行时使用哪个版本的GetMessage()。

阅读: 多态性(C#编程指南)

类似的答案: 编译时间和运行时间多态性

那么,有两种类型的多态性如下所述:

  • 静态多态性(早期绑定)
  • 动态多态性(后期绑定)

静态多态性(早期结合):

静态多态性也称为早期绑定和编译时间多态性。 方法重载和运算符重载是相同的示例。

它被称为Early Binding,因为编译器知道具有相同名称的函数,并且在编译时也需要调用哪个重载函数。

例如:

 public class Test { public Test() { } public int add(int no1, int no2) { } public int add(int no1, int no2, int no3) { } } class Program { static void Main(string[] args) { Test tst = new Test(); int sum = tst.add(10, 20); // here in above statement compiler is aware at compile time that need to call function add(int no1, int no2), hence it is called early binding and it is fixed so called static binding. } } 

动态多态性(后期绑定):

 public class Animal { public virtual void MakeSound() { Console.WriteLine("Animal sound"); } } public class Dog:Animal { public override void MakeSound() { Console.WriteLine("Dog sound"); } } class Program { static void Main(string[] args) { Animal an = new Dog(); an.MakeSound(); Console.ReadLine(); } } 

与上面的代码一样,任何其他对虚方法的调用,都会被编译成callvirt IL指令。 这意味着被调用的实际方法是在运行时确定的(除非JIT可以优化某些特殊情况),但编译器检查该方法是否存在,它选择了最合适的重载(如果有的话)并且它有保证函数指针将存在于类型的vtable中定义良好的位置(即使这是一个实现细节)。 解析虚拟调用的过程非常快(您只需要取消引用一些指针),因此它没有太大的区别。

 public class Animal { public virtual void MakeSound() { Console.WriteLine("Animal sound"); } } public class Dog:Animal { public override void MakeSound() { Console.WriteLine("Dog sound"); } } class Program { static void Main(string[] args) { Animal an = new Dog(); an.MakeSound(); Console.ReadLine(); } } 

这是动态多态,因为在运行时决定哪个版本的MakeSound将被调用父类或子类,因为子类可能不会覆盖父函数或者可能会覆盖它但是所有这些都是在运行时决定的,哪个版本叫做 ….