私たちのコードベースでいくつかのコードを見ていましたが、これがどのように/なぜ機能しているのか理解できません(無限再帰によるスタックオーバーフローを引き起こしていません)。以下に同等のコードをいくつか貼り付けました。 クラス P1 で定義され、クラス P2 でオーバーライドされた仮想メソッド Foo(B) があります。P2 は、プライベートな非仮想メソッド Foo(A) も定義します。B は A から派生します。P2::Foo(B) は最後に呼び出しがあります: Foo(b)。これがスタック オーバーフローに終わることを期待しています。ただし、出力は次のとおりです。 P2::Foo 仮想 P2::Foo プライベート 非仮想
この場合、オーバーライドされたメソッドでの Foo への 2 番目の呼び出しは、非仮想メソッド Foo を取得しているようです。P1 (コードのアンコメント) で同様の操作を行うと、再帰によって Foo を無限に呼び出すことになります。
質問: (最後に!) 1. 元の仮想メソッドとオーバーライドされたメソッドで動作が異なるのはなぜですか? 1 つは自分自身を呼び出し、もう 1 つは別のメソッドを呼び出すのはなぜですか? 2.どこかに指定された優先順位はありますか? private 修飾子を public に変更すると、どちらの場合も、非仮想メソッドを呼び出すことになることに注意してください (P2 をこのようにインスタンス化しても、 P2 p2 = new P2( の代わりに P1 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;
}
}