1. オブジェクトを作成する
オブジェクトの作成プロセスは、主にメモリの割り当てと初期化の 2 つの部分に分かれています。 .NET では、CLR によって管理されるメモリ領域は主にスタック、GC ヒープ、LOH ヒープの 3 つの部分で構成されます。スタックは主に値型データの割り当てに使用されます。その管理は、GC ヒープのような GC ではなく、システムによって制御されます。スレッドが値型インスタンスのメソッドの実行を終了すると、この領域は自動的に解放されます。一般に、スタックの実行効率は高くなりますが、容量には限界があります。
GC ヒープは、小さなオブジェクト インスタンスを割り当てるために使用され、メモリの割り当てとリサイクルは GC によって完全に制御されます。 LOH ヒープはラージ オブジェクト インスタンス用に準備されており、圧縮されず、GC が完全にリサイクルされる場合にのみリサイクルされます。 IL では、newobj、ldstr (文字列オブジェクトの作成)、newarr (新しい配列オブジェクトの割り当てに使用)、box (ボックス化) などのオブジェクトを作成するための一般的な命令を確認できます。
もちろん、値型もヒープ上に存在します。たとえば、値型がクラスのフィールドとして使用される場合、値型はヒープ内のインスタンス オブジェクト空間に格納され、ボックス化すると、値型が保存されます。ヒープ上にも存在します。さて、オブジェクトを作成する際のメモリ割り当てを見てみましょう。ここには person クラスと Student クラスがあります。次に、次の文 Student s = new Student() {studentId = 2, Id = 4 }; 実行後、s オブジェクトが作成され、オブジェクト作成時のメモリ割り当てを示します。私が描画していない同期インデックス ブロックと型オブジェクト ポインターがあります。
public class Person { public int Id; public void Eat() { Console.WriteLine("Eat Pear"); } } public class Student:Person { public int studentId; public void GotoSchool() { Console.WriteLine("Go to School"); } }
コードを見る
2. 親クラスのオブジェクトはサブクラスを指します
プログラムを書くとき、ポリモーフィズムを実現するために、通常、親クラスのオブジェクトを使用してサブクラスを指します。次に、 Person p=new Student(); と記述すると、ヒープ内にサブクラス オブジェクトが作成されます。以下は、サブクラスを指す親クラス オブジェクトのメモリ割り当て図です。 Person に仮想メソッドと抽象メソッドを追加し、Student サブクラスのメソッドをオーバーライドしました。
この図から、サブクラスが親クラスの仮想メソッドまたは抽象メソッドをオーバーライドすると、Person メソッド テーブル内の 2 つのメソッドがサブクラスによってオーバーライドされ、それに基づいてポリモーフィズムを実装できることがわかります。また、Student メソッド テーブルには新しい void Eat() メソッドがありますが、この時点の new Eat() はサブクラスに属しているため、p から呼び出すことはできません。
つまり、オーバーライドされたメソッドを除いて、p は Person メソッド テーブル内のメソッドのみを呼び出すことができます。見つからない場合は、オブジェクトが見つかるまで Person 親クラスのメソッドを検索し続けます。過去を振り返ることはなく、Student メソッド テーブル内のメソッドを検索しないことに注意してください
public abstract class Person { public int Id; public void Eat() { Console.WriteLine( "在吃梨"); } public virtual void Walk() { Console.WriteLine("在散步"); } //抽象方法只能在抽象类中声明,因此要在Person前加abstract,且只能声明并必须在子类中实现。 public abstract void Run(); } public class Student:Person { public int studentId; public void GotoSchool() { Console.WriteLine("Go to School"); } public new void Eat() { Console.WriteLine("学生 吃苹果"); } public override void Walk() { Console.WriteLine("学生 在散步"); } public override void Run() { Console.WriteLine("学生 在跑步"); } }
3. 孫オブジェクトをポイントします
次に、別の Student サブクラス James を追加します。これは、前の例にすでに含まれています。 override キーワードによってオーバーライドされたメソッドのみが親クラスによって呼び出されるようにするため、通常のメソッドをすべて削除しました。実行コードは次のとおりです。 Person p = new James() { name = “James”,studentId = 2, Id = 4 }; コードとメモリ割り当て図は、重要な点を強調するために次のとおりです。図内のフィールド。結果から、SayHi メソッドが最終的に孫クラスの SayHi によって上書きされたことがわかります。ここから、継承の推移性がわかります。
public abstract class Person { public int Id; public virtual void Eat() { Console.WriteLine( "在吃梨"); } public virtual void Walk() { Console.WriteLine("在散步"); } //抽象方法只能在抽象类中声明,因此要在Person前加abstract,且只能声明并必须在子类中实现。 public abstract void Run(); public virtual void SayHi() { Console.WriteLine("人说:你好!"); } } public class Student:Person { public int studentId; public virtual void Eat() { Console.WriteLine("学生 在吃梨"); } public override void Walk() { Console.WriteLine("学生 在散步"); } public override void Run() { Console.WriteLine("学生 在跑步"); } } public class James:Student { public string name; public override void Eat() { Console.WriteLine("James 在吃梨"); } public override void Walk() { Console.WriteLine("James 在散步"); } public override void Run() { Console.WriteLine("James 在跑步"); } public override void SayHi() { Console.WriteLine("James说:你好!"); } }
上記は C# の基本的なメモリ割り当ての内容です。さらに関連する内容については、PHP 中国語 Web サイト (www.php.cn) をご覧ください。