C 向上轉型,為什麼不需要強制轉換?

時間 2021-05-31 22:09:33

1樓:

從邏輯上講Drived "IS A" Base,所以Drived可以作為Base來訪問。

C++對於這個邏輯的一種常見的實現是在記憶體中子類首先包含其繼承的所有基類,然後再是子類自己

比如Derived的在記憶體中的表達是:

Derived Object Memory Layout:

dgtBase......|

Derived..|

d指標指向的是derived object的開始位置。

b = d,編譯器可以毫無顧慮的把d的值賦給b,因為它知道賦值完了之後,b指向的是derived object的Base部分,所以可以按Base正常訪問。

但是d = b 就不能無憂無慮了,因為b指向的是乙個base類,編譯器不能確認它是不是乙個derived object, 這時候需要你來告訴編譯器(也就是強制型別轉換),b指向的實際上是乙個derived object。

補充的例子跟多型沒什麼關係,還有「根據資料大小來決定是否需要型別轉換」這個依據是invalid的。正如 王勐 所說,型別轉換實際上是告訴程式如何去理解這塊記憶體。

2樓:潘安仁

在底層的記憶體裡,C++的類是父類的成員後面跟著子類的成員變數,所以父類物件能用的地方放個子類物件一樣能用。

當然說虛函式肯定還是要還原回去,就是虛表指標換一下。----這裡剛才說錯了,其實虛表指標不變,形成多型。

回到問題,子類向上轉型,其實就相當於你不用子類多出來的成員變數而已,當然是安全的了。不過考慮到虛函式的問題,如果子類重寫了父類的虛函式,那向上轉父類以後再調那個虛函式,其實調的可是子類的虛函式,而不是父類的了。

向上轉以後再向下轉的話可能就沒這麼幸運了,除非之前的記憶體都沒被破壞掉。

3樓:徐辰

sockaddris-not-asockaddr_in,這兩個型別根本就不是父子型別關係,只是碰巧尺寸一樣而已(其實還不一定是一樣的尺寸,因為它們都可以包含實現的細節),碰巧尺寸一樣的東西總不能隨便互換吧,哪個程式語言也不敢這麼設計啊。

4樓:張砸鍋

struct sockaddr 和 struct sockaddr_in 是 C 的資料結構,不是 C++ 類,當然不能用黎克特制替換原則。

至於說這兩個結構內容、大小一樣,是因為目前99.999%的網路應用都是基於Internet的 TCP/IP 協議,還沒有發展出其他網路被普遍使用,所以socket的位址也只有internet格式的sockaddr_in。sockaddr是當時保留以後擴充套件其他形態的網路用的。

5樓:付三歲

設計模式的角度,根據黎克特制代換原則,任何基類可以出現的地方,子類一定可以出現。

向上轉型可以理解成子類包含父類的所有資訊,所以父類替換成子類是沒有任何問題。

向下轉型子類替換成父類,因為父類是有可能不含有子類的相關資訊的。需要人為確認這樣

轉化是沒有問題的。所以語法上需要強制轉換。

6樓:JayChen

把Base改成People,Derived改成Student,你會發現,學生是人,人不一定是學生,所以P(People)=S(Student)很正常

7樓:Milo Yip

如果要從記憶體去解釋,就是合法的Dervied指標指向的物件會包含其Base的資料,語法上容許自動cast是為了方便。但語意上最好要符合Liskov替代原則。

8樓:

邏輯上來說,就像@藍色說的一樣,很好理解。

實現上來說,因為C++構造物件的方式保證了派生類啟始位址到 sizeof超類的記憶體區域和超類結構相同。強制型別轉換後訪問成員變數和函式的時候並不會產生錯誤。

理解這個問題的關鍵我認為在於需要從更底層的角度思考問題,指標本質是整數,它只表明了記憶體的起始位址,卻沒有指明對於這塊區域存放的資料需要怎麼解釋(資料在最底層沒有不同,都可以解釋成int和float或任何資料型別)。這樣,為了賦予乙個記憶體塊唯一的解讀方法,讓資料有意義,高階語言給指標加上了型別。回到題目來說,這個指標在型別轉化後值沒有改變,改變的是解釋方式。

為了使新的解讀同樣合理有效,只要保證派生類具有第二段的性質即可。

如果想深入,這也可以引申出虛函式和實函式等等一系列的問題。

為什麼父母不需要考試?

lzsj 我們先想象下,如果父母也要考試 採用3w 1h探索 what考什麼 when什麼時候考 where在哪考 how怎麼評判 what應該考父母手冊,你準備好迎接子女了嘛,你會用怎麼樣的方式撫養 教育孩子 與孩子相處。你現在工作穩定嗎,你有信心確保孩子能高枕無憂完成9年義務教育嗎,而不是把他 ...

為什麼nodejs不需要IO功能?

alsotang 專門來答個題支援一下 Twiknight 樓主的截圖是對 Node.js 一開始技術選型的說明,而且樓主的問題是帶有曲解的。Node.js 是帶有 IO 功能的。但 js 作為一門程式語言是不帶有 io 功能的。js 只有語言規範,一開始主要是跑在瀏覽器中,而在瀏覽器中的 ajax...

為什麼說腹肌不需要練?

我我我我不知道 誰和你說腹肌不要練的,當然瘦的人線條會明顯,但這麼說的話人們哪塊肌肉要練嘞,瘦不就完事了嗎?人們總是關注腹肌,就像提到手臂,就想到肱二頭肌,這是乙個十分外行的表現。因為每一塊肌肉都會有對抗肌,例如內側的肱二頭肌和外側的肱三頭肌,要是想提高整個手臂的力量,那麼這兩塊肌肉都要足夠發達,如...