[求解]基類引用不能訪問子類public實例字段


 

最近一直比較糾結CLR在類型轉換時到底做了些什么事情,在這里我撇開基本類型不談,因為那些類型在轉換過程中就是數據的擴充和裁切,這里主要討論繼承機制中的類型轉換問題。

先看段簡單代碼

 1 class Father
2 {
3 public int i=10;// 聲明為public類型是為了后面的驗證
4 /// <summary>
5 /// 非虛實例方法
6 /// </summary>
7 public void IsFather()
8 {
9 Console.WriteLine("I'm father");
10 }
11 /// <summary>
12 /// 虛方法
13 /// </summary>
14 public virtual void MyName()
15 {
16 Console.WriteLine("I'm father");
17 }
18 }
19
20 class Child : Father
21 {
22 public strings="Test

";// 聲明為public類型是為了后面的驗證
23
24 /// <summary>
25 /// 非虛實例方法
26 /// </summary>
27 public void IsChild()
28 {
29 Console.WriteLine("I'm child");
30 }
31 /// <summary>
32 /// 重寫實例方法
33 /// </summary>
34 public override void MyName()
35 {
36 Console.WriteLine("I'm child");
37 }
38 }

根據CLR Via C#中的介紹,我可以理解在繼承機制中方法的調用原理,但是對實例字段的調用就不是很明確了,書中說到(下面一段內容摘自() Jeffrey Richter著 ,周靖譯的《CLR Via C#》第三版,版權歸著作權所有者,這里僅引用一下):

4-8  在線程棧上分配M3的局部變量

 然后,M3執行它的代碼來構造一個Manager對象。這造成在托管堆中創建Manager類型的一個實例(也就是一個Manager對象),如圖4-9所示37。可以看出,和所有對象一樣,Manager對象也有一個類型對象指針和同步塊索引。該對象還包含必要的字節來容納Manager類型定義的所有實例數據字段,以及容納由Manager的任何基類(本例就是EmployeeObject)定義的所有實例字段。任何時候在堆上新建一個對象,CLR都會自動初始化內部類型對象指針成員,讓它引用與對象對應的類型對象(本例就是Manager類型對象)。此外,CLR會先初始化同步塊索引,並將對象的所有實例字段設為null0(零),再調用類型的構造器(它本質上是可能修改某些實例數據字段的一個方法)。new操作符會返回Manager對象的內存地址,該地址保存在變量e中(e在線程棧上)。

 

以上內容說明了Employ 類型的應用e指向了一個Manager類型的實例,而在這個實例對象中包含了所有Manager類型以及其基類中定義的所有實例字段,如下圖所示:

 

按理說既然e的引用指向了Manager對象的實例,就可以訪問其實例中的任何可訪問的資源,包括實例字段,

那么:

   class Program
{
static void Main(string[] args)
{
Father father = new Child();
Child child = new Child();
Console.WriteLine(father.s);
}
}

這里father.s應該是可以訪問的,但是事實上是不能訪問的。這里正是我疑惑的地方。

想了很久,我覺得應該是在Father father = new Child();進行隱式的類型轉換時CLR做了一些事情,所以我想搞明白在這種情況下CLR會做些什么操作?

剛開始我覺得是改變了實例對象的類型對象指針,使得對象的類型發生了變化,但是后來覺得這樣也不對,因為類型對象中並不存儲實例字段,即便改變了類型對象的指針,也不可能知道是否存在這樣的實例這段啊,而且根據實驗的結果,無論怎樣轉換類型,對象實例的類型永遠都是創建類型時類型對象指針指向的那個類型,即原本類型,事實上是不會被改變的。

 

百思不得其解,在這里求助高人,望大家不吝賜教!還請各位積極發表看法,討論一下在類型轉換時CLR會執行那些具體的操作。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM