簡體   English   中英

(C ++)如何基於條件聲明對象類成員

[英](C++) How to declare an object class member based on a conditional

我正在開發一個面向對象的井字游戲,但遇到了問題。 我的課程之一是游戲的主要控制器,並控制所有其他對象。 下面是該類的精簡版本。

最終用戶可以在一個和兩個玩家之間進行選擇。 因此,對於我來說,既不必創建第二個播放器又可以創建一個AI播放器。 游戲只需要一個。 如您在下面看到的,我嘗試使用if語句解決問題,但是對象沒有作用域。

如何根據傳遞給Game構造函數的玩家數量來初始化一個對象或另一個對象?

謝謝!

Game.h

#include "Player.h"
#include "AIPlayer.h"

class Game 
{
    private:
        Player human;

        // I would like to put these here so they have scope
        // but it is unecessary to declare them both
        // If the user chooses one player then human2 is unecessary
        // if the user choosed two player then ai is unecessary
        AIPlayer ai;
        Player human2; 

    public: 
        Game(int players)
        {
            if (players == 1)
            {
                AIPlayer ai; // this does not have scope
            }
            else
            {
                Player human2; // this does not have scope
            }
        }
};

我的建議是從一個通用基類(例如Player)派生AIPlayer和Player(或者可能更好,HumanPlayer),並在Game中有一個指向該基類的指針。 然后,構造函數實例化AIPlayer或HumanPlayer並將其分配給指針。

在AIPlayer和HumanPlayer之間不同的任何方法都應在基類Player中聲明為虛擬方法,然后在派生類中實現。

您可能想要做的是將一個抽象的Player超類的指針作為游戲的成員,並根據玩家的數量將其分配給new AIPlayernew HumanPlayer

就像是:

#include "Player.h"
#include "AIPlayer.h"
#include "HumanPlayer.h"

class Game 
{
    private:
        Player* other_player;

    public: 
        Game(int players)
        {
            if (players == 1)
            {
                other_player = new AIPlayer;
            }
            else
            {
                other_player = new HumanPlayer;
            }
        }
};

您應該為Player和AIPlayer都創建一個(抽象的)基類,例如

abstract class Player
{
    virtual void MakeMove(GameBoard& b);
}

class HumanPlayer : public Player
{...}

class AIPlayer : public Player
{...}

然后在游戲中,您可以簡單地存儲兩個Player實例。

類繼承是一個很好的解決方案。 您創建一個基類並從中派生其他玩家,如下所示:

class Player{
  virtual int move(int)=0;
}

class AIPlayer: Player{
  virtual int move(int);
}

class HumanPlayer: Player{
  virtual int move(int);
}

您對這里的“作用域”有一些誤解。 類聲明不是作用域-只是支持該類的數據和函數的聲明。 作用域存在於函數中。

class A
{
    int a;
};

aA的成員,但是由於尚未實例化,因此它不屬於任何范圍。

void func()
{
    A a;
}

func具有定義的范圍,並且a是它的一部分。 func結束時, a超出范圍並被銷毀。

現在,向您的問題提問:解決問題的最簡單方法是使用繼承。 這將避免您在整個代碼中進行各種條件檢查,以確定哪些對象有效,哪些無效。 下面是一個示例:

class Player
{
public:
    virtual void Move() = 0; // pure virutal function 
};

class HumanPlayer()
{
public:
    ...
    virtual void Move() { ... }
};

class AIPlayer()
{
public:
    ...
    virtual void Move() { ... }
};

class Game
{
public:
    Game(unsigned int humanPlayerCount = 0)
    {
        if (humanPlayerCount == 0)
        {
            m_player1.reset(new AIPlayer());
            m_player2.reset(new AIPlayer());
        }
        else if (humanPlayerCount == 1)
        {
            m_player1.reset(new HumanPlayer());
            m_player2.reset(new AIPlayer());
        }
        else // assume it is 2
        {
            m_player1.reset(new HumanPlayer());
            m_player2.reset(new HumanPlayer());
        }
    }
    ...
private:
    std::unique_ptr<Player> m_player1;
    std::unique_ptr<Player> m_player2;
};

構建完成后,您將對它們進行相同的處理(從Game的角度看,它們之間沒有任何區別)。

你不能做你想做的。 您的問題的解決方案是使用繼承。 創建沒有這2個字段中的任何一個的基類,然后創建2個派生類,並在每個類中放入一個字段。

如您所見,您不能使用if語句,因為if語句是在運行時執行的,但是必須在編譯時確定類的成員。

這給您留下了其他幾個選擇:

  • 您總是可以同時聲明兩個人類Player對象和一個AIPlayer對象,而只是在任何特定游戲中不使用其中一個對象。 (除非這樣做會產生大量開銷,否則我將這樣做,因為這是最簡單的方法)

  • 您可以聲明指向所有三個對象的指針,然后使用new運算符動態分配您要使用的對象。 (完成處理后,請務必使用刪除功能將它們取消分配)

  • 您可以創建Game的幾個子類(例如OnePlayerGame和TwoPlayerGame),以使子類具有您需要的額外對象(例如Game僅聲明human1,OnePlayerGame添加ai,TwoPlayerGame添加human2)

模板呢? 創建對象時選擇類型(AIPlayer或Player)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM