简体   繁体   English

如何独立于C ++中的声明位置使用另一个类函数中的类?

[英]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. 切换班级的职位(显然)是行不通的,但是我还是尝试了。

Code (reduced and minimized to the Game and Player classes): 代码(减少并最小化到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;
    }
};
}

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. 首先,您应该交换GamePlayer的定义顺序。 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 ,使payMoneybuyProperty 通过引用而不是通过值接受其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选择一个一致的类型( intunsigned 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.

相关问题 在函数内部声明的相互C ++类 - Mutual C++ classes declared inside of a function C++ 中 main() 函数中声明的类 - Declared class inside the main() function in C++ 在C ++中用另一个类初始化类? - Initialising classes inside another class in C++? C ++:如何访问另一个类中的类函数? - C++: How to access a class function inside another class? 如何在成员函数中的C ++中创建优雅的for_each(),而操作函数是同一类中的另一个成员函数? - How do I create an elegant for_each() in C++ inside a member function where the operating function is another member function in the same class? C++ 如何使用前向声明类的方法 - C++ How to use methods of forward declared classes 如何使用 arguments 并将其传递给 function 使用 ZA2F2ED4F8EBC2CBB4C21A29DC40ABBD61DZ 中声明的变量和列表 - How do you use, and pass arguments into function that use variables and lists declared in a class in c++? 如何使用在包含使用符号的文件的文件中声明的符号(函数,字段,类等)。 C ++ - How to use symbols(functions, fields, classes & etc.) declared in a file that includes file where the symbol is used. C++ 如何在 c++ 的头文件中使用类 - How to use classes inside headers in c++ 在 C++ 中的类声明中声明的函数如何执行? - How functions executed declared inside class declaration in c++?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM