虚函数在C#语言中的实际应用

Practical usage of virtual functions in c#

虚拟函数在C中的实际用法是什么?


所以基本上,如果你想在你的祖先类A的某些行为的方法。如果您使用的相同和方法,但有不同的实现,你可以覆盖它,如果它有一个虚拟的关键字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
using System;
class TestClass
{
   public class Dimensions
   {
      public const double pi = Math.PI;
      protected double x, y;
      public Dimensions()
      {
      }
      public Dimensions (double x, double y)
      {
         this.x = x;
         this.y = y;
      }

      public virtual double Area()
      {
         return x*y;
      }
   }

   public class Circle: Dimensions
   {
      public Circle(double r): base(r, 0)
      {
      }

      public override double Area()
      {
         return pi * x * x;
      }
   }

   class Sphere: Dimensions
   {
      public Sphere(double r): base(r, 0)
      {
      }

      public override double Area()
      {
         return 4 * pi * x * x;
      }
   }

   class Cylinder: Dimensions
   {
      public Cylinder(double r, double h): base(r, h)
      {
      }

      public override double Area()
      {
         return 2*pi*x*x + 2*pi*x*y;
      }
   }

   public static void Main()  
   {
      double r = 3.0, h = 5.0;
      Dimensions c = new Circle(r);
      Dimensions s = new Sphere(r);
      Dimensions l = new Cylinder(r, h);
      // Display results:
      Console.WriteLine("Area of Circle   = {0:F2}", c.Area());
      Console.WriteLine("Area of Sphere   = {0:F2}", s.Area());
      Console.WriteLine("Area of Cylinder = {0:F2}", l.Area());
   }
}

编辑评论:问题如果我不使用虚拟库类的关键字,将它的工作?

如果你使用关键字在您的类override和它不工作。你会产生编译错误:无法cs0506’function1重写继承的成员2’,因为这是不显著的"虚拟"、"摘要"或"覆盖"

如果你不使用你得到的覆盖cs0108预警"()desc.method隐藏继承的成员base.method()使用新的关键字,如果在隐藏什么。

要在这把new关键字在前面你的隐藏方法。

例如

1
2
3
4
  new public double Area()
  {
     return 2*pi*x*x + 2*pi*x*y;
  }

它是一个重写的预订源性类的虚拟方法。不,如果你不重写的方法和类的使用方法,它是inheriting想。


了解虚拟函数的实际用法的关键是记住,可以为某个类的对象分配从第一个对象的类派生的类的另一个对象。

例如。:

1
2
3
4
5
6
7
8
9
class Animal {
   public void eat() {...}
}

class FlyingAnimal : Animal {
   public void eat() {...}
}

Animal a = new FlyingAnimal();

Animal类具有eat()的功能,该功能通常描述动物应如何进食(例如,将物体放入口中并吞咽)。

然而,FlyingAnimal类应该定义一种新的eat()方法,因为飞行动物有一种特殊的进食方式。

因此,我想到的问题是:在我声明了Animal型的变量a并将其作为FlyingAnimal型的新对象之后,a.eat()会做什么?调用这两个方法中的哪一个?

这里的答案是:因为aAnimal类型,所以它将调用Animal的方法。编译器很笨,不知道要将另一个类的对象赋给a变量。

下面是virtual关键字的作用:如果您将该方法声明为virtual void eat() {...},则基本上是在告诉编译器"请注意,我在这里做了一些您无法处理的聪明事情,因为您不够聪明"。因此编译器不会试图将调用a.eat()链接到这两个方法中的任何一个,而是告诉系统在运行时执行该操作!

因此,只有在代码执行时,系统才会查看a的内容类型,而不是声明的类型,并执行FlyingAnimal的方法。

你可能会想:我到底为什么要这么做?为什么不从一开始就直接说出来呢?

原因是,例如,您可能有许多来自Animal的派生类:FlyingAnimalSwimmingAnimalBigAnimalWhiteDog等,并且在某一点上,您希望定义一个包含多个Animal的世界,因此您可以说:

1
Animal[] happy_friends = new Animal[100];

我们有一个拥有100只快乐动物的世界。您可以在某个时刻初始化它们:

1
2
3
4
5
...
happy_friends[2] = new AngryFish();
...
happy_friends[10] = new LoudSnake();
...

在一天结束的时候,你想让每个人在睡觉前吃东西。所以你想说:

1
2
3
for (int i=0; i<100; i++) {
   happy_friends[i].eat();
}

所以你可以看到,每种动物都有自己的进食方法。只有使用虚拟函数才能实现此功能。否则,每个人都将被迫以完全相同的方式"吃"东西:正如Animal类中最一般的eat函数所描述的那样。

编辑:这种行为实际上是常见的高级语言(如Java)中的默认值。


像其他任何语言,你想..when多态性。有吨的使用。例如,你想用的方式读取控制台输入A或A文件或其他一些设备。你可以有一个通用的接口实现的多阅读器后混凝土使用虚拟函数。


例如,代理的方法。IU overwriting方法在运行时。例如,NHibernate的使用本支持懒惰加载。


这允许实现后期绑定,而不是在运行时确定的意思是在编译时将invoked对象的成员。湖的维基百科。


虚拟成员基本上允许你表达类A中,有一个方法衍生的CAN和方法相同的签名作为其基地和基地的类,类的衍生类要调用的方法。

一个基本的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class Shape
{
    // A few example members
    public int X { get; private set; }
    public int Y { get; private set; }
    public int Height { get; set; }
    public int Width { get; set; }

    // Virtual method
    public virtual void Draw()
    {
        Console.WriteLine("Performing base class drawing tasks");
    }
}

class Circle : Shape
{
    public override void Draw()
    {
        // Code to draw a circle...
        Console.WriteLine("Drawing a circle");
        base.Draw();
    }
}
class Rectangle : Shape
{
    public override void Draw()
    {
        // Code to draw a rectangle...
        Console.WriteLine("Drawing a rectangle");
        base.Draw();
    }
}
class Triangle : Shape
{
    public override void Draw()
    {
        // Code to draw a triangle...
        Console.WriteLine("Drawing a triangle");
        base.Draw();
    }
}


在C语言中使用虚拟函数#

虚函数主要用于重写具有相同签名的派生类中的基类方法。

当派生类继承基类时,派生类的对象是对派生类或基类的引用。

虚拟函数被编译器延迟解析(即运行时绑定)

virtual在基类中,根据所引用对象的实际类型调用最派生类的函数实现,而不考虑指针或引用的声明类型。如果不是virtual,则解析方法early,并根据指针或引用的声明类型选择调用的函数。


例如你有一个基地和一类参数设置衍生类。你想可以执行相同的操作在所有可能的数组是从商店类衍生参数。

没有问题的方法将一些基本的虚拟实现,添加到它在params类和衍生类覆盖。现在你可以遍历数组的方法和呼叫通过参考正确的想法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Params {
public:
   virtual void Manipulate() { //basic impl here }
}

class DerivedParams1 : public Params {
public:
   override void Manipulate() {
      base.Manipulate();
      // other statements here
   }
};

// more derived classes can do the same

void ManipulateAll( Params[] params )
{
    for( int i = 0; i < params.Length; i++ ) {
       params[i].Manipulate();
    }
 }

从这里:

In object-oriented programming, a
virtual function or virtual method is
a function or method whose behavior
can be overridden within an inheriting
class by a function with the same
signature.