繁体   English   中英

在派生类中重载基方法

[英]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节)。 包含覆盖修饰符的声明将从集合中排除。

在你的情况下, NFoo() 由于Declarations that include an override modifier are excluded from the setDeclarations that include an override modifier are excluded from the set因此override Foo(int i)将从集合中排除。

因此,只有非重写的Foo(double i)仍然存在,因此它是被调用的那个。

这就是它对OverriddenDerivedClass示例的工作原理,但这不是DerivedClass示例的解释。

要解释一下,请看一下规范的这一部分:

接下来,从集合中删除被其他成员隐藏的成员。

DerivedClassFoo(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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM