虚拟和覆盖有什么意义?没有C#不做同样的事吗?

时间:2011-11-20 17:16:10

标签: inheritance polymorphism override virtual

根据我的理解,virtual关键字允许您使用基类'方法,override允许您在继承自基类的类中覆盖它。我的困惑是我刚刚测试了在基类的方法定义中没有使用virtual关键字,并且在派生类中没有包含该方法,我仍然可以调用基类的方法(它出现在intellisense并运行) 。另外,我知道如果我想为我的派生类使用相同方法的新方法定义,我可以使用new关键字..

我可能错过了一个关键点,但这是我理解它的方式,这就是为什么我对虚拟和覆盖的目的感到困惑

5 个答案:

答案 0 :(得分:3)

使用polymorphism

时,这些关键字的强大功能就会发挥作用

我认为一个例子有助于理解最多。请考虑以下事项:

class Base {
  public virtual void f() { Console.WriteLine("Virtual Base"); }
}

class Override : Base {
  public override void f() { Console.WriteLine("Overridden derived"); }
}

class New : Base {
  public new void f() { Console.WriteLine("New derived"); }
}

现在,如果您有一个实际类型Derived但静态类型Base的对象,则调用f()仍会输出“Overridden Derived”:

Base obj = new Override();
obj.f(); // Overridden derived

使用new关键字,告诉运行时停止从该类开始查找具有该名称的方法:

Base obj = new New();
obj.f(); // Virtual Base

与至少在f()类型上调用New相反:

New obj = new New();
obj.f(); // New derived

答案 1 :(得分:2)

  

我的困惑是我刚刚测试过没有使用虚拟关键字   基类的方法定义,而不包括该方法   派生类,我仍然能够调用基类的方法(它   出现在intellisense并且跑了。)

这是预期的行为。

Virtual允许你override一个在基类中定义的方法,换句话说,扩展派生类中方法的实现。

新关键字与覆盖一个can be found on MSDN here之间的差异。

如果您能够在派生类中调用基类方法,则access modifiers(private,public,protected)会受到影响。

答案 2 :(得分:0)

Virtual允许您覆盖基类方法。你仍然可以在没有它的情况下调用该方法,但如果没有它,将无法覆盖该方法。

抱歉,我忘记提及多态性了。因此,如果你有一个定义方法的基类,你可以做这样的事情。

以下代码段将从B

打印
public class A
{
  virtual void foo
  {
    Console.WriteLine("From A");
  }
}

public class B : A
{
  override void foo()
  {
   Console.WriteLine("From B");
  }
}

static void Main(string[] args) 
{
   A testA = new B();

   a.foo();
}

答案 3 :(得分:0)

要覆盖基类中的方法,必须将覆盖的方法标记为虚拟 - 使用覆盖关键字覆盖方法。

新方法的上下文略有不同。它允许您在子类中添加一个方法,该方法的名称与基类中的方法相同。调用哪个方法取决于您用来访问该方法的引用。

您可以访问基类中实现的任何方法(受访问修饰符限制),无论它们是否标记为虚拟。

答案 4 :(得分:0)

当您将方法标记为虚拟或抽象时,运行时类型检查用于确定要调用的方法的实际实现:它检查实现/覆盖虚方法的“派生类型最多”,并调用那个实现。普通方法不需要运行时类型检查。

因此,虚拟和非虚拟之间的区别会对代码的语义产生有意义的影响,尤其是对于公共API。如果你看到这个:

class A { void foo(); virtual void bar(); }
...
A myObject = getSomeObject();
myObject.foo();
myObject.bar();

您可以确定调用的foo的实现是在类A中声明的实现。这是因为只使用编译时类型检查来确定要调用的方法。但是,调用的bar的具体实现可能是A的某个子类中的实现,具体取决于myObject的运行时类型。

更多信息:http://msdn.microsoft.com/en-us/library/aa645767(v=vs.71).aspx