简体   繁体   English

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

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

For the following code: 对于以下代码:

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

The result is BG() , whereas the result of similar C++ code would be DG() . 结果是BG() ,而类似的C ++代码的结果将是DG()

Why is there this difference? 为什么会出现这种差异?

Use the override keyword: 使用override关键字:

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

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

Without the override keyword, the inherited method doesn't replace the base one. 如果没有override关键字,则继承的方法不会替换基本方法。

Without override: 没有覆盖:

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

With override: 使用覆盖:

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

C# generics are compiled only once: at the time the generic is compiled. C#泛型只编译一次:编译泛型时。 (Think about it: C# lets you use List<T> without seeing its implementation.) Here, it sees from the where T: B clause that the parameter is a B , so it calls BG . (考虑一下:C#允许你使用List<T>而不看其实现。)这里,它从where T: B看到where T: B子句参数是B ,所以它调用BG

C++ templates are compiled each time they are invoked. 每次调用C ++模板时都会编译它们。 When you type TestG<D>() , a brand new copy of TestG is compiled with T = D . 当您键入TestG<D>() ,将使用T = D编译一个全新的TestG副本。 At invocation time, the compiler sees that D has its own G method and calls it. 在调用时,编译器会看到D有自己的G方法并调用它。

The C++ equivalent of the C# generic would be C#generic的C ++等价物

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

The remarks of others regarding the use of virtual apply equally to C# and C++. 其他人关于virtual使用的评论同样适用于C#和C ++。 I'm just explaining why C++ behaves differently from C#. 我只是在解释为什么C ++与C#的行为不同。

Becuase you've neglected to mark BG as virtual , and DG as override . 因为你忽略了将BG标记为virtual ,而将DG标记为override

You got this compiler warning: 你有这个编译器警告:

CS0108: 'DG()' hides inherited member 'BG()'. CS0108:'DG()'隐藏继承的成员'BG()'。 Use the new keyword if hiding was intended. 如果要隐藏,请使用new关键字。

but you chose to ignore it. 但你选择忽略它。 I would expect better from a C++ developer! 我希望C ++开发人员能做得更好! :) :)

It's because the parameter b is in a B type ref. 这是因为参数bB型ref。 if you cast b to D it'll call the function on D . 如果你将bD它将调用D上的函数。

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

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