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

看板C_and_CPP作者 (偶爾想擺爛一下)時間15年前 (2010/02/11 12:38), 編輯推噓2(2026)
留言28則, 3人參與, 最新討論串3/3 (看更多)
※ 引述《littleshan (我要加入劍道社!)》之銘言: : 是的,答案就是利用 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 後,我想結果應該會符合你的預期。 另外也可以考慮使用 static_cast 來偏移 D* pointer。 D *p = new D; cout << &static_cast<B*>(p)->a << endl; cout << &static_cast<C*>(p)->a << endl; cout << "D object:" << p << endl; cout << "B object in D:" << static_cast<B*>(p) << endl; cout << "C object in D:" << static_cast<D*>(p) << endl; *補充一點: 沿用 QQ29 的 class A, B, C, D 定義,這樣子的碼很常見: B* bP = new D; 實際上它就是等同: B* bP = static_cast<B*>(new D);// 我這次不提 bP 的值與 new D 是有偏差的 :D -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 218.173.136.12

02/11 22:59, , 1F
我在看inside COM第一個範例看完我才知道轉型會偏移pointer..
02/11 22:59, 1F

02/11 23:00, , 2F
不過比較不確定的是vptr會不會跟著從A繼承到D...
02/11 23:00, 2F

02/11 23:00, , 3F
這幾天問的文章想說過年來一次好好看懂= =
02/11 23:00, 3F

02/12 00:03, , 4F
雖說會偏移,但用 == 去比對還是有效,所以其實不需要特別
02/12 00:03, 4F

02/12 00:03, , 5F
去在意它。
02/12 00:03, 5F

02/12 00:09, , 6F
需不需要知道這東西見仁見智。在 coding 上不會用到者
02/12 00:09, 6F

02/12 00:09, , 7F
自然可以不在意之。
02/12 00:09, 7F

02/12 00:11, , 8F
但有時會遇到不得不用,或是因為不知道這觀念而造成
02/12 00:11, 8F

02/12 00:12, , 9F
自己解決不了的 bug。
02/12 00:12, 9F

02/12 00:13, , 10F
有多重繼承又習慣使用 c-style casting 者要特別小心
02/12 00:13, 10F

02/12 00:20, , 11F
coding 上會用到就糟糕了,比習慣用 c-style casting 還要
02/12 00:20, 11F

02/12 00:20, , 12F
慘,那代表更誇張的觀念性錯誤。
02/12 00:20, 12F

02/12 00:20, , 13F
典型的例子就是做 hash table 拿 pointer 當 key。
02/12 00:20, 13F

02/12 00:21, , 14F
拿 pointer 本身當 key 還無所謂,最慘的是轉成整數型別。
02/12 00:21, 14F

02/12 00:29, , 15F
請問這些例子點出使用 static_cast 有什麼觀念性錯誤?
02/12 00:29, 15F

02/12 00:30, , 16F
我是在回 1F,不是回本文。
02/12 00:30, 16F

02/12 00:30, , 17F
你回了之後才是回你的。
02/12 00:30, 17F

02/12 00:31, , 18F
4F 那邊回的單純是 address 會變這件事不是那麼重要。
02/12 00:31, 18F

02/12 00:34, , 19F
@tinlans: 看來是我誤解你的意思了~~~
02/12 00:34, 19F
※ 編輯: sbrhsieh 來自: 218.173.134.25 (02/12 00:39)

02/12 00:35, , 20F
所以我後面回你 6F 的部分是從 1F -> 4F -> 6F 這種順序看
02/12 00:35, 20F

02/12 00:37, , 21F
那我可以問問 static cast到底跟c style最關鍵的差異在哪阿
02/12 00:37, 21F

02/12 00:38, , 22F
一直覺得他們很像...要是compile會錯 寫這兩種都會錯...
02/12 00:38, 22F
c-style casting 指 (type) 這種 casting 寫法。它的語意是隨著使用情況而異。 int n = (int) 3.14; // 同 static_cast float *fp = (float*) &n; // 同 reinterpret_cast char *str = (char*) "Hello"; // const_cast 因為 c-style casting 的語意不明確,所以 C++ 訂了四種不同語意的 casting: static_cast const_cast reinterpret_cast dynamic_cast 讓 programmer 可以更明確地向 compiler 表示意圖。(而不是任由 compiler 決定) ※ 編輯: sbrhsieh 來自: 218.173.134.25 (02/12 00:55)

02/12 00:55, , 23F
差別在於你用 C-style casting 是在考驗看 code 的人。
02/12 00:55, 23F

02/12 00:56, , 24F
假設 D 多重繼承 B1, B2,你對 D instance 用 (B2 *) 就是
02/12 00:56, 24F

02/12 00:57, , 25F
static_cast,但是用 (C *) 這種不相干的 type,又會變成
02/12 00:57, 25F

02/12 00:57, , 26F
reinterpret_cast;reinterpret_cast 不會幫你修 address
02/12 00:57, 26F

02/12 00:58, , 27F
。為了確認你到底寫那行想做什麼,還要去翻繼承關係。
02/12 00:58, 27F

02/12 01:01, , 28F
修個筆誤:D instance 改成 pointer to D instance。
02/12 01:01, 28F
文章代碼(AID): #1BS_f6qt (C_and_CPP)
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 3 之 3 篇):
問題
0
7
文章代碼(AID): #1BS_f6qt (C_and_CPP)