在c#中实际使用虚函数
c#中虚函数的实际用法是什么?
所以基本上,如果在你的祖先类中你想要某种方法的某种行为。 如果你的后代使用相同的方法,但有不同的实现,你可以覆盖它,如果它有一个虚拟关键字。
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':由于未标记为“virtual”,“abstract”或“override”,因此无法覆盖继承的成员'function2'
如果你不使用覆盖你会得到CS0108的警告'desc.Method()'隐藏了继承的成员'base.Method()'如果隐藏的目的是使用新的关键字。
为了解决这个问题,将new
关键字放在您隐藏的方法前面。
例如
new public double Area()
{
return 2*pi*x*x + 2*pi*x*y;
}
..是否必须重写派生类中的虚方法?
不,如果你不覆盖该方法,后代类将使用它继承的方法。
理解虚拟函数的实际用法的关键是要记住,某个类的对象可以被赋予来自第一个对象的类的另一个类的对象。
例如:
class Animal {
public void eat() {...}
}
class FlyingAnimal : Animal {
public void eat() {...}
}
Animal a = new FlyingAnimal();
Animal
类有一个函数eat()
,它通常描述动物应该如何吃(例如将物体放入口中并吞下)。
然而, FlyingAnimal
类应该定义一个新的eat()
方法,因为飞行动物有特定的饮食方式。
这样说到这里想到的问题是:当我声明的变量a
类的Animal
和asigned这类型的新对象FlyingAnimal
,你会a.eat()
吗? 这两种方法中的哪一种被称为?
这里的答案是:因为a
是Animal
类型,它会调用Animal
的方法。 编译器是愚蠢的,不知道你打算将另一个类的对象分配给a
变量。
这里是virtual
关键字的作用:如果你将方法声明为virtual void eat() {...}
,你基本上是告诉编译器“小心我在这里做了一些聪明的事情,你不能处理,因为你“不那么聪明”。 所以编译器不会尝试将调用a.eat()
链接到两个方法中的任何一个,而是告诉系统在运行时执行它!
因此,只有在代码执行时,系统会看a
的内容在其声明的类型不是类型和执行FlyingAnimal
的方法。
你可能会问:为什么我会这样做? 为什么不从一开始就说正确FlyingAnimal a = new FlyingAnimal()
?
其原因是,例如,你可能有许多来自Animal
派生类: FlyingAnimal
, SwimmingAnimal
, BigAnimal
, WhiteDog
等等。在某一时刻,你想定义一个包含许多Animal
的世界,所以你说:
Animal[] happy_friends = new Animal[100];
我们有一个有100个快乐动物的世界。 你在某个时候初始化它们:
...
happy_friends[2] = new AngryFish();
...
happy_friends[10] = new LoudSnake();
...
而在一天结束时,你希望每个人在睡觉之前吃东西。 所以你想说:
for (int i=0; i<100; i++) {
happy_friends[i].eat();
}
正如你所看到的,每只动物都有自己的吃法。 只有使用虚拟功能,才能实现此功能。 否则,每个人都会被迫以完全相同的方式“吃”,正如Animal
类中最常用的eat
功能所描述的那样。
编辑:这种行为实际上是默认的普通的高级语言,如Java。
像其他语言一样..当你想要多态。 这有很多的用法。 例如,您想要抽象从控制台或文件或其他设备读取输入的方式。 你可以有一个通用的阅读器接口,然后是使用虚拟函数的多个具体实现。
链接地址: http://www.djcxy.com/p/38117.html上一篇: Practical usage of virtual functions in c#
下一篇: How to have a default method while still be able to override it?