[英]How Base classes are automatically instantiated before derived classes
我想知道在創建派生類的實例時,如何在派生類之前自動實例化基類。
我只想知道基類的成員如何占用內存,子類的引用如何訪問它們。
讓我們舉一些例子:
class A
{
int x;
int y;
}
class B: A
{
int c;
}
如果創建A
的新實例,則會在堆上創建一塊內存。 該內存將占用8個字節; x
4個字節, y
4個字節。 (我知道,將為其類型保留更多的內存,等等,但是我將其保留在此范圍之外)。
如果創建B
的新實例,則會創建更多的內存。 不是兩個,只有一個。 因此,沒有子實例或任何實例。 這塊內存的長度為12個字節( x
為4個字節, y
為4個字節,新字段z
為4個字節。
在堆上創建一塊內存時,它將始終填充零。 因此,所有fied將具有其默認值,在這種情況下為0
。
如果兩個類都具有公共的無參數構造函數,則將自動調用這些構造函數。
class A
{
int x;
int y;
public A()
{
x = 1; y = 2;
}
}
class B: A
{
int c;
public B()
{
z = 3;
}
}
創建新的B
實例時,將調用B
的構造函數。 構造函數要做的第一件事是調用A
構造函數。 A
將其字段x
和y
為1
和2
。 然后,程序返回到B
的構造函數,該構造函數將使用值3
初始化z
。
B
的構造函數也可以寫成(以表明B
正在調用其基數A
的構造函數):
public B()
: base()
{
z = 3;
}
一次創建對象:基於以下知識分配字段空間: X : Y : Z
需要空間來存儲X
, Y
, Z
聲明的字段總和(以及任何object
開銷,作為X
的隱式基礎) Z
)。 字段是繼承的,因此X
是 Z
它們是自下而上初始化的,因為這是構造函數的工作方式 ; 如果我們寫:
class A : B
{
private int _a = 1;
public A() { Console.WriteLine("A"); }
}
class B {
private int _b = 1;
public B() { Console.WriteLine("B"); }
}
然后我們得到(對於B
):
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: ldc.i4.1
L_0002: stfld int32 B::_b
L_0007: ldarg.0
L_0008: call instance void [mscorlib]System.Object::.ctor()
L_000d: ldstr "B"
L_0012: call void [mscorlib]System.Console::WriteLine(string)
L_0017: ret
}
對於A
:
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: ldc.i4.1
L_0002: stfld int32 A::_a
L_0007: ldarg.0
L_0008: call instance void B::.ctor()
L_000d: ldstr "A"
L_0012: call void [mscorlib]System.Console::WriteLine(string)
L_0017: ret
}
請注意,它會在運行自己的本地構造函數代碼之前調用base-constructor。 還請注意,字段初始化器甚至早於此。
一個簡單的解釋是將繼承視為復制機
因此,讓我們定義2個類
class Base
{
}
class Child : Base
{
}
現在您要創建一個子對象。 子級有其自己的字段,但是由於它是從基類繼承的,因此它必須去復制其基類的所有字段,從而自動創建。
類是對象的模板,繼承不過是在創建新模板時可以附加的可重用模板。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.