正在查看我们代码库中的一些代码,我无法理解它是如何/为什么工作的(并且不会由于无限递归而导致堆栈溢出)。我在下面粘贴了一些等效代码: 我们在类 P1 中定义了一个虚拟方法 Foo(B),并在类 P2 中被覆盖。P2 还定义了一个私有的非虚拟方法 Foo(A)。B 派生自 A。P2::Foo(B) 最后有一个调用:Foo(b)。我希望这最终会导致堆栈溢出。但是,输出是: P2::Foo Virtual P2::Foo Private Non-Virtual
在这种情况下,看起来在被覆盖的方法中对 Foo 的第二次调用正在选择非虚拟方法 Foo 。在 P1(取消注释代码)中执行类似操作时,我们最终通过递归无限次调用 Foo。
问题:(终于!) 1.为什么原始虚拟方法和覆盖方法的行为不同?为什么一个调用自己而另一个调用不同的方法?2. 某处是否指定了优先顺序?请注意,如果我们将 private 修饰符更改为 public,在这两种情况下,我们最终都会调用非虚拟方法(即使我们以这种方式实例化 P2: P1 p2 = new P2(); ,而不是 P2 p2 = new P2( );) 看起来非虚拟版本是首选,除非它位于虚拟方法定义中。这是真的?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
public class P1
{
static void Main(string[] args)
{
B b = new B();
P2 p2 = new P2();
p2.Foo(b);
// Uncomment code to cause infinite recursion
//P1 p1 = new P1();
//p1.Foo(b);
}
private void Foo(A a)
{
Console.WriteLine("P1::Foo Private Non-Virtual");
}
public virtual void Foo(B b)
{
Console.WriteLine("Inside P1::Foo");
// Uncomment code to cause infinite recursion
// Foo(b);
}
}
public class P2 : P1
{
private void Foo(A a)
{
Console.WriteLine("P2::Foo Private Non-Virtual");
}
public override void Foo(B b)
{
Console.WriteLine("P2::Foo Virtual");
Foo(b);
}
}
public class A
{
public int a = 10;
}
public class B : A
{
public int b = 20;
}
}