用于向下轉化。 父類引用指向指類對象
假設父親是a, 子類是b.
B* pb = new B; 子類對象
A* pa 父類引用指向子類對象,
那么向上轉化 Apa = pb 這個是自動完成的,隱式轉化,不需要dynamic_cast
向下轉化指的是
A pa = new B。 這個是指向子類對象的父類引用, 轉化為子類引用
B *b = dynamic_cast<B*>(pa)
總結就是 父類 向下轉化為子類, 但是父類指針本身是指向子類的。
而不是說指向父類的指針轉化為指向子類的指針,這個是無法轉的。
2. 舉例說明用法
首先,類X和類A都是基類,各自有虛析構函數。然后,類B公有繼承自A,類C公有繼承自B,所以C的繼承鏈是C→B→A。接著,類D公有繼承自X和C,也就是多重繼承,D的基類是X和C,而C又繼承自B和A。因此,D的繼承結構應該是D同時繼承X和C,而C又繼承B和A。所以D的完整繼承鏈是D→X,D→C→B→A。
現在來看各個選項:
選項A:D* pd = new D; A* pa = dynamic_cast<A*>(pd);
這里pd是D類型的指針,轉換為A*。因為D繼承自C,而C繼承自B和A,所以D是A的派生類。因此,從D到A是上行轉換(upcast),這種轉換是安全的,不需要dynamic_cast,直接隱式轉換即可**(父類引用指向子類對象,安全的,直接隱式轉化)**。但即使使用dynamic_cast,結果也是有效的,pa會指向D對象中的A子對象部分。所以選項A的轉換是合法的,結果成功。
選項B:B* pb = new B; D* pd = dynamic_cast<D*>(pb);
這里pb是B類型的指針,嘗試轉換為D*。因為D繼承自C,而C繼承自B,所以D是B的派生類。但pb實際指向的是B對象,而不是D對象。dynamic_cast在下行轉換(downcast)時,會檢查對象的實際類型是否為目標類型。由于pb指向的是B對象,而不是D對象,所以轉換失敗,返回nullptr。因此選項B的轉換是合法的,但結果失敗,pd為nullptr。
選項C:A* pa = new D; X* px = dynamic_cast<X*>(pa);
pa是一個指向D對象的A指針。D繼承自X和C,而C繼承自B和A。因此,D對象中包含X和A的子對象。這里要將A轉換為X。由于A和X之間沒有直接的繼承關系,但因為D同時繼承了X和C(而C繼承自A),所以D對象中包含X和A的子對象。dynamic_cast在這種情況下,可以進行跨基類的轉換,前提是兩個基類都在同一個對象中。這里,pa指向的是D對象的A子對象,要轉換到X子對象,需要通過D的類型信息。由于D確實繼承自X,所以dynamic_cast應該可以找到X的子對象,轉換成功。因此選項C的轉換是合法的,結果成功,px指向D對象的X子對象。
選項D:A* pa = new C; C* pc = dynamic_cast<C*>(pa);
pa是一個指向C對象的A指針。因為C是A的派生類(C→B→A),所以這里從A到C是下行轉換。由于pa實際指向的是C對象,dynamic_cast會檢查類型是否匹配。因為C確實是A的派生類,所以轉換成功,pc指向原來的C對象。所以選項D的轉換是合法的,結果成功。
不過,我需要再仔細檢查選項D的描述是否正確。實際上,C是A的派生類,所以存在繼承關系。因此,選項D的dynamic_cast是合法的,且轉換成功。
3. 原理說明:A* pa = new D; X* px = dynamic_cast<X*>(pa); 通過畫出內存布局來解釋,為什么可以使用轉化
B* pb = new B; D* pd = dynamic_cast<D*>(pb); 通過內存布局分析這個為甚不可以轉化