0

我正在製作一個簡單的流氓般的遊戲地圖。 因此,我需要通過接收來自字符數組[i] [j]的數據來初始化具有爲每個數組單元創建的對象的映射。 建議這樣的CWall,CDoor類在CWall.cpp,CWall.h等其他文件中定義。下面是在map.cpp中初始化的代碼流氓喜歡遊戲初始化錯誤

但是,這是正確的代碼方式嗎? 我認爲這會導致分配內存的問題。

CObject CMap::insertObject(char character){ 
    if (character = '*') { 
     CWall cwall; 
     return cwall; 
    } 

    if (character = 'D') { 
     CDoor cdoor; 
     return cdoor; 
    } 

    if (character = 'F') { 
     CFood cfood; 
     return cfood; 
    } 

    if (character = 'K') { 
     CKey ckey; 
     return ckey; 
    } 

    if (character = 'M') { 
     CMMonster cmmonster; 
     return cmmonster; 
    } 

    if (character = 'm') { 
     CMonster cmonster; 
     return cmonster; 
    } 

    if (character = '@') { 
     CPlayer cplayer; 
     return cplayer; 
    } 

    if (character = 'P') { 
     CPrincess cprincess; 
     return cprincess; 
    } 

    if (character = '&') { 
     CRock crock; 
     return crock; 
    } 

    if (character = 'S') { 
     CShield cshield 
     return cshield; 
    } 

    else { 
     CShield cshield; 
     return cshield; 
    } 
} 

void CMap::initialize(char arr[][COLS]){ 
    for (int i = 0; i <= 11; i++){ 
     for (int j = 0; j <= 38; j++){ 
      char character = arr[i][j]; 
      insertObject(character); 
     } 
    } 
} 
+0

我已經像你所說的改變了。但它發生了額外的問題。那麼返回格式會是什麼樣?它會是「返回Cwall」嗎? –

+1

'如果(字符='應該是'如果(字符==' – Biffen

+1

在一個側面說明,你不太可能與基因多態性在這裏取得成功沒有什麼共同之處門和公主之間 - 。所以沒有幾乎性質,他們可以一起分享。最後你會不斷鑄造你的對象,這是一個噩夢。 – SergeyA

回答

0

那麼,首先,你並沒有實際初始化任何東西。 CWall* cwall = new CWall;將是動態分配和初始化一個新的CWall對象(當然,假設CWall有一個默認構造函數)或任何對象的正確方法。

您還需要牢記的是,對於您分配的所有內容,您必須稍後使用delete取消分配new。因此,您需要考慮如何存儲這些分配的對象,以確保您的析構函數或清理函數在完成後將其全部刪除。要考慮的一種設計模式是Object Pool,雖然有幾十種好的方法可以做到這一點。不過,這是你必須自己做的腳步,因爲只有你足夠了解你的項目才能選擇正確的設計模式。 (我鏈接到的這本書是一個很好的資源。)

編輯:根據您的評論,還有一個其他問題,那就是您返回不同類型的對象。這是一個簡單的問題繼承 - 只要所有這些對象繼承自抽象基類CObject(或類似的東西),您可以簡單地列出返回類型爲CObject*。然後,只要你返回一個從CObject繼承的對象(或指向對象的指針),你就是金。編輯2:當你使用new時,你實際上得到了一個指向動態分配對象的指針。這會造成一些問題,包括如果分配失敗,new可以返回空指針。一定要檢查!智能指針可以防止許多這些問題,但是您使用智能指針取決於您的設計模式選擇。

+0

謝謝您的建議。我已經改變了,就像你提到的,但它發生。另一個問題那麼會是怎樣的回報格式一樣會是誰?「cwall返回;」 –

+0

我與信息編輯 – CodeMouse92

+0

'new'返回一個指針,所以'CWall cwall =新CWall;'是不正確的 – Biffen

3

這不是正確的做法。你需要object slicing,因爲我的猜測是你的CObject是一個對象,而不是指向某個對象的指針。您需要在函數中返回類型爲CObject*的指針,然後針對每種情況返回new CMonsternew CPlayer等。更好的是,使用智能指針代替。

你正在努力實施的方法叫做工廠方法模式How to implement the factory method pattern in C++ correctly瞭解更多詳情。

1

您應該動態處理數據。你現在正在做什麼有幾個問題。

一個更好的辦法是:

CObject* CMap::insertObject(char character){ 
    if (character = '*') { 
     return new CWall(); 
    } 
... 

這將利用多態性隱藏通用接口(CObject)背後的實際的類(如CWall)。正如你寫的那樣,每個「新」對象,如cdoor,實際上都會被傳遞給CObject的拷貝構造函數。其中沒有一個實際上完成了任

當然,你需要對這樣的創作適當殘害的道路。

2

而另一些人正確地指出,如何編寫你想編碼的想法,我將專注於另一件事。也就是說,這裏不恰當地使用多態。繼承一些無意義的對象氣味,如Java,並不歡迎使用C++。公主和怪物之間根本沒有什麼共同之處(一個人被親吻,另一個人被殺,並且做出與自己的口味相符的東西),所以當兩個人都是從Object繼承的時候,編寫正確的遊戲是非常困難的機械。你將不得不存儲實際的對象類型(比如說枚舉),而不是強制轉換爲這種類型 - 因爲只有其中一個對象會有方法kiss()

整個代碼將是不安全的強制類型轉換的意大利麪條和將不可能維持或推理。

相反,去stongly類型的方法。總是知道在你面前的是什麼類型!

+1

高超技巧,謝爾蓋。從同一個源頭繼承公主和怪物,並且你得到一個沮喪之謎。 (雖然,如果你想讓你的公主攻擊......也許不是一個壞的場景?)而牆壁也不會發作。具有不同的基類也使得更容易編碼,因爲所有的怪物都攻擊力和實力,對象有結界水平等 – CodeMouse92

+1

TDTTOE - 一個球員應該能夠爲'吻()'什麼誘人親吻,以及遊戲應該處理導致有意義的方式。 –