c++ - 如何在另一个类函数中使用类,而与在 C++ 中声明的位置无关?
问题描述
我正在尝试用 C++ 创建一个 Monopoly 游戏,我一直在搞乱面向对象的编程,问题发生在“游戏”和“玩家”类上,我想知道如何使用“游戏”' s 函数在“Player”中,“Player”函数在“Game”中,但我收到一个编译器错误,提示该类未定义。
转换班级职位是行不通的(显然),但我还是尝试了。
代码(减少并最小化为 Game 和 Player 类):
namespace Monopoly {
typedef enum { normal, train, company, incometax, luxurytax, start, chancecard, chestcard, jail } type;
class Game {
private:
bool running = false;
int turn = 1;
int currentPlayerID;
int startingMoney = 1000;
std::vector<Player> players;
public:
// Functions
void createPlayer() {
++currentPlayerID;
Player newPlayer(currentPlayerID, startingMoney);
players.push_back(newPlayer);
++currentPlayerID;
}
void createPlayers(int playerAmount) {
for (int i = 0; i <= playerAmount; ++i) {
createPlayer();
}
}
Player getPlayer(int index) {
Player p = players[index];
return p;
}
};
class Player {
private:
int playerID;
int money;
std::vector<int> propertiesOwned;
void addProperty(int id) {
this->propertiesOwned.push_back(id);
}
public:
// Constructor
Player(int pID, int sMoney) {
this->playerID = pID;
this->money = sMoney;
}
// Functions
Player payMoney(int payAmount, unsigned int destinationID, Game engine) {
this->money -= payAmount;
if (destinationID > 0) {
// Checks if you're paying to a player or bank
bool playerFound = false;
for (int i = 0; i <= engine.getPlayerAmount(); ++i) {
if (engine.getPlayer(i).getID() == destinationID) {
playerFound = true;
break;
}
}
if (playerFound) {
// Player was found
engine.getPlayer(destinationID).giveMoney(payAmount);
return;
}
else {
std::cout << "\nERROR: Invalid player ID at function payMoney\n";
return;
}
}
else {
// You're paying to the bank
}
return;
}
void buyProperty(int id, int price, Game engine) {
payMoney(price, 0, engine);
addProperty(id);
}
void giveMoney(int payMoney) {
this->money += payMoney;
}
// Returns
inline int getMoney() { return this->money; }
inline int getID() { return this->playerID; }
inline auto getProperties(int index) {
auto p = propertiesOwned[index];
return p;
}
inline int getPropertyAmount() {
int amount = std::size(propertiesOwned);
return amount;
}
};
}
我希望这些类能够正常运行其他类功能,但它看起来像在 C++ 中,类是按特定顺序定义的,并且您只能访问在您使用的类、反馈和替代方案之前声明的类(在类中)解决这个问题会有所帮助
解决方案
您是正确的,在 C++ 声明顺序中很重要,这就是您的错误的原因,但是代码还有一些其他问题。
首先,您应该交换定义的Game
顺序Player
。这将使其更容易,因为Player
依赖Game
的次数比Game
依赖的次数少Player
。
接下来,Game
在 的定义之前添加一个前向声明Player
:
class Game;
这告诉编译器存在一个名为的类Game
,并允许您在不需要知道类的内容(即定义)的情况下使用它。
接下来,通过将参数说明符更改为,通过引用而不是通过值payMoney
来生成和buyProperty
接受它们的engine
参数。这很重要,有两个原因。首先,只有在你已经定义了类型的情况下才能进行值传递,而我们还没有定义(我们只是声明了它)。其次,按值传递会创建对象的副本,在这种情况下,这意味着全新对象的全新,并且更改不会同步回旧对象。有关参考资料的更好解释,请参见此处。Game &engine
vector
Player
接下来,您需要在 的定义payMoney
之后提取 to 的定义Game
。原因是,虽然 的参数列表payMoney
不再依赖 的定义Game
,但函数体中的代码确实如此(因为它调用了engine
对象上的函数)。看看这到底是什么样子的。
这解决了声明/定义顺序的所有问题。您还应该将payMoney
return 设为 void,因为它的返回值从未提供也从未使用过,为 ID 选择一致的类型(或者,int
或者unsigned int
,不是混合),然后添加getPlayerAmount
到Game
.
这是最终代码的样子:
namespace Monopoly {
typedef enum { normal, train, company, incometax, luxurytax, start, chancecard, chestcard, jail } type;
class Game;
class Player {
private:
int playerID;
int money;
std::vector<int> propertiesOwned;
void addProperty(int id) {
this->propertiesOwned.push_back(id);
}
public:
// Constructor
Player(int pID, int sMoney) {
this->playerID = pID;
this->money = sMoney;
}
// Functions
void payMoney(int payAmount, int destinationID, Game &engine);
void buyProperty(int id, int price, Game &engine) {
payMoney(price, 0, engine);
addProperty(id);
}
void giveMoney(int payMoney) {
this->money += payMoney;
}
// Returns
inline int getMoney() { return this->money; }
inline int getID() { return this->playerID; }
inline auto getProperties(int index) {
auto p = propertiesOwned[index];
return p;
}
inline int getPropertyAmount() {
int amount = std::size(propertiesOwned);
return amount;
}
};
class Game {
private:
bool running = false;
int turn = 1;
int currentPlayerID;
int startingMoney = 1000;
std::vector<Player> players;
public:
// Functions
void createPlayer() {
++currentPlayerID;
Player newPlayer(currentPlayerID, startingMoney);
players.push_back(newPlayer);
++currentPlayerID;
}
void createPlayers(int playerAmount) {
for (int i = 0; i <= playerAmount; ++i) {
createPlayer();
}
}
Player getPlayer(int index) {
Player p = players[index];
return p;
}
int getPlayerAmount() {
int amount = players.size();
return amount;
}
};
void Player::payMoney(int payAmount, int destinationID, Game &engine) {
this->money -= payAmount;
if (destinationID > 0) {
// Checks if you're paying to a player or bank
bool playerFound = false;
for (int i = 0; i <= engine.getPlayerAmount(); ++i) {
if (engine.getPlayer(i).getID() == destinationID) {
playerFound = true;
break;
}
}
if (playerFound) {
// Player was found
engine.getPlayer(destinationID).giveMoney(payAmount);
return;
}
else {
std::cout << "\nERROR: Invalid player ID at function payMoney\n";
return;
}
}
else {
// You're paying to the bank
}
return;
}
}
旁注:使用 C++size_t
代替int
存储向量大小的变量在技术上更好,因为这是size
函数返回的内容(它是无符号整数类型,而int
有符号),但这并不是特别重要。
推荐阅读
- c# - 如何使用 C# 将 SQLite Blob 转换为 GUID
- apache-spark-sql - Databricks SparkSQL 作业
- sql-server-2008 - 存储过程中的数据截断错误,但 SSIS 包没有失败
- google-cloud-platform - Cloud IAM 条件 - 如何将 instanceAdmin 限制为仅特定实例名称
- javascript - 更改 JavaScript 中的默认复制/粘贴机制
- php - 试图将文件链接发送到邮件但只得到一个文件
- spring-boot - Docker容器忽略目录中的文件夹
- javascript - 使用鼠标悬停在three.js中旋转相机
- scom - 移动到新版本的 Active Directory 时更新 SCOM 中的自定义规则
- c - 如何通过 C 代码使用 ffmpeg lib 将 mp4(h264&aac) 转换为 m3u8 (hls)?