C# 虚拟函数

C# 虚拟函数,c#,C#,我真的不明白-我什么时候应该使用虚拟函数?如果有人能给我解释一下,我会很高兴的,谢谢。虚拟函数是子类可以重写的函数,如果它愿意的话 //父母 public virtual string someMethod() { return "someting"; } //在儿童时期 public override string someMethod() { return "someting else"; } 虚拟方法是成功

我真的不明白-我什么时候应该使用虚拟函数?如果有人能给我解释一下,我会很高兴的,谢谢。

虚拟函数是子类可以重写的函数,如果它愿意的话

//父母

    public virtual string someMethod()
    {
        return "someting";
    }
//在儿童时期

    public override string someMethod()
    {
        return "someting else";
    }

虚拟方法是成功的关键。标记为virtual的方法可以在派生类中重写,以更改或专门化类的行为

例如:

class Base
{
    public virtual void SayHello()
    {
        Console.WriteLine("Hello from Base");
    }
}

class Derived : Base
{
    public override void SayHello()
    {
        Console.WriteLine("Hello from Derived");
    }
}

static void Main()
{
    Base x = new Base();
    x.SayHello(); // Prints "Hello from Base"
    x = new Derived();
    x.SayHello(); // Prints "Hello from Derived"
}
请注意,您可以重新声明(而不是重写)非虚拟的方法,但在这种情况下,它不会参与多态性:

class Base
{
    public void SayHello() // Not virtual
    {
        Console.WriteLine("Hello from Base");
    }
}

class Derived : Base
{
    public new void SayHello() // Hides method from base class
    {
        Console.WriteLine("Hello from Derived");
    }
}

static void Main()
{
    Base x = new Base();
    x.SayHello(); // Prints "Hello from Base"
    x = new Derived();
    x.SayHello(); // Still prints "Hello from Base" because x is declared as Base
    Derived y = new Derived();
    y.SayHello(); // Prints "Hello from Derived" because y is declared as Derived
}

如果希望更改(重写)子类中函数的行为,则使用虚拟函数

class Order
{
    public virtual long GetOrderNumber { return nextOrderNumber; }
}

class ExpressOrder : Order
{
    public override long GetOrderNumber { return nextOrderNumber + 1000000; }
}

如果您已经设置了继承链,并且希望覆盖派生类中基类中定义的函数的默认实现,则只需要虚拟函数

经典的例子如下:

public class Animal
{
    public virtual void Speak()
    {
        Console.WriteLine("...");
    }
}

public class Dog : Animal
{
    public override void Speak()
    {
        Console.WriteLine("Bow-wow");
    }
}

public class Human : Animal
{
    public override void Speak()
    {
        Console.WriteLine("Hello, how are you?");
    }
}
Dog
Human
类都继承自基本的
Animal
类,因为它们都是动物类型。但是它们都以非常不同的方式说话,因此它们需要重写
speak
函数以提供自己独特的实现

在某些情况下,在设计自己的类时使用相同的模式可能是有益的,因为这样可以启用,这本质上就是不同的类共享一个公共接口,并且可以由代码进行类似的处理

但我将回应其他人在评论中的建议:正确地学习面向对象编程不是通过问几个堆栈溢出问题就能做到的。这是一个复杂的话题,也是一个值得作为开发人员投入时间学习的话题。我强烈建议你读一本关于面向对象编程的书(特别是一本为C语言编写的书)并仔细阅读这些例子。如果正确使用OOP,它是一个非常强大的工具,但如果设计不当,它肯定会成为一个障碍

给定一个基类:

class SomeBaseClass()
{
    public virtual string GetName()
    {
         return "SomeBaseClass";
    }
}
当您重写它时,您将继承该函数

class SomeDerivedClass() : SomeBaseClass
{
}
所以当你说:

SomeDerivedClass sdc = new SomeDerivedClass();
Console.WriteLine(sdc.GetName()); //outputs "SomeBaseClass"
GetName()
返回“SomeBaseClass”

但是,您可以覆盖它

class SomeDerivedClass()
{
    public override string GetName()
    {
         return "SomeDerivedClass";
    }
}

这里的
GetName()
现在将返回“SomeDerivedClass”

可能是通过一个示例最容易理解的,想象一下我们有如下代码

class Base{
public virtual string VirtualMethod(){
    return "base virtual";
}

public string NotVirtual(){
    return "base non virtual";
}
}

class Derived : Base{
  public override string VirtualMethod(){
        return "Derived overriden";
  }
  public new string NotVirtual(){
        return "new method defined in derived";
  }
}

}
如果您使用下面的代码

  Base b = new Base();
  Derived d = new Derived();
  Base b2 = d;

  Console.WriteLine(b.VirtualMethod());
  Console.WriteLine(d.VirtualMethod());
  Console.WriteLine(b2.VirtualMethod());

  Console.WriteLine(b.NotVirtual());
  Console.WriteLine(d.NotVirtual());
  Console.WriteLine(b2.NotVirtual());
值得注意的是,b2 a d是完全相同的对象

上述结果将是:

基本虚拟

派生重写

派生重写

基本非虚拟

派生类中定义的新方法

基本非虚拟

即使最后两行调用同一对象上的方法名NotVirtual。由于te变量声明为基本变量并派生,且方法不是虚拟的,因此声明的变量类型决定调用的方法,而如果方法是虚拟的,则对象的运行时类型是将调用的方法的决定因素

public abstract class Weapon
{
    public virtual abstract FireOnTarget();
}

public class Pistol : Weapon
{
    public override FireOnTarget()
    {
        LoadPowder();
        LoadBullet();
        CockIt();
        PullTheTrigger();
    }
}

public class SucideBomber : Weapon
{
    public override FireOnTarget()
    {
        BuyTruck();
        LoadWithC4();
        DriveToTarget();
        ActivateDetonator();
    }
}
好的,现在你有两门课。关键是在不知道实际类的情况下引用虚拟函数,例如:

public void PerformFiring(Weapon W)
{
    // do stuff
    W.FireOnTarget();
    // do more stuff
}
Pistol p=new Pistol();
PerformFiring(p);
此方法将使用您发送的来自武器的任何对象,并对该对象调用FireOnTarget。例如:

public void PerformFiring(Weapon W)
{
    // do stuff
    W.FireOnTarget();
    // do more stuff
}
Pistol p=new Pistol();
PerformFiring(p);

我知道,但我什么时候需要使用覆盖?也许举个例子会有所帮助。在父对象中是虚拟的,在子对象中是重写的。我建议读一本关于C#和OOP的入门书。可能重复的我建议避免公共虚拟,使用模板方法模式如下:试着看以下答案:谢谢解释:)