[英]Overloading base method in derived class
所以我正在玩C#以查看它是否与此帖子中的C ++行为相符: http : //herbsutter.com/2013/05/22/gotw-5-solution-overriding-virtual-functions/当我遇到这个非常奇怪的时候行为:
public class BaseClass
{
public virtual void Foo(int i)
{
Console.WriteLine("Called Foo(int): " + i);
}
public void Foo(string i)
{
Console.WriteLine("Called Foo(string): " + i);
}
}
public class DerivedClass : BaseClass
{
public void Foo(double i)
{
Console.WriteLine("Called Foo(double): " + i);
}
}
public class OverriddenDerivedClass : BaseClass
{
public override void Foo(int i)
{
base.Foo(i);
}
public void Foo(double i)
{
Console.WriteLine("Called Foo(double): " + i);
}
}
class Program
{
static void Main(string[] args)
{
DerivedClass derived = new DerivedClass();
OverriddenDerivedClass overridedDerived = new OverriddenDerivedClass();
int i = 1;
double d = 2.0;
string s = "hi";
derived.Foo(i);
derived.Foo(d);
derived.Foo(s);
overridedDerived.Foo(i);
overridedDerived.Foo(d);
overridedDerived.Foo(s);
}
}
产量
Called Foo(double): 1
Called Foo(double): 2
Called Foo(string): hi
Called Foo(double): 1
Called Foo(double): 2
Called Foo(string): hi
所以显然它倾向于隐式转换的int,以便从基类中更加特定的Foo(int)加倍。 或者它是否隐藏了基类的Foo(int)? 但那么:为什么不隐藏Foo(字符串)? 感觉非常不一致...如果我重写Foo(int)也没关系; 结果是一样的。 谁能解释一下这里发生了什么?
(是的,我知道在派生类中重载基本方法是不好的做法--Liskov和所有 - 但我仍然不会指望OverriddenDerivedClass中的Foo(int)没有被调用?!)
要解释它对OverriddenDerivedClass
示例的工作原理:
在这里查看成员查找的C#规范: http : //msdn.microsoft.com/en-us/library/aa691331%28VS.71%29.aspx
这定义了查找的完成方式。
特别是,看看这部分:
首先,构造在T中声明的名为N的所有可访问(第3.5节)成员的集合,并构造T的基本类型(第7.3.1节)。 包含覆盖修饰符的声明将从集合中排除。
在你的情况下, N
是Foo()
。 由于Declarations that include an override modifier are excluded from the set
的Declarations that include an override modifier are excluded from the set
因此override Foo(int i)
将从集合中排除。
因此,只有非重写的Foo(double i)
仍然存在,因此它是被调用的那个。
这就是它对OverriddenDerivedClass
示例的工作原理,但这不是DerivedClass
示例的解释。
要解释一下,请看一下规范的这一部分:
接下来,从集合中删除被其他成员隐藏的成员。
DerivedClass
的Foo(double i)
将Foo(int i)
隐藏在基类中,因此它将从集合中删除。
这里的棘手问题是:
在集合中删除与基本类型S中声明的M具有相同签名的所有方法。
你可能会说“但是等等! Foo(double i)
与Foo(int i)
没有相同的签名,因此它不应该从集合中删除!”。
然而,因为有从int加倍的隐式转换,它被认为具有相同的签名,所以Foo(int i)
从集合中移除。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.