为什么要在C#中显式覆盖虚方法?
答案 0 :(得分:16)
通过将方法声明为virtual
,您声明您的意图可以在派生类中重写该方法。
通过将您的实施方法声明为override
,您声明您的意图表明您正在覆盖virtual
方法。
要求override
关键字用于覆盖虚拟方法,语言的设计者会要求您说出您的意图,从而鼓励明确。
答案 1 :(得分:11)
如果您不添加override
关键字,则该方法将被隐藏(就像它具有new
关键字一样),而不会被覆盖。
例如:
class Base {
public virtual void T() { Console.WriteLine("Base"); }
}
class Derived : Base {
public void T() { Console.WriteLine("Derived"); }
}
Base d = new Derived();
d.T();
此代码打印Base
。
如果您将override
添加到Derived
实施中,则代码将打印Derived
。
使用虚方法无法在C ++中执行此操作。 (There is no way to hide a C++ virtual method without overriding it)
答案 2 :(得分:10)
这是因为C#团队成员都是熟练的C ++程序员。并且知道这个特定的bug是多么开始:
class Base {
protected:
virtual void Mumble(int arg) {}
};
class Derived : public Base {
protected:
// Override base class method
void Mumble(long arg) {}
};
比你想象的更常见。派生类始终在另一个源代码文件中声明。你通常不会马上弄错,它会在你重构时发生。没有窥视编译器,代码运行正常,只是没有做你期望它做的事情。您可以查看它一小时或一天而不会看到错误。
这在C#程序中永远不会发生。即使是托管C ++也采用了这种语法,故意打破本机C ++语法。永远是一个勇敢的选择。 IntelliSense消除了额外的措辞。
C#中有很多语法调整,类似于这种避免错误的语法。
编辑:其余的C ++社区同意并将 override 关键字引入新的C ++ 11语言规范。
答案 3 :(得分:5)
因为它使代码更具可读性:
class Derived : Base
{
void Foo();
}
在C ++中,Foo可能是也可能不是虚方法,我们无法通过查看定义来判断。在C#中,我们知道方法是虚拟的(或者不是),因为存在虚拟或覆盖关键字。
杰森在下面的评论是一个更好的答案。
(为清晰起见而编辑)
答案 4 :(得分:1)
并非所有虚拟方法都应该被覆盖,尽管所有抽象方法都应该(并且必须)。至于为什么'override'关键字是显式的,那是因为覆盖和隐藏的行为有所不同。隐藏方法不是通过对基类的引用来调用的,而重写的方法是。这就是为什么编译器会特别警告你在隐藏而不是覆盖的情况下应该如何使用'new'关键字。