在派生类重载基方法 [英] Overloading base method in derived class

查看:127
本文介绍了在派生类重载基方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我用C#玩,看它是否匹配,从这个帖子C ++的行为:的http://herbsutter.com/2013/05/22/gotw-5-solution-overriding-virtual-functions/
,当我遇到这个非常奇怪的现象就来了:

 公共类BaseClass的
{
公共虚拟无效美孚(int i)以
{
控制台.WriteLine(叫美孚(INT):+ I);
}

公共无效美孚(字符串I)
{
Console.WriteLine(叫做foo(字符串):+ I);
}
}

公共类DerivedClass:BaseClass的
{
公共无效美孚(双I)
{
控制台。的WriteLine(叫做foo(双)+ I);
}
}

公共类OverriddenDerivedClass:BaseClass的
{
公众覆盖无效美孚(int i)以
{
基包含.foo(ⅰ);
}

公共无效美孚(双I)
{
Console.WriteLine(叫做foo(双)+ I);
}
}

类节目
{
静态无效的主要(字串[] args)
{
DerivedClass派生=新DerivedClass();
OverriddenDerivedClass overridedDerived =新OverriddenDerivedClass();

INT I = 1;
双D = 2.0;
字符串s =你好;

derived.Foo(ⅰ);
derived.Foo(四);
derived.Foo(S);

overridedDerived.Foo(ⅰ);
overridedDerived.Foo(四);
overridedDerived.Foo(S);
}
}



输出

 叫做foo(双):1 
叫做foo(双):2
叫做foo(字符串):喜
叫做foo(双):1
叫做foo(双):2
叫做foo(字符串):喜

所以显然这有利于隐式转换INT在从基类更具体美孚(INT)翻一番。或者它隐藏从基类美孚(INT)?但后来:为什么不是美孚(串)隐藏?感觉很不一致......它还如果我重写美孚(INT),或者并不重要;结果是相同的。任何人能解释这是怎么回事呢?



(是的,我知道这是不好的做法,超负荷在派生类中的方法基地 - 里氏和所有 - 但我仍然不会想到,美孚(INT)在OverriddenDerivedClass不叫?!)


解决方案

要解释它是如何工作的 OverriddenDerivedClass 例如:



看一看这里的成员查找的C#规格:的 http://msdn.microsoft.com/en-us/library/aa691331%28VS.71%29.aspx < 。/ p>

这定义查询是如何完成的。



在特定的,看这个部分:




首先,集合所有可访问(第3.5节)名为N的成员在T中声明和T的基本类型(第7.3.1节)构造。声明包括override修饰符被排除在集。




在你的情况, N 美孚( )。因为声明包括override修饰符被排除在集那么重写美孚(int i)以从排除在外设定。



因此,只有非重写美孚(双I)仍然存在,因此它是一个叫



这是如何工作的 OverriddenDerivedClass 的例子,但是这不是一个解释。在 DerivedClass 例如



要说明的是,看规范的这一部分:




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




美孚(双I) DerivedClass 隐藏着美孚(INT我)从基类,所以它是从集合中删除



这里的棘手的事情是说,部分:




具有相同签名为M的所有方法从集合中移除S的基本类型中声明。




您可能会说:别急! 美孚(双I)的具有相同签名美孚(int i)以,因此它不应该被从集合中去掉!



不过,因为从int隐式转换翻一番,它的被认为具有相同的签名,那么美孚(int i)以的从集合中删除。


So I was playing with C# to see if it matched C++ behavior from this post: http://herbsutter.com/2013/05/22/gotw-5-solution-overriding-virtual-functions/ when I came across this very strange behavior:

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);
    }
}

Output

Called Foo(double): 1
Called Foo(double): 2
Called Foo(string): hi
Called Foo(double): 1
Called Foo(double): 2
Called Foo(string): hi

So apparently it favors the implicitly converted int to double over the more specific Foo(int) from the base class. Or does it hide the Foo(int) from the base class? But then: why isn't Foo(string) hidden? Feels very inconsistent... It also does not matter if I override Foo(int) or not; the outcome is the same. Can anyone explain what's going on here?

(Yes I know that it is bad practice to overload base methods in a derived class - Liskov and all - but I still wouldn't expect that Foo(int) in OverriddenDerivedClass isn't called?!)

解决方案

To explain how it works for the OverriddenDerivedClass example:

Have a look at the C# spec for member lookup here: http://msdn.microsoft.com/en-us/library/aa691331%28VS.71%29.aspx

That defines how the lookup is done.

In particular, look at this part:

First, the set of all accessible (Section 3.5) members named N declared in T and the base types (Section 7.3.1) of T is constructed. Declarations that include an override modifier are excluded from the set.

In your case, N is Foo(). Because of Declarations that include an override modifier are excluded from the set then the override Foo(int i) is excluded from the set.

Therefore, only the non-overridden Foo(double i) remains, and thus it is the one that is called.

That is how it works for the OverriddenDerivedClass example, but this is not an explanation for the DerivedClass example.

To explain that, look at this part of the spec:

Next, members that are hidden by other members are removed from the set.

The Foo(double i) in DerivedClass is hiding the Foo(int i) from the base class, so it is removed from the set.

The tricky thing here is the part that says:

All methods with the same signature as M declared in a base type of S are removed from the set.

You might say "But wait! Foo(double i) doesn't have the same signature as Foo(int i), so it shouldn't be removed from the set!".

However, because there is an implicit conversion from int to double, it is considered to have the same signature, so Foo(int i) is removed from the set.

这篇关于在派生类重载基方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆