2009-12-05 82 views
4

我正在開發一款遊戲,我需要找到一種在遊戲中以char格式獲取某個'地圖塊'值的方法。我有一個可以照顧所有精靈的類DisplayableObject和一個照顧玩家對象的子類ThreeDCubePlayer。爲了便於渲染/更新所有內容,所有DisplayableObjects都存儲在一個數組中,第0個單元包含播放器(類型爲ThreeDCubePlayer)。 ThreeDCubePlayer具有與DisplayableObject不同的構造函數(它需要兩個附加參數),並且只有ThreeDCubePlayer具有我需要的GetMap()函數。所以,這裏是我迄今所做的:投射一個指向子類的指針(C++)

ThreeDCubePlayer* cubePlayer = &((ThreeDCubePlayer &)m_ppDisplayableObjects[0]); 

char mapEntry = GetMapEntry((int)*(cubePlayer->GetMapX()), (int)*(cubePlayer->GetMapY())); 

這是ThreeDCubeGame.cpp(控制地圖和鍵盤輸入功能)的一部分。我遇到的問題是這兩行在編譯時會給出'非法間接'錯誤。我認爲這個錯誤是當我試圖解引用不是指針的東西時,我確信cubePlayer看起來像一個指針...

有沒有人有我應該做什麼的想法?

+4

在C++中使用C風格轉換通常意味着你的代碼和/或你的設計有問題,但是從你在這裏發佈的內容來看,它很難說更多。 – 2009-12-05 16:14:02

+0

wayyyy許多演員。我們真正需要的是類聲明。 – 2009-12-05 17:30:31

回答

4

使用其中一種類型的安全鑄件,例如, dynamic_cast而不是C風格轉換。

如果m_ppDisplayableObjects是DisplayableObject **,那麼它會是這個樣子:

ThreeDCubePlayer* cubePlayer = dynamic_cast<ThreeDCubePlayer*>(m_ppDisplayableObjects[0]); 

if (cubePlayer != NULL) 
{ 
    char mapEntry = GetMapEntry(cubePlayer->GetMapX(), cubePlayer->GetMapY()); 
} 
else // Not a ThreeDCubePlayer* ... 
+0

謝謝 - 這解決了非法間接錯誤,但現在我得到這個錯誤: ThreeDCubeGame.obj:錯誤LNK2001:無法解析的外部符號「私人:靜態字符(* ThreeDCubeGame :: m_acMapData)[10]」(?m_acMapData @ ThreeDCubeGame @@ 0PAY09DA) 這是代碼中其他地方的問題嗎? – benwad 2009-12-05 16:44:25

+0

是的,這是代碼中其他地方的問題。您的代碼已成功編譯。這個錯誤是一個鏈接錯誤。這就是說ThreeDCubeGame :: m_acMapData已經被聲明瞭(你已經告訴程序了,甚至可以使用它),但是它還沒有定義(你沒有爲它保留任何空間)。 – richj 2009-12-05 18:36:04

+0

if(cubePlayer)... but yeah good point – timB33 2009-12-05 19:06:19

1

你投錯了,而且我覺得第二行需要在所有沒有投(取決於方法如何定義)。

它應該是:

ThreeDCubePlayer* cubePlayer = (ThreeDCubePlayer*)m_ppDisplayableObjects[0]; 

char mapEntry = GetMapEntry(cubePlayer->GetMapX(), cubePlayer->GetMapY()); 

在第一線演員也應該是一個C++風格的轉換,如:

ThreeDCubePlayer* cubePlayer = static_cast<ThreeDCubePlayer*>(m_ppDisplayableObjects[0]); 
1

對於第一線,你可以施放DisplayableObject到派生類ThreeDCubePlayer類型使用dynamic_cast

​​

對於第二行,您取消引用由ThreeDCubePlayer::GetMapX()返回的任何內容。如果這個函數沒有返回一個指針(或者一個超載的運算符類),你會得到一個編譯錯誤。

+0

dynamic_cast可以工作,但這裏不需要。 static_cast就足夠了。 – Frunsi 2009-12-05 16:11:59

+0

boost :: polymorphic_downcast <>可能是最好的使用方法。 static_cast的速度,但在調試模式下用dynamic_cast斷言。 – Macke 2009-12-05 16:17:19

+0

@frunsi,是的,一個static_cast可以工作,但是他從基礎向下派生到派生類,所以除非這裏真的是性能關鍵的代碼,否則動態類型轉換更合適。 – 2009-12-05 16:21:32

0

你還沒有太多的代碼去,但是我覺得你的第一行應該是:

ThreeDCubePlayer* cubePlayer = (ThreeDCubePlayer *) m_ppDisplayableObjects[0]); 

我們就需要看GetMapX的聲明()瞭解第二行。

3

一對夫婦的建議:

不要使用C風格的強制轉型,用正確的C++蒙上代替。就你而言,當你拋出繼承層次結構時,你應該使用dynamic_cast而不是大錘C型鑄造。這會產生一個小的運行時間開銷,但它也會使整個類型變得安全,因爲它不會因爲你將一塊$ deity_knows_what視爲ThreeDCubePlayer而在背後做一些令人討厭的事情。假設你m_ppDisplayableObjects數組實際持有的指針,它會是這樣的:

ThreeDCubePlayer *cubePlayer = dynamic_Cast<ThreeDCubePlayer *>(m_ppDisplayableObjects[0]) 
if (cubePlayer) { // Important, if you don't check for 0 here you might dereference a null pointer 
    ... cubePlayer->GetMapX() ... 

另外,如果你要投的GetMapX的結果,那麼你有一個阻抗不匹配,你應該理清別的地方;我建議調整GetMapX的返回類型或傳遞給GetMapEntry的參數。通常,不得不瘋狂地大肆渲染是設計問題的標誌 - 精心設計的C++代碼不應該需要大量的強制轉換,特別是不需要大量的C風格強制轉換。

1

請注意,在遊戲應用程序中,如果您最終在每個遊戲框架中投入大量dynamic_casts,可能會對性能產生負面影響。您通常會發現有人正在執行其他解決方案,以確定如何使用static_cast或C樣式轉換將存儲在容器中的對象指針重新轉換爲適當的對象類型,而不是依賴RTTI。根據對象類型的數量和其他因素,有多種方法可以做到這一點,但一個簡單的方法就是爲每個枚舉類型設置枚舉類id和get方法,如果類id不是'不符合要求的人。

0

ppDisplayableObjects是一個數組還是基指針不是嗎? 那麼試試這個?

const ThreeDCubePlayer* const cubePlayer = m_ppDisplayableObjects[0]; 
char mapEntry = GetMapEntry(cubePlayer->GetMapX(), cubePlayer->GetMapY()); 

GetMapX等應該返回一個(無符號)int?而不是一個int指針? (no negs?so unsigned?)

我想在其他人對鑄件的評論中,他們表明你的等級沒有正常工作,但是......但是如果你必須施放,那麼考慮你需要使用哪個C++類型是一個有用的練習,這也意味着當你想重新訪問/收緊你的代碼時,所有的類型變得更容易搜索和刪除。

ps - 你可以 並添加陣列等某種類的所有者類,也許是一個單身人士,如果你知道你只有一個

恕我直言...(對不起)寫一個自己的科恩斯類,讓你可以做GetMapE之類的事情ntry(const Coords & coords),而不是單獨獲取x和y值,這將節省您讓它們以錯誤的方式交換等。 :)