对于tic tac toe游戏,我有一个基类Player
和两个派生类HumanPlayer
和AIPlayer
。
两个派生类都包含数据字段char token
。该字段是否应包含在基类中,因此不需要在派生类中声明它?
现在我没有明确声明Player
的构造函数,但如果数据字段char token
是Player
的一部分,我是否需要?
#pragma once // include guard
#include "Board.h"
class Player
{
public:
virtual void makeAMove(Board &myBoard) = 0; // pure virtual function
};
派生类的头文件:
#pragma once // include guard
#include "Player.h"
class HumanPlayer: public Player
{
public:
HumanPlayer(char token);
virtual void makeAMove(Board &myBoard);
private:
char token;
int askForRow();
int askForColumn();
};
#pragma once // include guard
#include "Player.h"
class AIPlayer: public Player
{
public:
AIPlayer(char token);
virtual void makeAMove(Board &myBoard);
private:
char token;
};
答案 0 :(得分:4)
是的,我会使它成为protected
基类的Player
成员,并提供一个构造函数(由派生类使用)来初始化它。
另外,如果你的派生类可以通过你添加到基类的成员函数来访问/使用它,你可能会在你的基类中使它成为private
,但我认为在你的游戏中,它是可能没问题protected
。
答案 1 :(得分:3)
这是另一种疯狂的方法,假设令牌是类属性而不是实例属性:将令牌设为模板参数:
template <char Token> class TokenPlayer : public Player
{
static char const token = Token;
};
class HumanPlayer : public TokenPlayer<'H'>
{
// ...
};
在每个TokenPlayer
中,您可以通过Token
引用令牌,并在每个派生类中引用token
。
不确定这对您是否有意义,但它是另一种选择,它可以节省存储空间。
答案 2 :(得分:3)
在这些情况下,这对我来说通常很有效:
class Player
{
public:
...
char Token() const { return _token; }
protected:
void SetToken(char tok) { _token = tok; }
private:
char _token;
};
像往常一样,使用setter / getter会隐藏实现,允许您稍后使用计算替换成员_token
,或者在客户端代码不必担心的情况下进行其他更改。每个人都可以看到值,但只允许“应该”更改它的函数(Player
的派生类)。
答案 3 :(得分:0)
是的,将token
放入基类是有意义的。在这种情况下,您应该为基类提供构造函数,并在派生类的构造函数中使用它。
答案 4 :(得分:0)
对于tic tac toe游戏,我认为不需要为Player
和AI
逻辑创建单独的类。两者都将做出明确的决定,但最终,他们两人基本上都会做同样的事情:在董事会上留下印记。您将需要AI的特殊逻辑,但这可以很容易地在另一个类中抽象出来。您的界面将主要用于Player
输入,无论是控制台输入还是Windows窗体。
答案 5 :(得分:0)
除非您想为token
派生的每个类声明Player
等,否则是。您应该使其成为基类的受保护成员,或者提供getToken()
和setToken()
方法并使令牌成为私有成员。你当然可以把它变成一个公共成员,但那是不好的封装。
你也不必在构造函数中初始化它的类成员,但这样做是好的。