[英](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 AIPlayer
或new 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;
};
a
是A
的成員,但是由於尚未實例化,因此它不屬於任何范圍。
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.