本文介绍了混淆虚拟/新/覆盖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有点困惑的虚拟 / / 覆盖的事情。这里有一个例子:

I am a bit confused about the virtual/new/override thing. Here's an example:

class A
{
    public virtual void mVVirtual() { Console.WriteLine("A::mVVirtual"); }
}

class B : A
{
    public virtual void mVVirtual() { Console.WriteLine("B::mVVirtual"); }
}

class C : B
{
    public override void mVVirtual() { Console.WriteLine("C::mVVirtual"); }
}


class Test
{
    static void Main()
    {
        B b1 = new C();
        b1.mVVirtual();    //C::mVVirtual ... I understand this

        A a2 = new C();
        a2.mVVirtual();    //A::mVVirtual ... ???
    }
}



我不明白为什么在第二个电话我们获得 A :: mVVirtual 。我通常这种算法对待这些问题:

I don't get why in the second call we get A::mVVirtual. I usually treat these issues with this "algorithm":


  1. 检查变量持有一个实例方法对象的引用的所谓的类型 mVVirtual ?没有这样的......但确实有与签名和名字!

  2. 虚拟方法的虚方法?那么,让我们检查的对象的类型正在举行的 A2 C ),该方法的一个压倒一切的。它有一个! - >执行ç:: mVVirtual

  1. Check the type of the variable holding the reference for the object for an instance method called mVVirtual? Doesn't have one...but does have a virtual method with that signature and name!
  2. Virtual method? Let's then check the type of the object being held by a2 (C) for an overriding of that method. It has one -> Executes C::mVVirtual!

哪里是我的算法错了吗?我真的感到困惑这和将不胜感激一些帮助。

Where is my "algorithm" wrong? I really am confused by this, and would greatly appreciate some help.

推荐答案

下面是你怎么想的虚方法。类的每个实例都有盒子来保存方法。当你标记方法虚拟它说,做一个新的盒子,把一个方法吧。当您标记的方法为在派生类中重写,它使盒子从基类,但提出一个新的方法吧。

Here's how you think of virtual methods. Every instance of a class has "boxes" to hold methods. When you mark a method as virtual it says make a new "box" and put a method in it. When you mark a method as override in a derived class, it keeps the "box" from the base class but puts a new method in it.

所以在这里你有一个类 A 和一个名为方法 mVVirtual 标记为虚拟。这是说做一个新的盒子命​​名为 mVVirtual ,把一个方法,它与定义

So here you have a class A and a method named mVVirtual that is marked as virtual. This says make a new "box" named mVVirtual and put a method in it with definition

Console.WriteLine("A::mVVirtual");



然后你有一个派生类 B 和一个名为方法 mVVirtual 标记为虚拟。这是说做一个新的盒子命​​名为 mVVirtual ,把一个方法,它与定义

Then you have a derived class B and a method named mVVirtual that is marked as virtual. This says make a new "box" named mVVirtual and put a method in it with definition

Console.WriteLine("B::mVVirtual");



特别是盒子从 A 是隐藏的!它不能被类型为 B B 派生s或类的对象可见。

In particular, the "box" inherited from A is hidden! It can not be seen by objects that are typed as Bs or classes that derive from B.

然后你有一个派生类 C 和一个名为方法 mVVirtual 标记为覆盖。这是说把盒子命​​名为 mVVirtual B继承,把一个不同的方法,它的定义。

Then you have a derived class C and a method named mVVirtual that is marked as override. This says take the "box" named mVVirtual inherited from B and put a different method in it with definition

Console.WriteLine("C::mVVirtual");

现在,当你有

B b1 = new C();
b1.mVVirtual();



你是在告诉编译器 B1 是一个 B b1.mVVirtual()看在盒子 mVVirtual ,并认为与定义方法

you are telling the compiler that b1 is a B so that b1.mVVirtual() looks in the "box" mVVirtual and finds the method with definition

Console.WriteLine("C::mVVirtual");

由于 B1 是一个真正的 C ,这是什么在盒子 mVVirtual 的C实例

because b1 is really a C and that is what is in the "box" mVVirtual for instances of C.

但是如果你有

A a2 = new C();
a2.mVVirtual();



你是在告诉编译器 A2 是一个 A ,所以它看起来在盒子,并认为

you are telling the compiler that a2 is an A and so it looks in the "box" and finds

Console.WriteLine("A::mVVirtual");



编译器无法知道 A2 是一个真正的 C (你输入它作为一个 A ),所以它不知道 A2 是真的从已隐藏盒子 mVVirtual 按 A 。它的真正知道的是, A 有一个盒子命​​名 mVVirtual ,所以它发出代码来调用方法。那个盒子

The compiler can not know that a2 is really a C (you've typed it as an A) so it does not know that a2 is really an instance of a class that is derived from a class that has hidden the "box" mVVirtual defined by A. What it does know is that A has a "box" named mVVirtual and so it emits code to invoke the method in that "box".

所以,要尽量把这个简洁:

So, to try to put this succinctly:

class A {
    public virtual void mVVirtual() { Console.WriteLine("A::mVVirtual"); }
}

定义,有一个盒子全名<$ C类$ C> A :: mVVirtual ,但你可以通过名称引用 mVVirtual

defines a class that has a "box" with full name A::mVVirtual but that you can refer to by the name mVVirtual.

class B : A
{
    // "new" method; compiler will tell you that this should be marked "new" for clarity.
    public virtual void mVVirtual() { Console.WriteLine("B::mVVirtual"); }
}

定义,有一个盒子全名<$ C类$ C> B :: mVVirtual ,但你可以通过名称引用 mVVirtual 。参照 B.mVVirtual 将不参考的盒子全名 A :: mVVirtual ;该盒子,不能由被类型为 B 的S对象可见(即从 B派生或类

defines a class that has a "box" with full name B::mVVirtual but that you can refer to by the name mVVirtual. Referring to B.mVVirtual will not refer to the "box" with full name A::mVVirtual; that "box" can not be seen by objects that are typed as Bs (or classes that derive from B).

class C : B
{
    public override void mVVirtual() { Console.WriteLine("C::mVVirtual"); }
}



定义一个类,它的盒子全名 b :: mVVirtual ,并提出不同的方法吧。

defines a class that takes the "box" with full name B::mVVirtual and puts a different method in it.

然后

A a2 = new C();
a2.mVVirtual();



表示, A2 A a2.mVVirtual 看在盒子全名 A :: mVVirtual 并调用该方法在盒子。这就是为什么你看到

says that a2 is an A so that a2.mVVirtual looks in the "box" with full name A::mVVirtual and invokes the method in that "box". This is why you see

A::mVVirtual

在控制台上。

有其他两种方法annotaters。 摘要使得一个新的盒子并没有把一个方法定义的盒子。 使一个新的盒子,并提出一个方法定义的盒子,但不允许派生类把自己的方法定义在盒子(使用虚拟如果你想这样做)。

There are two other method annotaters. abstract makes a new "box" does not put a method definition in the "box". new makes a new "box" and puts a method definition in the "box" but does not allow derived classes to put their own definitions of the method in the "box" (use virtual if you want to do that).

对不起,是啰嗦,但我希望帮助。

Sorry for being long-winded but I hope that helps.

这篇关于混淆虚拟/新/覆盖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-12 00:22