[英]How to use classes inside another class function independently of where it is declared in C++?
I'm trying to create a Monopoly game in C++ and I've been messing with object-oriented-programming, the problem happens with the classes "Game" and "Player", I would like to know how to use "Game"'s functions inside "Player" and "Player"'s functions inside "Game", but I've been getting a compiler error saying that the class is not defined. 我正在尝试用C ++创建一个Monopoly游戏,而且我一直在搞面向对象编程,问题发生在“ Game”和“ Player”类上,我想知道如何使用“ Game””的“播放器”内部的“函数”和“游戏”内部的“播放器”的函数,但是我一直在得到一个编译器错误,指出未定义该类。
Switching class positions won't work (obviously) but I tried anyways. 切换班级的职位(显然)是行不通的,但是我还是尝试了。
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;
}
};
}
I expected the classes to run the other classes function normally, but it seens like that in C++, classes are defined in certain order, and you can only access classes (in a class) declared before the class you're using, feedback and alternatives that fix this would help 我希望这些类能够正常运行其他类,但是看起来就像在C ++中一样,类是按特定顺序定义的,并且您只能访问在使用的类之前声明的类(在类中),反馈和替代方法解决这个问题会有所帮助
You are correct that in C++ declaration order matters, and that is the cause of your errors, however there are a few other issues with the code. 您认为C ++声明顺序很重要,这是导致错误的原因,但是代码中还有其他一些问题。
Firstly, you should swap the order that Game
and Player
are defined. 首先,您应该交换Game
和Player
的定义顺序。 This will make it easier, as Player
relies on Game
fewer times than Game
relies on Player
. 由于Player
依赖于Game
的次数少于Game
依赖于Player
的次数,因此这将变得更加容易。
Next, add a forward declaration for Game
before the definition of Player
: 接下来,在Player
的定义之前添加Game
前向声明:
class Game;
This tells the compiler that a class named Game
exists and allows you to use it in scenarios where it doesn't need to know the contents (ie definition) of the class. 这告诉编译器存在一个名为Game
的类,并允许您在不需要知道该类内容(即定义)的情况下使用它。
Next, make payMoney
and buyProperty
accept their engine
parameter by reference instead of by value by changing the parameter specifier to Game &engine
. 接下来,通过将参数说明符更改为Game &engine
,使payMoney
和buyProperty
通过引用而不是通过值接受其engine
参数。 This is important for two reasons. 这很重要,有两个原因。 First, passing by value can only be done if you have already defined the type, which we have not (we've only declared it). 首先,只有在您已经定义了类型(但我们尚未声明)的情况下,才可以按值传递。 Second, passing by value creates a copy of the object, which in this case means a completely new vector
of completely new Player
objects, and the changes will not synchronize back to the old object. 其次,按值传递会创建对象的副本,在这种情况下,这意味着全新的Player
对象的全新vector
,并且更改将不会同步回到旧对象。 See here for a better explanation of references. 请参阅此处以获得参考的更好解释。
Next, you need to extract the definition of payMoney
to after the definition of Game
. 接下来,您需要在Game
的定义之后提取payMoney
的定义。 The reason is that while the parameter list of payMoney
no longer relies on the definition of Game
, the code in the function body does (because it calls functions on the engine
object). 原因是,尽管payMoney
的参数列表不再依赖Game
的定义,但函数主体中的代码却依赖(因为它调用engine
对象上的函数)。 See the end for what this looks like. 请参阅结尾以了解其外观。
This fixes all the problems with declaration/definition order. 这解决了声明/定义顺序的所有问题。 You also should make payMoney
return void as its return value is never provided and never used, pick a consistent type for IDs (either int
or unsigned int
, not a mix), and add the getPlayerAmount
to Game
. 您还应该使payMoney
返回空值,因为从不提供也不使用它的返回值,为ID选择一个一致的类型( int
或unsigned int
,而不是混合),并将getPlayerAmount
添加到Game
。
Here's what the final code could look like: 最终的代码如下所示:
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;
}
}
Side note: it's technically better C++ to use size_t
instead of int
for variables storing the size of vectors, as that is what the size
functions return (and it's an unsigned integer type whereas int
is signed), but that's not especially important. 旁注:对于存储向量大小的变量,使用size_t
而不是int
在技术上是更好的C ++,因为这是size
函数返回的内容(它是无符号整数类型,而int
是带符号的),但这并不是特别重要。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.