2014-11-05 66 views
1

我只是有一个基本的问题:函数重载和覆盖

public class virtualTest 
    { 
     public virtual void vTest() 
     { 
      Console.WriteLine("Base Class"); 
     } 
    } 

    public class derivedVirtualTest : virtualTest 
    { 
     public override void vTest() 
     { 
      Console.WriteLine("Derived Class"); 
     } 
    } 

在这里,我已经使用功能与功能VTEST()

重写但是,如果我:

public class virtualTest 
    { 
     public void vTest() 
     { 
      Console.WriteLine("Base Class"); 
     } 
    } 

    public class derivedVirtualTest : virtualTest 
    { 
     public void vTest() 
     { 
      Console.WriteLine("Derived Class"); 
     } 
    } 

中移除了虚拟和覆盖各个地方的关键字,然后还有代码作品。

这怎么可能?

或者如果代码工作正常,没有虚拟和重写,那么override和virtual(整个函数覆盖)的用法是什么?

编辑:

我的方法,通过它我打电话上述类

static void Main(string[] args) 
     { 



      derivedVirtualTest objderivedVirtualTest = new derivedVirtualTest(); 
      objderivedVirtualTest.vTest(); 

      virtualTest objvirtualTest = new virtualTest(); 
      objvirtualTest.vTest(); 

      Console.ReadLine(); 


     } 
+0

你说这段代码有效,但你从来没有显示过你如何测试它。也发布该代码。这是最重要的部分。 – 2014-11-05 06:45:19

+0

@SriramSakthivel刚刚发布。请看看它 – 2014-11-05 06:48:10

+0

请参考[this](http://stackoverflow.com/questions/392721/difference-between-shadowing-and-overriding-in-c)要使用多态,你需要编译时间类型为basetype不是派生类型。只需将'derivedVirtualTest objderivedVirtualTest'更改为'virtualTest objderivedVirtualTest'来查看差异。 – 2014-11-05 07:00:00

回答

2

正如qwr所解释的,mai在OOP方面的差异是多态性。这意味着如果您通过基本类型引用访问基类成员覆盖的类,则您对可重写成员执行的调用将被重定向到覆盖。

如果是基类成员,则调用不会被重定向,并且基类的方法正在执行,如果类别为阴影/隐藏

因此,考虑到:

class Base 
{ 
    public virtual void OverrideMe() 
    { 
     Console.WriteLine("I'm the base"); 
    } 
} 

class Derived : Base 
{ 
    public override void OverrideMe() 
    { 
     Console.WriteLine("I'm derived"); 
    } 
} 

class Shadowing : Base 
{ 
    public void OverrideMe() 
    { 
     Console.WriteLine("I'm shadowing"); 
    } 
} 

并利用他们这样说:

var instances = new Base[] {new Base(), new Derived(), new Shadowing()}; 

foreach (var instance in instances) 
{ 
    instance.OverrideMe(); 
} 

会产生:

我来源的基本

我是基地

另外的区别在于,如果重写可以演变您的基类,例如更改基础成员的签名或完全删除它,而不更改隐藏基类。在某些情况下,这可能恰恰适合需要,而在某些情况下可能不太适合。

如果覆盖你,必须也改变覆盖成员的签名,否则你的代码将无法编译。

+0

假设在上面的例子中只有两个类:Base和Shadowing,OverrideMe在Base中没有声明为虚拟。那是不是叫做阴影? – 2014-11-05 07:20:14

+1

是的。如果通过* Base *类型引用派生类,派生方法将永远不会被调用。另外,你甚至可以让隐藏方法返回一些值(而不是* void *),编译器不会产生错误,只警告不使用* new *关键字。 – galenus 2014-11-05 07:32:57

+0

谢谢老板:) – 2014-11-05 07:35:15

5

在第一次就可以实现polimorphism。第二你不能。

首先叫overriding,第二个叫hiddingshadowing (Vb.Net)

而且还有问一下这么多的问题。

override vs hiding questions

Differences Between Shadowing and Overriding MSDN

+0

但是这里写的是:请注意,在C#中,你不能覆盖非虚拟或静态方法。但是我没有虚拟的方法overrided – 2014-11-05 06:50:48

+0

你是什么意思?第二你不能做多态吗? @qwr – dotctor 2014-11-05 06:53:01

+0

我只是说如果你把派生类当作基类并调用它的函数,它会调用基类函数。 – qwr 2014-11-05 06:58:51

1

在第二个例子,也许你测试你的代码是这样的:

derivedVirtualTest deviTest = new derivedVirtualTest(); 
deviTest.vTest(); //Result "Derived Class" 

试试这个,你会看到该函数has't被覆盖还有:

virtualTest deviTest = new derivedVirtualTest(); 
deviTest.vTest(); //Result "Base Class" 
//This will result "Dervived class" in the first one