繁体   English   中英

为什么这个泛型方法调用基类方法,而不是派生类方法?

[英]Why does this generic method call the base class method, not the derived class method?

对于以下代码:

class B
{
    public String G() { return "B.G()"; }
}

class D : B
{
    public String G() { return "D.G()"; }
}

class TestCompile
{
    private static String TestG<T>(T b) where T: B 
    {
        return b.G();
    }

    static void Main(string[] args)
    {
        TestG(new D());
    }
}

结果是BG() ,而类似的C ++代码的结果将是DG()

为什么会出现这种差异?

使用override关键字:

class B
{
    public virtual String G() { return "B.G()"; }
}

class D : B
{
    public override String G() { return "D.G()"; }
}

如果没有override关键字,则继承的方法不会替换基本方法。

没有覆盖:

D obj = new D();
obj.G(); // "D.G()"
((B)obj).G(); // "B.G()"

使用覆盖:

D obj = new D();
obj.G(); // "D.G()"
((B)obj).G(); // "D.G()"

C#泛型只编译一次:编译泛型时。 (考虑一下:C#允许你使用List<T>而不看其实现。)这里,它从where T: B看到where T: B子句参数是B ,所以它调用BG

每次调用C ++模板时都会编译它们。 当您键入TestG<D>() ,将使用T = D编译一个全新的TestG副本。 在调用时,编译器会看到D有自己的G方法并调用它。

C#generic的C ++等价物

template<typename T>
string TestG(T t)
{
    B& b = static_cast<B&>(t); // force `t` into a `B`
    return b.G();
}

其他人关于virtual使用的评论同样适用于C#和C ++。 我只是在解释为什么C ++与C#的行为不同。

因为你忽略了将BG标记为virtual ,而将DG标记为override

你有这个编译器警告:

CS0108:'DG()'隐藏继承的成员'BG()'。 如果要隐藏,请使用new关键字。

但你选择忽略它。 我希望C ++开发人员能做得更好! :)

这是因为参数bB型ref。 如果你将bD它将调用D上的函数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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