Re: [問題] 多重繼承疑惑

看板C_and_CPP作者 (我要加入劍道社!)時間15年前 (2010/02/11 09:52), 編輯推噓3(303)
留言6則, 4人參與, 最新討論串2/3 (看更多)
※ 引述《QQ29 (我愛阿蓉)》之銘言: : 有點走火入魔了.... : 現在試著了解一下多重繼承 : http://nopaste.csie.org/5f8d3 : 這是不使用虛擬繼承跑跑看的結果 : 發現new的 和 直接用物件 印出來的結果竟然有差異 : 先拿物件的方式印來看 : A::a 分給B::a 和C::a 因為D先繼承C 所以A::a和C::a是同一個變數 : 位址一樣...可以接受(這也是更改繼承順序得到的心得....) : 但是我用new來看結果發現A::a 是一個 B::a和C::a竟然是一樣 很奇怪 咳咳...你用了錯誤的轉型。 先來看看你如何把 p 轉型成 B*: cout<<&( ((B*)&p)->B::a )<<endl; 首先你用 &p 就錯了...&p 是 B**,也就是指向指標的指標,而不是指向 A 的指標。 因此至少你要改成: cout<<&( ((B*)p)->B::a )<<endl; 不幸的是,這樣做的結果不如預期。你的想法可能是: 「p 的型別雖然是 A*,但它實際上指向 D 物件,我希望取出這個 D 物件中, 屬於 B 的那部份」 OK...現在,假設你是 compiler,你要怎麼知道「p 實際指向一個 D 物件」? 事實上是 compiler 根本無法知道 p 指向什麼,因為同樣的 code 我們可以這樣寫: void print(A* p) { cout<<&( ((B*)p)->B::a )<<endl; } print(new A); print(new B); print(new C); print(new D); 你注意到了嗎...compiler 根本就無法知道他接的 p 是來自於哪一種物件, 所以你寫 (B*)p,其實就只是把 p 的內容「直接」當成一個指向 B 的指標, 而不是「p 其實是個 D*,而 D 裡面有 B,所以應該取出 D 裡面的那份 B」, compiler 不知道 p 真正指向什麼的。 如果上面的東西你能理解,我們繼續來看要怎麼解決這問題。 回想一下我上一篇提到 virtual function,想一下: 如果 a 這個東西並不是某個 member variable 而是 member function, 為什麼 compiler 會知道 p 的真正形別? void print(A* p) { // 我不知道 p 指向什麼,但我可以從 vtable 中找出 function pointer cout << p->a() << endl; } print(new A); // 使用 A::a() print(new D); // 使用 D::a() 是的,答案就是利用 vtable。事實上 compiler 在 vtable 中, 除了加入 function pointer 之外,還會記錄這個 vtable 屬於哪個 class。 而 C++ 提供了 dynamic_cast 這個轉型用的 operator,幫助你在這種情況下轉形。 所以你的 code 要改成這樣: A *p =(B*) new D; cout << &(p->A::a) << endl; cout << &( (dynamic_cast<B*>(p) )->B::a) << endl; cout << &( (dynamic_cast<C*>(p) )->C::a) << endl; dynamic_cast<B*>(p) 的意思是說,我不知道 p 真正指向哪一種 class, 但我想利用 vtable 中的資訊,試圖把 p 「正確地」轉成 B*。 改用 dynamic_cast 後,我想結果應該會符合你的預期。 : 於是我把C和B class都加上virtual public: http://nopaste.csie.org/3e47e : 物件的方式印出 全部都一樣 恩~可以接受 : 但是用new的方式印 : 奇怪A::a 又和其他不一樣了? : 是我cout寫錯嗎 new的和用物件的方式怎麼會有差異 : 請教一下 : 謝謝 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 140.112.29.108

02/11 18:57, , 1F
..................我太誇張了 &p .....我瞎了!!!!
02/11 18:57, 1F

02/11 19:08, , 2F
謝謝l大 有許多東西可以補強我的觀念 謝謝你
02/11 19:08, 2F

02/11 20:42, , 3F
要使用 RTTI(dynamic_cast) 必須得是 polymorphic type
02/11 20:42, 3F

02/11 20:43, , 4F
polymorphic type: class 要有 virtual function(vtable)
02/11 20:43, 4F

02/11 20:49, , 5F
天阿!為什麼強者這麼多! m不完啦 XD
02/11 20:49, 5F

02/12 00:26, , 6F
推佛心的l大....:)
02/12 00:26, 6F
文章代碼(AID): #1BSzD5hj (C_and_CPP)
討論串 (同標題文章)
本文引述了以下文章的的內容:
問題
0
7
以下文章回應了本文
完整討論串 (本文為第 2 之 3 篇):
問題
0
7
文章代碼(AID): #1BSzD5hj (C_and_CPP)