2014-02-26 197 views
8

我有一个困惑,我想解决..在C#中,只有具有virtual标记的基类方法可以在派生类中重写。不包含virtual标记的基类方法不能被覆盖。充其量,派生类可以使用new隐藏基类方法。然后我们有sealed方法,这些方法也不能在基类中重写。非虚拟方法和密封方法有什么区别?

那么,密封的方法和标准的非虚拟方法有什么区别呢?

另一个相关的问题。可以使用new在派生类中替换基类sealed方法吗?

+0

密封和虚拟关键字不服务于相同的目的。可以在虚拟方法上定义密封方法 – Aidin

+0

最后一个问题:'new'修饰符不能代替任何东西。它只是告诉编译器停止抱怨,当你在你的类中引入一个** new **成员与已存在的(继承)成员具有相同的名称(加上方法的签名)时,会停止抱怨。没有什么被取代。这两种方法(成员)都在那里,但不相关。在某些情况下,其中一种方法是** hidden **,但仍可通过将引用强制转换为基本类型来找到(并调用)该方法。避免使用'new'修饰符;相反,为新方法选择一个未使用的名称。 –

回答

12

sealed阻止任何进一步覆盖链上的虚拟方法。您只能在过期的方法上定义sealed。看看该文档为sealedhttp://msdn.microsoft.com/en-us/library/aa645769(v=vs.71).aspx

他们给封闭使用的一个很好的例子:

using System; 
class A 
{ 
    public virtual void F() { 
     Console.WriteLine("A.F"); 
    } 
    public virtual void G() { 
     Console.WriteLine("A.G"); 
    } 
} 
class B: A 
{ 
    sealed override public void F() { 
     Console.WriteLine("B.F"); 
    } 
    override public void G() { 
     Console.WriteLine("B.G"); 
    } 
} 
class C: B 
{ 
    override public void G() { 
     Console.WriteLine("C.G"); 
    } 
} 

在这种情况下,任何人谁导出过的B可以覆盖G,但不F

+2

嗯..这是C#规范中“密封”的例子。但是非虚方法和区别的解释在哪里? –

+0

因此'''封闭',使'虚拟'功能,'非虚拟',在某处下线?我的意思是说,'密封'删除了方法的'虚拟'分类? – Ahmad

+0

@Ahmad'sealed'表示此方法上次被覆盖,如果派生,则不能再覆盖它。 – 2014-02-26 15:51:09

1

如果我正确阅读this,密封允许虚拟化为虚拟虚拟。实质上取消了虚拟。

+0

这是不正确的。该方法仍然是虚拟的,只有在方法被“密封”之前,vtable才会仅限于那些条目。这是一个重要的区别。 – Servy

+1

@Servy,这正是我的意思。将虚拟方法标记为“密封”的继承链的类基本上阻止那些将方法视为虚拟(即使原来是虚拟方法)的类继承它。换句话说,密封的关键字会删除较早的虚拟关键字(在该层次上,而不是在下面的层次上,只能在该层次或更高层次上)。 – LB2

2

密封方法只能是从基类重写方法的方法,因此不可能进一步重载。

从文档:

当一个实例方法的声明包括一个密封的改性剂,该方法 被说成是一个密封的方法。
如果一个实例方法 声明包含密封修饰符,则它还必须包含覆盖修饰符 。

这不是虚拟方法所必需的。

相关问题