→ angleevil:是不是因為你沒加虛擬解構函式? 02/14 09:48
→ angleevil:虛擬解構函式出現undefined reference to vtable for A 02/14 09:54
→ angleevil:超哥不好意思,麻煩你把這三段刪除掉,因為那不是問題點 02/14 10:06
→ james732:不會啊,你沒講的話,我都忘了虛擬解構函式這東西了 02/14 10:13
推 shadow0326:應該是因為把A ptr cast成B的關係, A和B並無derive 02/14 10:30
→ shadow0326:直接call ((C*)p)->sub() 就是對的 02/14 10:31
推 cuteclare:cout << ((B *)((C *)p))->sub() << endl; 02/14 10:36
→ cuteclare:orz沒看後面的code就直接推文...我錯了~><~ 02/14 10:38
→ angleevil:基本上碰到這種做法,我會使用抽像類別讓A,B去繼承 02/14 10:41
→ angleevil:所以A,B class中的運算式暫時註解掉.effective c++有提 02/14 10:44
→ angleevil:到詳細做法,只是我手上沒書.看看有沒有其他人可以補充 02/14 10:44
→ shadow0326:可以用dynamic_cast<B*>硬幹, 不過超低效 XD 02/14 10:45
→ cuteclare:oh 對唷...完全忘記還有dynamic_cast 02/14 10:49
→ angleevil:樓上,我硬幹過了,結果是失敗. 02/14 10:50
→ cuteclare:樓上 cout << (dynamic_cast<B*>(p))->sub() << endl; 02/14 10:52
→ cuteclare:我這樣可以欸.我是用gcc version 4.5.2 (GCC) 02/14 10:53
→ angleevil:真的要用,我會直接用(dynamic_cast<C*>(p))->sub().畢竟 02/14 10:57
→ angleevil:c本來就有B的功能了.不過我學起來,謝謝兩位. 02/14 10:58
我沒有強調一個重點,這兩個 parent class 裡,有一個不是我寫的
它其實是 MFC 的 CDialog class
所以沒辦法在 class A, class B 上面再加一層 Abstract
另外,我一直不知道 dynamic_cast 什麼時候會用到,這篇總算讓我懂了 XD
推 shadow0326:所以我說直接call ((C*)p)->sub() 就是對的, 只是不知 02/14 11:00
→ shadow0326:道原本要特地cast成B的use case是什麼就是了 @_@ 02/14 11:01
哎呀,是我沒有說清楚
其實我的情況還會有一個 D, 同樣繼承 A 與 B
在程式執行的時候會藉由建立 C 或 D 的實體,來做不同的事情
而且工作會改變的是 B 介面的部份
用原本的例子改起來就像這樣 http://ideone.com/RUFzz
我有點驚訝這兩行程式碼竟然可以正確執行,得到我要的答案
A *p = new D;
cout << ((C *)p)->sub() << endl;
不過總覺得看起來好怪異...
→ angleevil:盡量還是用c++的轉型,c的轉型不是很適合OO 02/14 11:12
推 NIKE74731:angleevil大的作法會構成Death Diamond吧@@ 02/14 11:18
→ shadow0326:可以正確執行是因為C,D剛好成員數一樣, 這寫法也太不健 02/14 11:18
→ shadow0326:康了 @_@ 架構上要整個改過比較好吧 02/14 11:18
我也覺得很恐怖,所以才會想要轉成B
大概是類似這樣的感覺,會比轉成C還要合理
A *p = new C;
((B *)p)->sub();
delete p;
p = new D;
((B *)p)->sub();
→ ADF:static_cast< C* >( p )->sub(); 02/14 11:50
→ ADF:別用c的轉型 如果你要把B的pointer換成C且C的定義還沒出現 02/14 11:54
→ ADF:p轉型後資料會敗壞 02/14 11:56
→ angleevil:喔!終於搞懂NIKE74731的意思,當然class c不要同時繼承 02/14 12:31
→ angleevil:A和B是最好的,本人不是很專精OO的繼承技巧,大家也可以提 02/14 12:33
→ angleevil:出改進的方法.如果一定要有好的方法,那就是宣告B 物件 02/14 12:35
→ angleevil:然後將p dynamic_cast成B *.最後assign給B 物件. 02/14 12:37
推 NIKE74731:我很好奇既然是MFC的Class 竟然會有pure virtual func. 02/14 15:51
→ NIKE74731:這樣一來要使用這個類別就必須繼承且實作該virtual func 02/14 15:52
→ NIKE74731:MFC有這種Class嗎 02/14 15:53
唔,其實 CDialog 並沒有 pure virtual function (應該吧?)
我承認這裡是我的例子舉得不好XD
→ angleevil:其實如果你只要引用B 部分的功能,直接在C理面宣告 02/15 09:30
→ angleevil:B* getBptr,然後用一個成員函式包起來.ex: int sub(){ 02/15 09:32
→ angleevil:return getBptr->sub()} 這樣就可以了 02/15 09:33
可是我需要B的介面...XD
※ 編輯: james732 來自: 101.13.7.106 (02/15 09:46)
推 NIKE74731:那如果是C繼承A A繼承B 可解嗎? 02/15 17:33
→ angleevil:他應該care會很肥,所以一直不願意如此去解決 02/15 21:16
→ angleevil:可是超哥,我必須要說,你第三個方法基本上跟我在09:30 02/16 08:53
→ angleevil:提到方法差不多,晚點看我有沒有時間舉例出來 02/16 08:54
推 mingtai1:大量重複new/delete易造成memory fragmentation 不太建議 02/17 22:41