Thread: How to use functions and variables from one class in another

  1. #1
    Registered User
    Join Date
    Feb 2015
    Posts
    56

    How to use functions and variables from one class in another

    Hi, I'm making a small game to test out and build upon my C++ knowledge, but i've hit a road block. I'm familiar with classes however I have never really learned how to use objects from one class in another without inheritance. I know about friend but I was wondering if there was a way to use functions and variables without friend. I dont think inheritance is applicable here so what else can I do? For instance, in this program, I have the DrawMap() Function, in that function I need to set the player start position but since the player is not part of game class, I cannot use the function from the player class in the game class functions. I'm having an extraordinarily difficult time figuring this out. I've been messing with it and researching stuff for a few hours now and I cannot seem to get it to work. I feel so close to a solution but cant get there, it's like trying to put together two negative sides of a powerful magnet.


    main.cpp


    Code:
    #include <iostream>
    #include <string>
    
    
    #include "Game.h"
    #include "Player.h"
    
    
    using namespace std;
    
    
    //I wrote the entire working program in main just to make sure it //works right, now im trying to break it up into smaller chunks.
    int main()
    {
        /*
        int mapColSize = 10;
        int mapRowSize = 22;
    
    
        char mapArray[mapColSize][mapRowSize];
    
    
        char mapGrid = 'o';
        char playerChar = '*';
        char rockObstacle = '#';
    
    
        int playerXPos = 3;
        int playerYPos = 3;
    
    
        int choice = 0;
    
    
        while(choice != -1)
        {
            for(int col = 0; col < mapColSize; col++)
            {
                for(int row = 0; row < mapRowSize; row++)
                {
                   mapArray[col][row] = mapGrid;
                   mapArray[playerYPos][playerXPos] = playerChar;
    
    
                   cout << mapArray[col][row];
                }
                cout << endl;
            }
    
    
            cout << "\nWhat direction would you like to move?\n" << endl;
    
    
            cout << "1) UP" << endl;
            cout << "2) DOWN" << endl;
            cout << "3) LEFT" << endl;
            cout << "4) RIGHT" << endl;
            cout << ">";
            cin >> choice;
    
    
            switch(choice)
            {
                case 1:
                    if(playerYPos > 0)
                    {
                        playerYPos -= 1;
                        cout << "Player Y Pos: " << playerYPos << endl;
                    }
                    else if(playerYPos == 0)
                    {
                        playerYPos -= 0;
                        cout << "You cannot go any further North!\n" << endl;
                    }
                    break;
                case 2:
                    if(playerYPos < mapColSize -1)
                    {
                        playerYPos += 1;
                        cout << "Player Y Pos: " << playerYPos << endl;
                    }
                    else if(playerYPos == mapColSize -1)
                    {
                        playerYPos += 0;
                        cout << "You cannot go any further South!" << endl;
                    }
                    break;
                case 3:
                    if(playerXPos > 0)
                    {
                        playerXPos -= 1;
                        cout << "Player X Pos: " << playerXPos << endl;
                    }
                    else if(playerXPos == 0)
                    {
                        playerXPos -= 0;
                        cout << "You cannot go any further West!" << endl;
                    }
                    break;
                case 4:
                    if(playerXPos < mapRowSize -1)
                    {
                        playerXPos += 1;
                    }
                    else if(playerXPos == mapRowSize -1)
                    {
                        playerXPos += 0;
                        cout << "You cannot go any further East!" << endl;
                    }
                    break;
                default:
                    cout << "Not a valid option" << endl;
            }
        }
    
    
        */
    
    
        return 0;
    }



    Game.h


    Code:
    #ifndef GAME_H
    #define GAME_H
    
    
    
    
    class Game
    {
        public:
            Game() = default;
            ~Game() = default;
    
    
            void DrawMap();
            void DrawObstacles();
            void GameLoop();
    
    
        private:
            int mapColSize = 10;
            int mapRowSize = 22;
    
    
            char mapArray[0][0];
    
    
            char mapGrid = 'o';
            char rockObstacle = '#';
    };
    
    
    #endif // GAME_H



    Game.cpp


    Code:
    #include "Game.h"
    #include "Player.h"
    
    
    #include <iostream>
    
    
    using std::cout;
    using std::endl;
    using std::cin;
    
    
    void Game::GameLoop()
    {
        int choice = 0;
    
    
        while(choice != -1)
        {
            cout << "\nWhat direction would you like to move?\n" << endl;
    
    
            cout << "1) UP" << endl;
            cout << "2) DOWN" << endl;
            cout << "3) LEFT" << endl;
            cout << "4) RIGHT" << endl;
            cout << ">";
    
    
            cin >> choice;
    
    
            /*Call CheckPlayerScreenBounds()*/
        }
    }
    
    
    void Game::DrawMap()
    {
            for(int col = 0; col < mapColSize; col++)
            {
                for(int row = 0; row < mapRowSize; row++)
                {
                    mapArray[col][row] = mapGrid;
                    /*Call DrawPlayer() function*/
                    cout << mapArray[col][row];
                }
                cout << endl;
            }
    }



    Player.h


    Code:
    #ifndef PLAYER_H
    #define PLAYER_H
    
    
    
    
    class Player
    {
        public:
            Player() = default;
            ~Player() = default;
    
    
            void SetPlayerOnMap();
            int GetPlayerXYPosition() const;
            void CheckScreenBounds(int choice);
            void CheckObstacleBounds();
            int GetPlayerInput();
            inline int MoveUp();
            inline int MoveDown();
            inline int MoveLeft();
            inline int MoveRight();
    
    
    
    
        private:
            char playerChar = '*';
            int playerXPos = 3;
            int playerYPos = 3;
            int playerMovement = 1;
    };
    
    
    #endif // PLAYER_H

    Player.cpp


    Code:
    #include "Player.h"
    
    
    #include <iostream>
    
    
    using std::cout;
    using std::endl;
    
    
    inline int Player::MoveUp()
    {
        playerYPos -= playerMovement;
    
    
        return playerYPos;
    }
    
    
    inline int Player::MoveDown()
    {
        playerYPos += playerMovement;
    
    
        return playerYPos;
    }
    
    
    inline int Player::MoveLeft()
    {
        playerXPos -= playerMovement;
    
    
        return playerXPos;
    }
    
    
    inline int Player::MoveRight()
    {
        playerXPos += playerMovement;
    
    
        return playerXPos;
    }
    
    
    
    
    void Player::CheckScreenBounds(int choice)
    {
        switch(choice)
        {
            case 1: //Move Up
                if(playerYPos > 0)
                {
                    MoveUp();
                    cout << "Player Y Pos: " << playerYPos << endl;
                }
                else if(playerYPos == 0)
                {
                    MoveDown();
                    cout << "You cannot go any further North!\n" << endl;
                }
                break;
            case 2: //Move Down
                if(playerYPos < mapColSize -1)
                {
                    MoveDown();
                    cout << "Player Y Pos: " << playerYPos << endl;
                }
                else if(playerYPos == mapColSize -1)
                {
                    MoveUp();
                    cout << "You cannot go any further South!" << endl;
                }
                break;
            case 3: //Move Left
                if(playerXPos > 0)
                {
                    MoveLeft();
                    cout << "Player X Pos: " << playerXPos << endl;
                }
                else if(playerXPos == 0)
                {
                    MoveRight();
                    cout << "You cannot go any further West!" << endl;
                }
                break;
            case 4: //Move Right
                if(playerXPos < mapRowSize -1)
                {
                    MoveRight();
                }
                else if(playerXPos == mapRowSize -1)
                {
                    MoveLeft();
                    cout << "You cannot go any further East!" << endl;
                }
                break;
            default:
                cout << "Not a valid option" << endl;
        }
        Game::DrawMap();
    }
    
    
    inline void Player::SetPlayerOnMap()
    {
        mapArray[playerYPos][playerXPos] = playerChar;
    }

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by CH1156
    I have the DrawMap() Function, in that function I need to set the player start position but since the player is not part of game class, I cannot use the function from the player class in the game class functions.
    In the context of the DrawMap member function of the Game class, you can freely use public member functions of the Player class for a given Player object, e.g., perhaps you could call the SetPlayerOnMap member function of the Player class.

    However, it is not clear to me how you would implement SetPlayerOnMap: the member function takes no arguments, the Player object does not store a pointer or reference to a Game object, so it seems that SetPlayerOnMap has no way to actually set the player on the map that is within the Game object.

    By the way, one thing to consider is the idea of layers of components. For example, your Player object presently both models a Player and also performs interactive I/O with the user in CheckScreenBounds, i.e., it has logic to move the player on the map and write the result to standard output, and then does things like warn the user about exceeding the map boundaries. This should actually be separated into two components, e.g., a Player object that models a Player object such that you can change its position on the map, retrieve its map coordinates, etc. Then you can say, have a library of functions that operate on Player objects, and within this library you can then implement CheckScreenBounds to work with standard I/O, or perhaps you might have another library with a version of CheckScreenBounds that works with a graphical user interface because you want another version of this game that is GUI-based, reusing the same underlying Player object.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Feb 2015
    Posts
    56
    "In the context of the DrawMap member function of the Game class, you can freely use public member functions of the Player class for a given Player object, e.g., perhaps you could call the SetPlayerOnMap member function of the Player class."


    So like this?


    Code:
    void Game::DrawMap()
    {
            for(int col = 0; col < mapColSize; col++)
            {
                for(int row = 0; row < mapRowSize; row++)
                {
                    mapArray[col][row] = mapGrid;
                    Player::SetPlayerOnMap();
                    cout << mapArray[col][row];
                }
                cout << endl;
            }
    }


    It says cant do it without a player object, but when i create one it gives me more errors.

    ||=== Build: Debug in double vector map (compiler: GNU GCC Compiler) ===|
    C:\Users\thund\Desktop\double vector map\main.cpp||In function 'int main()':|
    C:\Users\thund\Desktop\double vector map\main.cpp|23|warning: unused variable 'rockObstacle' [-Wunused-variable]|
    obj\Debug\src\Game.o||In function `ZN4Game7DrawMapEv':|
    C:\Users\thund\Desktop\double vector map\src\Game.cpp|24|undefined reference to `Player::SetPlayerOnMap()'|
    ||error: ld returned 1 exit status|
    ||=== Build failed: 2 error(s), 1 warning(s) (0 minute(s), 0 second(s)) ===|
    Last edited by CH1156; 10-15-2017 at 06:00 AM.

  4. #4
    Registered User
    Join Date
    Feb 2015
    Posts
    56
    Ok so i made a simpler example of the problem, So I have this code:

    Code:
    #include <iostream>
    
    using namespace std;
    
    
    class A
    {
        public:
            A() = default;
            ~A() = default;
    
    
            int AddX();
    
    
        private:
            int x = 10;
    };
    
    
    
    
    
    
    int A::AddX()
    {
        return x;
    }
    
    
    
    
    class B
    {
        public:
            B() = default;
            ~B() = default;
    
    
            int AddY();
            int SumXY();
    
    
        private:
            int y = 35;
    };
    
    
    
    
    
    
    int B::AddY()
    {
        return y;
    }
    
    
    
    
    
    
    int B::SumXY()
    {
        A a;
    
    
        int sum = AddY() + a.AddX();
    
    
        return sum;
    }
    
    
    int main()
    {
        B b;
    
    
        cout << b.SumXY();
        return 0;
    }
    It works, but is there a cleaner way of creating an object instead of doing it like that in every function? also to achieve that I have to have getters and setters for almost every variable which is bad practice.
    Last edited by CH1156; 10-15-2017 at 08:23 AM.

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    You need to think about the relationships between the classes. Does a Game contain a Player? Does a Player play a Game, but could possibly play another Game?

    If a Game contains a Player, then perhaps you would have a Player object be a member variable of Game. Then, in order to access Game from within Player member functions, perhaps Player could store a pointer to the Game object that owns the Player object. This could be passed as an argument in the Player constructor.

    If a Player could play multiple Games, then perhaps it would be the opposite: a vector of Game objects might be a member variable of Game, or if it is a multiplayer Game, then maybe a vector of pointers to Game objects. Each Game object could also store a pointer to the corresponding Player object.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User
    Join Date
    Feb 2015
    Posts
    56
    Ok, but if im going to make a player object a member of game, then why do i need to make a pointer to game from player? cant I just make a game object in player?

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by CH1156
    Ok, but if im going to make a player object a member of game, then why do i need to make a pointer to game from player? cant I just make a game object in player?
    You can't do that. It's like saying that your lungs are part of your body, so why can't your body be part of your lungs? If it were at all possible to make a game object in player, then it means that each Game object contains a Player object which contains a Game object which contains a Player object which contains a Game object which contains a Player object which contains a Game object which contains a Player object which contains a Game object which contains a Player object which contains a Game object which contains a Player object which contains a Game object which contains a Player object which contains a Game object which contains a Player object which contains a Game object which contains a Player object which contains a Game object which contains a Player object which contains a Game object which contains a Player object which contains a Game object which contains a Player object which contains a Game object which contains a Player object which contains a Game object which contains a Player object which contains a Game object which contains a Player object which contains a Game object which contains a Player object which contains a Game object which contains a Player object which contains...

    Okay, I'll stop here, but it actually goes on and on and on until the entire multiverse and beyond is consumed by your program. Hence, you need a way to refer to the Game object from within the Player object without actually storing the entire Game object within the Player object, and one way is to store a pointer to the Game object. If a Player object might deal with different Game objects, then passing a Game object (by reference) as an argument to the desired member function of Player could work too.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Registered User
    Join Date
    Feb 2015
    Posts
    56
    Ok so I decided to just open a new file and write the classes with little in them so I dont lose sight of what im trying to do. So step by step here:

    Step one: Create Player Object in Game and Pointer to Game Object:

    Code:
    #include <iostream>
    
    using namespace std;
    
    
    class Player;
    
    
    class Game
    {
        public:
            Game(Player player);
            ~Game();
    
    
        private:
            char gme_mapArray[0][0];
    };
    
    
    class Player
    {
        public:
            Player(Game* game);
            ~Player();
    
    
        private:
            int plr_XPos = 0;
            int plr_YPos = 0;
    };
    
    
    int main()
    {
        cout << "Hello world!" << endl;
        return 0;
    }
    Is this correct so far?

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I would expect something like this instead:
    Code:
    class Game;
    
    class Player
    {
    public:
        explicit Player(Game* game) : game(game) {}
    private:
        int plr_XPos = 0;
        int plr_YPos = 0;
        Game* game;
    };
    
    class Game
    {
    public:
        Game() : player(this) {}
    private:
        char gme_mapArray[10][10];
        Player player;
    };
    
    int main()
    {
        Game game;
        return 0;
    }
    A forward declaration of the Game class is enough to declare a member variable of type Game* in the Player class definition. A forward declaration of the Player class would not be enough to declare a member variable of type Player in the Game class. That's why I forward declare Game, define Player, and then define Game.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    Registered User
    Join Date
    Feb 2015
    Posts
    56
    Would this be fine as well?

    Code:
    #include <iostream>
    
    using namespace std;
    
    
    class A
    {
        public:
            A() = default;
            ~A() = default;
    
    
            void AMethod(){cout << "This text is in class A" << endl;}
    };
    
    
    class B
    {
        public:
            B() = default;
            ~B() = default;
    
    
            void BMethod(){cout << "This text is in class B" << endl;}
    };
    
    
    void BMethod(A& a)
    {
        a.AMethod();
    }
    
    
    void AMethod(B& b)
    {
        b.BMethod();
    }
    
    
    int main()
    {
        A a;
        B b;
    
    
        a.AMethod();
        b.BMethod();
        return 0;
    }

  11. #11
    Registered User
    Join Date
    Feb 2015
    Posts
    56
    I realized that coded didnt work but this does.

    Code:
    #include <iostream>
    
    using namespace std;
    
    
    class B;
    
    
    class A
    {
        public:
            A() = default;
            ~A() = default;
    
    
            void AMethod(B&);
            void AMethodText(){cout << "This text is in class A" << endl;}
    
    
            private:
    };
    
    
    class B
    {
        public:
            B() = default;
            ~B() = default;
    
    
            void BMethod(A&);
            void BMethodText(){cout << "This text is in class B" << endl;}
    
    
        private:
    
    
    };
    
    
    void B::BMethod(A& a)
    {
        a.AMethodText();
    }
    
    
    void A::AMethod(B& b)
    {
        b.BMethodText();
    }
    
    
    int main()
    {
        A a;
        B b;
    
    
        a.AMethod(b);
        b.BMethod(a);
    
    
        return 0;
    }

  12. #12
    Banned
    Join Date
    Aug 2017
    Posts
    861
    Just an idea.
    why not just put a player inside of the game itself? or make it so that if you are having players, and you come to a point whereas you create more player types, the constructor for the player itself is included inside of the game class so when that gets created it can ask how many players wanted, and the default would be one or two depending on what type of game it is. This way when ever starting the game that game class will always be creating the basic amount of players needed to play that game.

    just a question.
    Furthermore, wouldn't you only being needing one game class, and one player class, whereas the player class has its members to describe each players characteristics within the private part of the class? Then functions to give them characteristics substance?


    Code:
    class Player{
    private:
    char *name
    char *hair_color;
    int hair_length:
    public:
    void setHairColor(char *clr);
    void setHairLength(int ln);
    void setName(char *name);
    char *getHairColor();
    int getHairLength();
    char *getName();
    };
    just set its properties for each separate player using just one class called player.

    next, is the player interacting with the game, or is the game interacting with the player?

    does a tree ( inanimate object ) interact with you, or do you interact with the (inanimate object) tree ? line of thought.

    then write your functions that give it (as a whole) that functionality to show that process.

    just a thought.
    Ever read up on abstract and concrete classes?

    as laserLight is basically trying to express to you as well. as far as her post #7 if you create one then you'll get put into a growing loop of same objects. so do correct my line of thought if wrong, but

    and this is abstract writing of this so do not use it, but maybe the idea will be able to be used.
    Code:
    class player{
    private:
    arm
    eyes
    legs
    feet
    name
    public:
    functions to set them properties
    and other needed functions
    };
    
    class Game{
    private:
    whatever is needed in here:
    public:
    
    creator for game class
    
    a means to call to
    create a player or two, and
    another function that
    asks how many players
    if a multi player game more than 2
    then provides a means
    to call the creator for the class player, 
    and funny enough to set its properties as well?
    
    is that a friend ? 
    };
    then everything would have to be done through the game class to change the game items as well as the players within the game class?

    I do not know, it is defiantly needed to be thought about.

    the players, will they have a means to talk to the game, or is that game going to be talking to the players?

    how to make the players aware of the items within the game?

    how to make the players have an ability to manipulate same said
    items?

    how would you make that inanimate object within the game aware of a player if said player comes close to it?

    that is if this is an animated game.

    if it is just a game where a player can kick a bucket, then you have to do the math for force applied to the kick at point of contact then get distance that the bucket traveled, next player to see who can kick the bucket furthest.

    it still has the same basics to it.
    Last edited by userxbw; 10-26-2017 at 09:04 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 5
    Last Post: 08-02-2017, 04:15 AM
  2. Replies: 2
    Last Post: 05-12-2011, 04:19 PM
  3. Functions in class and class variables.
    By Karakus in forum C++ Programming
    Replies: 4
    Last Post: 01-15-2006, 03:29 AM
  4. Static variables and functions problem in a class
    By earth_angel in forum C++ Programming
    Replies: 16
    Last Post: 09-15-2005, 12:08 PM
  5. Class member variables only readable by member functions?
    By _Elixia_ in forum C++ Programming
    Replies: 4
    Last Post: 10-10-2003, 03:52 PM

Tags for this Thread