首页 > 解决方案 > 如何在另一个类函数中使用类,而与在 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++classoop

解决方案


您是正确的,在 C++ 声明顺序中很重要,这就是您的错误的原因,但是代码还有一些其他问题。

首先,您应该交换定义的Game顺序Player。这将使其更容易,因为Player依赖Game的次数比Game依赖的次数少Player

接下来,Game在 的定义之前添加一个前向声明Player

class Game;

这告诉编译器存在一个名为的类Game,并允许您在不需要知道类的内容(即定义)的情况下使用它。

接下来,通过将参数说明符更改为,通过引用而不是通过值payMoney来生成和buyProperty接受它们的engine参数。这很重要,有两个原因。首先,只有在你已经定义了类型的情况下才能进行值传递,而我们还没有定义(我们只是声明了它)。其次,按值传递会创建对象的副本,在这种情况下,这意味着全新对象的全新,并且更改不会同步回旧对象。有关参考资料的更好解释,请参见此处Game &enginevectorPlayer

接下来,您需要在 的定义payMoney之后提取 to 的定义Game。原因是,虽然 的参数列表payMoney不再依赖 的定义Game,但函数体中的代码确实如此(因为它调用了engine对象上的函数)。看看这到底是什么样子的。

这解决了声明/定义顺序的所有问题。您还应该将payMoneyreturn 设为 void,因为它的返回值从未提供也从未使用过,为 ID 选择一致的类型(或者,int或者unsigned int,不是混合),然后添加getPlayerAmountGame.

这是最终代码的样子:

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有符号),但这并不是特别重要。


推荐阅读