CLR会检查整个继承链以确定要调用哪个虚方法吗? [英] Will CLR check the whole inheritance chain to determine which virtual method to call?

查看:87
本文介绍了CLR会检查整个继承链以确定要调用哪个虚方法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

继承链如下:

class A
    {
        public virtual void Foo()
        {
            Console.WriteLine("A's method");
        }
    }

class B:A
    {
        public override void Foo()
        {
            Console.WriteLine("B's method");
        }
    }

class C:B
    {
        public new virtual void Foo()
        {
            Console.WriteLine("C's method");
        }
    }

class D:C
    {
        public override void Foo()
        {
            Console.WriteLine("D's method");
        }
    }

然后:

class Program
    {
        static void Main(string[] args)
        {
            A tan = new D();
            tan.Foo();
            Console.Read();
        }
    }

结果是,类中的方法foo() B被称为。

The result is, the method foo() in class B is called.

但是在引用


调用虚方法时,对象的运行时类型为
检查了一个压倒一切的成员。如果没有
派生类重写了成员,则调用大多数
派生类中的重写成员,该成员可能是原始成员。

When a virtual method is invoked, the run-time type of the object is checked for an overriding member. The overriding member in the most derived class is called, which might be the original member, if no derived class has overridden the member.

在我的逻辑中,CLR首先发现 Foo()是一个虚方法,它查看 D的方法表,运行时类型,然后它发现在这个派生程度最高的类中有一个重写成员,它应该调用它并且永远不会意识到有一个 new Foo()在继承链中。

In my logic, CLR first finds Foo() is a virtual method, it looks into the method table of D, the runtime type, then it finds out there is an overriding member in this most derived class, it should call it and never realizes there is a new Foo() in the inheritance chain.

我的逻辑出了什么问题?

What's wrong with my logic?

推荐答案


调用虚方法时,会检查对象的运行时类型一个压倒一切的成员。如果没有派生类重写成员,则调用派生类最多的成员,可能是原始成员。

When a virtual method is invoked, the run-time type of the object is checked for an overriding member. The overriding member in the most derived class is called, which might be the original member, if no derived class has overridden the member.

你是从错误的地方开始的。您的变量类型为 A 并包含 D 的实例,因此使用的虚拟表为 A 1 。在上面的文字之后,我们检查一个压倒一切的成员。我们在 B 中找到一个。 C 不计算,因为它没有覆盖,它是 shadowing 基本方法。由于 D 会覆盖 C ,而不是 A B ,它也不算数。我们正在寻找最派生类中的重要成员。

You're starting from the wrong place. Your variable is of type A and contains an instance of D, so the virtual table used is A's 1. Following the text above, we check for an overriding member. We find one in B. C does not count because it is not overriding, it is shadowing the base method. And since D overrides C, not A or B, it doesn't count either. We're looking for the overriding member in the most derived class.

所以找到的方法是 B.Foo()

如果您更改 C 以使其覆盖而不是阴影,则找到的方法将为 D ,因为它是派生最多的重要成员。

If you change C so it overrides instead of shadows, the found method will then be D, because it is the most derived overriding member.

如果您改为将对象更改为 B 或<$的实例c $ c> C , B.Foo()仍将是所选的覆盖。澄清一下,这就是我的意思:

If you instead change your object to an instance of B or C, B.Foo() will still be the chosen override. To clarify, this is what I mean:

A tan = new B();
tan.Foo();    // which foo is called?  Why, the best Foo of course!  B!

调用 B 的原因是因为继承链我们正在搜索从 A (变量类型)到 B (运行时类型)的范围。 C D 不再是该链的一部分,也不属于虚拟表。

The reason B is called is because the inheritance chain we are searching spans from A (the variable type) to B (the runtime type). C and D are no longer part of that chain, and are not part of the virtual table.

如果我们改为将代码更改为:

If we instead change the code to this:

C tan = new D();
tan.Foo();  // which foo, which foo?

我们搜索的继承链跨越 C D D 有一个重写成员,因此调用了 Foo

The inheritance chain we search spans from C to D. D is has an overriding member, so it's Foo is called.

假设您添加了继承自 A R <的另一个类 Q / code>继承自 Q ,依此类推。你有两个继承分支,对吧?在搜索大多数派生类型时选择哪个?按照从 A (您的变量类型)到 D (运行时类型)的路径。

Suppose you add another class Q that inherits from A, and R that inherits from Q, and so forth. You have two branches of inheritance, right? Which is chosen when searching for most derived type? Follow the path from A (your variable type) to D (the runtime type).

我希望这是有道理的。

1 不是字面意思。虚拟表属于 D ,因为它是运行时类型并包含其继承链中的所有内容,但它有用且更容易想到 A 作为起点。毕竟,您正在搜索派生类型。

1 Not literally. The virtual table belongs to D because it is the runtime type and contains everything in its chain of inheritance, but its useful and easier to think of A as the starting point. You are searching for derived types, after all.

这篇关于CLR会检查整个继承链以确定要调用哪个虚方法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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