[問題] 子類別陣列轉型成父類別指標問題

看板C_and_CPP作者 (AA)時間12年前 (2012/06/06 19:32), 編輯推噓7(7030)
留言37則, 10人參與, 最新討論串1/3 (看更多)
開發平台(Platform): (Ex: VC++, GCC, Linux, ...) C++ 額外使用到的函數庫(Library Used): (Ex: OpenGL, ...) 問題(Question): 對於轉型的部份不熟悉 想請問高手這樣寫是否會有問題, 如果把子類別的陣列餵進父類別的指標 接下來對陣列取值可以取到正確的值嗎 程式碼(Code):(請善用置底文網頁, 記得排版) class Base { protected: int a; public: int getA(){ return a; } }; class Derived : public Base { protected: int b; }; class Set { protected: Base* dataArray; public: run1() { int c = 5; dataArray = new derived[c]; cout << dataArray[3].getA(); // case 1 } }; run2(Base* b, int index ) { cout << b[index].getA(); } int main() { Set set1; set1.run1();//case 1 Derived set2[5]; run2(set2, 3);// case 2 return 0; } 想請問case1和case 2這兩個情況下是否能夠提取到正確的 a 因為Base和Derived不一樣大 用Base陣列下去算Derived的東西似乎會錯? 然後也請強者解釋一下我的觀念 非常感謝 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 60.248.182.130

06/06 21:08, , 1F
你的疑慮是對的,這樣做會爆炸
06/06 21:08, 1F

06/06 21:08, , 2F
請見 more effective c++ 條款3
06/06 21:08, 2F
那請問一下如果想做類似case 1 的處理(把子類別陣列丟到某東西處理) 要怎麼寫比較方便 我知道可以用雙重指標 不過這樣寫還是不太直觀 ※ 編輯: whoowh 來自: 114.34.216.47 (06/06 22:10)

06/06 22:12, , 3F
boost::ptr_vector
06/06 22:12, 3F
請問是類似這樣的作法嗎...? http://davidlwq.iteye.com/blog/1127797

06/06 22:19, , 4F
想請問你為什麼會有這種需求, 硬要透過父類別指標, 來存取
06/06 22:19, 4F

06/06 22:20, , 5F
可以繼承下去給子類的介面
06/06 22:20, 5F
要詳細解釋可能可以這樣說: 父類別是水果 然後子類別是蘋果 然後接下我希望在某個類別可以寫 "一次處理一大串水果的函數" 所以定義了水果指標 然後丟一個蘋果陣列進去讓他處理 可是會有問題就不知道要怎麼辦這樣 如果只針對蘋果做處理那當然OK 不過這樣就不夠廣義 有點頭痛~"~

06/07 00:46, , 6F
用interface如何
06/07 00:46, 6F
想請問這邊怎麼做

06/07 00:51, , 7F
他的重點是陣列存指標會混淆多型的 offset
06/07 00:51, 7F
※ 編輯: whoowh 來自: 114.34.216.47 (06/07 01:51) ※ 編輯: whoowh 來自: 114.34.216.47 (06/07 01:52) ※ 編輯: whoowh 來自: 114.34.216.47 (06/07 02:11)

06/07 02:22, , 8F
http://ideone.com/dfSj0 類似這種寫法可以嗎?
06/07 02:22, 8F
這樣好像會run time error 我猜轉成最基底的話編譯器不知道陣列的offset多大.. ※ 編輯: whoowh 來自: 60.248.183.2 (06/07 10:03)

06/07 10:24, , 9F
虛擬函式呢??
06/07 10:24, 9F

06/07 10:25, , 10F
virtual function 不就是為了這種情況而出現的嗎
06/07 10:25, 10F

06/07 10:35, , 11F
唔,我的範例是可以的,為什麼你的不行我就不懂了
06/07 10:35, 11F

06/07 11:12, , 12F
因為 james 的物件大小剛好都一樣
06/07 11:12, 12F

06/07 11:36, , 13F
咦咦,原來會有這樣的問題
06/07 11:36, 13F

06/07 12:27, , 14F
這跟虛擬函式沒有關係 是元素 offset 的問題
06/07 12:27, 14F

06/07 12:28, , 15F
如果建一個陣列內含所有元素的"Base*"指標如何?
06/07 12:28, 15F

06/07 12:29, , 16F
(這個其實是 java 的做法的概念就是了)
06/07 12:29, 16F
是說像這樣嗎 我現在的作法是 Base** pDataArray; pDataArray = new Base*[numOfObjects]; 要用物件的時候 pDataArray[i]->getA(); ^^^^^^^^^^^^^這個指標可以拿來指derived物件 不過總覺得很不直觀.... ※ 編輯: whoowh 來自: 210.66.52.167 (06/07 12:34) ※ 編輯: whoowh 來自: 210.66.52.167 (06/07 12:35)

06/07 12:41, , 17F
我終於看懂這個問題了...XD
06/07 12:41, 17F

06/07 12:41, , 18F
差不多是這樣沒錯 不直觀個人覺得是指標語法的問題...
06/07 12:41, 18F

06/07 12:50, , 19F
不太懂哪裡不直觀,這不才是正常用法嗎XDDDD
06/07 12:50, 19F

06/07 13:14, , 20F
你所謂的"直觀"實際上是對語意上的誤解, Derived is a
06/07 13:14, 20F

06/07 13:14, , 21F
Base 物件, 但 Derviced '物件陣列' is not a Base
06/07 13:14, 21F

06/07 13:15, , 22F
'物件陣列', 再來就是對陣列做 [] 取值行為, 則是假設
06/07 13:15, 22F

06/07 13:15, , 23F
該處有 Base 物件存在, 但跟你講的水果意義上差別很大
06/07 13:15, 23F

06/07 13:16, , 24F
沒有'水果'這種東西, 但是有香蕉、蘋果等屬於'水果'的
06/07 13:16, 24F

06/07 13:17, , 25F
物品, 所以'水果'該是interface或是abstract class
06/07 13:17, 25F

06/07 13:17, , 26F
想當然爾用 [] 取值的行為就是不合法的, 因為這種物件
06/07 13:17, 26F

06/07 13:19, , 27F
無法被建構出來, 不想間接取值的話你用 ptr_vector
06/07 13:19, 27F

06/07 13:20, , 28F
不過如果在 Set 類別不消存有 Base* 成員, run1、run2
06/07 13:20, 28F

06/07 13:21, , 29F
用 template function 就可以作掉了
06/07 13:21, 29F

06/07 13:21, , 30F
按照 "你希望" 的描述方式...你要看看如何正確使用
06/07 13:21, 30F

06/07 13:21, , 31F
virtual function 比較好
06/07 13:21, 31F

06/07 13:24, , 32F
再噁心一點就用 boost::any XD
06/07 13:24, 32F

06/07 13:26, , 33F
但是你 new 的地方都寫死了, 那存 void* 就好, run1
06/07 13:26, 33F

06/07 13:27, , 34F
呼叫時再透過模板引數指定型別即可
06/07 13:27, 34F

06/07 13:33, , 35F

06/07 13:36, , 36F
set 用來存指標
06/07 13:36, 36F

06/07 13:37, , 37F
物件本身則存在陣列裡或是用 new 的
06/07 13:37, 37F
文章代碼(AID): #1Fpp_K65 (C_and_CPP)
討論串 (同標題文章)
文章代碼(AID): #1Fpp_K65 (C_and_CPP)