ホームページ >バックエンド開発 >C#.Net チュートリアル >C# 仮想関数
インスタンス メソッドが virtual キーワードを使用して宣言されている場合、このメソッドは仮想メソッドです。
仮想メソッドと非仮想メソッドの最大の違いは、仮想メソッドの実装が派生クラスで置き換えられることです (これについては後で詳しく説明します)
仮想メソッドの特徴:
仮想メソッドは次のとおりです。 Static、abstract、または override 修飾子を前に付けることはできません
仮想メソッドはプライベートにできないため、プライベート修飾子は使用できません
仮想メソッドの実行:
一般関数はコンパイル時に実行ファイルに静的にコンパイルされることがわかっています。相対アドレスはプログラムの実行中に変更されません。
仮想関数はコンパイル中に静的にコンパイルされず、その相対アドレスは実行時オブジェクト インスタンスに基づいて動的に決定されます。
ここで。宣言時に定義したクラスを宣言クラス、実行時にインスタンス化されるクラスをインスタンスクラスと呼びます。
例: A a =new B(); ここで、A は宣言クラス、B はインスタンス クラスです。
1. オブジェクトの関数を呼び出すとき、システムはオブジェクトによって宣言されたクラス、つまり宣言されたクラスを直接チェックして、呼び出された関数が仮想関数であるかどうかを確認します。関数の場合、この関数が直接実行されます。それが仮想関数の場合、この時点では関数はすぐには実行されませんが、オブジェクトのインスタンス クラスのチェックが開始されます。
3. このインスタンス クラスでは、インスタンス クラスの定義に仮想関数を実装するメソッドがあるかどうか、または (override キーワードを使用して) 仮想関数を再実装するメソッドがあるかどうかを確認します。再度検索しますが、インスタンス クラスに実装されている仮想関数のメソッドがすぐに実行されます。そうでない場合、システムはインスタンス クラスの親クラスを検索し続け、仮想関数をオーバーロードする最初の親クラスが見つかるまで、インスタンス クラスで先ほどのチェックを繰り返します。その後、親クラスでオーバーロードされた関数を実行します。 。
例 1:
class A { public virtual void Sum() { Console.WriteLine("I am A Class,I am virtual sum()."); } } class Program { static void Main(string[] args) { A a=new A(); // 定义一个a这个A类的对象.这个A就是a的申明类,实例化a对象,A是a的实例类 a.Sum(); Console.Read(); } }
例 2:
class A { public virtual void Sum() { Console.WriteLine("I am A Class,I am virtual sum()."); } } class B : A { public override void Sum() // 重新实现了虚函数 { Console.WriteLine("I am B Class,I am override sum()."); } } class Program { static void Main(string[] args) { A a=new B(); // 定义一个a这个A类的对象.这个A就是a的申明类,实例化a对象,B是a的实例类 a.Sum(); Console.Read(); } }
class A { public virtual void Sum() { Console.WriteLine("I am A Class,I am virtual sum()."); } } class B : A { public override void Sum() // 重新实现了虚函数 { Console.WriteLine("I am B Class,I am override sum()."); } } class C : B { } class Program { static void Main(string[] args) { A a=new C();// 定义一个a这个A类的对象.这个A就是a的申明类,实例化a对象,C是a的实例类 a.Sum(); Console.Read(); } }
a.Sum:
1 を実行します。最初に宣言クラス A を確認します。 2. それが仮想メソッドであることを確認します。 3. インスタンス クラス C を確認します。オーバーライドされたメソッドはありません。 4. クラス C の親クラス B に移動します。オーバーライドされたメソッドがあります
5. B で親クラスの Sum メソッドを実行します 6. 結果を出力します 私は B クラスで、sum() をオーバーライドします
class A { public virtual void Sum() { Console.WriteLine("I am A Class,I am virtual sum()."); } } class B : A { public new void Sum() //覆盖父类里的同名函数,而不是重新实现 { Console.WriteLine("I am B Class,I am new sum()."); } } class Program { static void Main(string[] args) { A a=new B(); a.Sum(); Console.Read(); } }
class A { public virtual void Sum() { Console.WriteLine("I am A Class,I am virtual sum()."); } } class B : A { public new void Sum() //覆盖父类里的同名函数,而不是重新实现 { Console.WriteLine("I am B Class,I am new sum()."); } } class Program { static void Main(string[] args) { B b=new B(); b.Sum(); Console.Read(); } }クラス B で Sum() を実行し、結果を出力します。私は B クラスで、新しい sum() です。
基本クラスの仮想関数をオーバーライドするために抽象関数を使用できますか?
答えは「はい」です。
class A { public virtual void PrintFriends() { Console.WriteLine("A.PrintFriends()"); } } abstract class B : A { public abstract override void PrintFriends(); //使用override 修饰符,表示抽象重写了基类中该函数的实现 } abstract class C : A { public abstract new void PrintFriends(); //使用 new 修饰符显式声明,表示隐藏了基类中该函数的实现 }シールされたクラスは仮想関数を持つことができますか?
はい、基本クラスの仮想関数は暗黙的に非仮想関数に変換されますが、シールされたクラス自体は新しい仮想関数を追加できません
class A { public virtual void Fun() { Console.WriteLine("I am A."); } } sealed class Program:A { public override void Fun() { Console.WriteLine("I am B."); } static void Main(string[] args) { Program p = new Program(); p.Fun(); Console.Read(); } }