簡體   English   中英

將派生類對象分配給父類引用

[英]Assigning derived class object to a parent class reference

當我看到時,我總是感到困惑:

Parent ref = new Child();

其中Child類擴展Parent。

  1. 對象ref如何在內存中看起來像?
  2. 如何處理虛擬方法? 非虛?
  3. 它與以下內容有何不同:
Child ref = new Child();

對象在內存中的外觀如何?

你的問題不清楚。 有兩個相關的內存位置。 變量與存儲位置相關聯。 該存儲位置包含對另一個存儲位置的引用

變量的存儲位置通常實現為四字節或八字節整數,其中包含“托管指針” - 垃圾收集器已知的內存地址。

對象的內存布局也是CLR的實現細節。 與對象關聯的內存緩沖區將包含對象的所有數據 - 字段的所有值和諸如此類的東西。 它還包含對另一個內存位置的引用,該對象的虛函數表

然后,虛函數表(vtable)包含更多引用 ,這次引用引用與最派生類型的對象關聯的方法。

如何處理虛擬方法? 非虛?

通過從變量中查找對象引用,然后查找vtable,然后在vtable中查找方法,然后調用該方法來執行虛方法。

非虛方法不是通過vtable調用的,因為它們在編譯時是已知的。

它與......有什么不同?

在對象上調用的非虛方法將根據變量的類型調用方法的版本。 調用對象的虛方法將根據變量引用的對象的類型調用方法的版本。

如果不是很清楚,您可能需要閱讀我的文章,該文章解釋了如何使用沒有它們的語言“模擬”虛擬方法。 如果你能理解如何自己實現虛擬方法在沒有他們的語言,這將有助於你了解我們如何其實實現虛擬方法。

http://blogs.msdn.com/b/ericlippert/archive/2011/03/17/implementing-the-virtual-method-pattern-in-c-part-one.aspx

ref是一個Child對象。 Child類上調用虛方法。 但是,僅在Child類中定義的方法在分配給Parent對象時不可見。

如果foo()不是虛擬的,那么編譯將根據變量ref的聲明類型選擇一個方法。 如果你有Parent ref = new Child(); 然后將調用Parent.foo() 如果您有Child ref = new Child(); 然后將調用Child.foo() 當然,在這種情況下,C#編譯器會要求您在Child.foo()的聲明中使用new來表示您的意思是隱藏Parent的實現。

我想ref只包含可以找到引用的Child對象的地址。 如果調用虛方法,則調用的實際方法取決於對象的動態類型( Child ); 如果調用非虛方法,則取決於靜態類型( Parent )。 它與Child ref = ...不同,因為在那一個中​​,靜態類型是Child而不是Parent

我希望這不是功課:)

可以這樣想(假設Parent不是抽象類)

Parent ref = new Child();

Parent ref = new Parent();

大致相同,除了在Child中重寫的虛擬方法將被調用,而不是后者。

聲明對象的類型將確定可用的方法。 聲明一個對象是一個不像你實例化它的特定類型 - 前一種情況 - 影響在運行時調用哪些方法,但前提是這些方法被聲明為抽象或虛擬。

在任何一種情況下,假設您在ref上調用了方法foo 運行時在類Parent上很好的方法foo 然后,運行時將查看foo為虛擬(或抽象)。 如果foo不是虛擬的或抽象的,那么運行時會調用foo Parent定義然后在那里,並完成它。 但是,如果foo 虛擬的或抽象的,運行時將檢查ref是否真的被實例化為覆蓋foo的更具體的類型。 如果是的話,它會調用 foo

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM