從物件的記憶體角度來理解「父類的引用指向子類的物件」

2021-07-09 05:37:07 字數 3053 閱讀 4335



多型中總不理解father f = new son()是怎麼引用子類物件的,現在從從物件的記憶體角度來理解試試

.假設現在有乙個父類

father,

它裡面的變數需要占用

1m記憶體

.有乙個它的子類

son,

它裡面的變數需要占用

0.5m記憶體.

現在通過**來看看記憶體的分配情況

:father f = new father();//

系統將分配

1m記憶體

.son s = new son();//

系統將分配

1.5m記憶體!

因為子類中有乙個隱藏的引用

super

會指向父類例項

,所以在例項化子類之前會先例項化乙個父類

,也就是說會先執行父類的建構函式.由於

s中包含了父類的例項,所以

s可以呼叫父類的方法

.son s1 = s;//s1

指向那1.5m

的記憶體.

father f1 = (father)s;//

這時f1

會指向那

1.5m

記憶體中的

1m記憶體

,即是說

,f1只是指向了

s中例項的父類例項物件,所以

f1只能呼叫父類的方法

(儲存在

1m記憶體中

),而不能呼叫子類的方法

(儲存在

0.5m

記憶體中).

son s2 = (son)f;//

這句**執行時會報

classcastexception.因為f

中只有1m記憶體,

而子類的引用都必須要有

1.5m

的記憶體,

所以無法轉換

.son s3 = (son)f1;//

這句可以通過執行,這時

s3指向那

1.5m

的記憶體.

由於f1是由s

轉換過來的

,所以它是有

1.5m

的記憶體的

,只是它指向的只有

1m記憶體

.示例:

class father;

}class son extends father

void show()

}class demo}

1 .如果你想實現多型

,那麼必須有三個條件

,父類引用

,子類物件

,方法覆蓋你這裡如果

fathor

類有乙個

show()方法,

那麼形成方法覆蓋

,那麼此時就可以這麼寫

:obj.show(),

此刻形成了多型

. 2. 

沒有方法覆蓋

,那你這裡只能解釋為父類引用去訪問乙個子類的方法,當然

,父類引用沒有這麼大範圍的許可權

,當然會報錯 

ps:多型實際上是一種機制

,在編譯時刻

,會生成一張虛擬表

,來記錄所有覆蓋的方法

,沒有被覆蓋的方法是不會記錄到這張表的

.若乙個父類引用呼叫了沒有覆蓋的子類方法

,那麼是不符合該錶的

,那麼編譯時刻就會報錯

. 在執行程式的時候

,虛擬機會去這張虛擬表中找覆蓋的方法

,比如引用中實際上存的是乙個子類物件引用

,那麼就會去找子類中的相應的覆蓋的方法來執行

定義乙個父類型別的引用指向乙個子類的物件既可以使用子類強大的功能,又可以抽取父類的共性。

所以,父類型別的引用可以呼叫父類中定義的所有屬性和方法,而對於子類中定義而父類中沒有的方法,它是無可奈何的;

同時,父類中的乙個方法只有在在父類中定義而在子類中沒有重寫的情況下,才可以被父類型別的引用呼叫;

看下面這段程式:

class father

//這是父類中的

func2()

方法,因為下面的子類中重寫了該方法

//所以在父類型別的引用中呼叫時,這個方法將不再有效

//取而代之的是將呼叫子類中重寫的

func2()

方法public void func2()

}class child extends father

//func2()

重寫了父類

father

中的func2()

方法//

如果父類型別的引用中呼叫了

func2()

方法,那麼必然是子類中重寫的這個方法

public void func2()

}public class polymorphismtest }

上面的程式是個很典型的多型的例子。子類

child

繼承了父類

father

,並過載了父類的

func1()

方法,重寫了父類的

func2()

方法。過載後的

func1(int i)

和func1()

不再是同乙個方法,由於父類中沒有

func1(int i)

,那麼,父類型別的引用

child

就不能呼叫

func1(int i)

方法。而子類重寫了

func2()

方法,那麼父類型別的引用

child

在呼叫該方法時將會呼叫子類中重寫的

func2()

。那麼該程式將會列印出什麼樣的結果呢?

很顯然,應該是

「ccc」。

變數是不存在重寫覆蓋的!

public class a 

public class b extends a 

測試類裡呼叫了這個方法

void compare()

控制台出來的是

overrided

類中的屬性是沒有多型性的,即你在引用上面使用屬性時,系統只會去找引用的靜態型別中的那個屬性,而與它的實際型別無關。

靜態方法也是沒有多型性的。

從物件的記憶體角度來理解「父類的引用指向子類的物件」

從物件的記憶體角度來理解試試 假設現在有乙個父類 father,它裡面的變數需要占用 1m記憶體 有乙個它的子類 son,它裡面的變數需要占用 0.5m記憶體.現在通過 來看看記憶體的分配情況 father f new father 系統將分配 1m記憶體 son s new son 系統將分配 1...

從記憶體四區的角度來理解C 中的類

下屬專案 測試用例數量結論無 0試驗無1 先給出記憶體四區的概念 堆區 棧區 全域性區 區。詳情可自行搜尋,此處不作贅述。c 類中物件的成員變數和成員函式是分開儲存的。普通成員變數 儲存於物件 棧區或堆區 中,與struct變數有相同的記憶體布局和位元組對齊方式 會補齊 靜態成員變數 儲存於全域性區...

從記憶體和物件的角度看C 類的靜態

提綱 1,c 的記憶體分割槽 stack heap和靜態儲存區 2,靜態物件和例項物件 3,使用規則 4,應用場景 一 c 的記憶體分割槽和物件模型 參考 c primer plus 第9章 記憶體模型和命名空間 c 中用 持續性 作用域和鏈結性 三個屬性來表徵其儲存特性,包括變數和函式。c 的記憶...