Search code examples
c++classintegervoid

Cannot Input Integer Into Class Object to Store and Output


I have been learning c++ for a short time now so please keep in mind I'm a beginner. Currently I am doing my best to learn classes, structs, and oop for c++. I am currently creating a small RPG game to get some of the basics down, however I have ran into my most difficult issue thus far.

I have created a class to store items in using type 'Int' for the items and 'void functions' to read cin as well as output the integer values. However, when I attempt to call a void function that isn't inside of the main file where the cin was read, it consistently outputs either '0' or an odd long negative number due to not reading any input. After a few hours of testing and scavenging the internet, I have yet to find a solution.

//Main game file

void lich_swamp()
{
    Inv inv; //Class I'm Using
    do
    {
        std::cout << "---Irrelevant---";
        std::cout << "[Insert Number]\n";
        inv.c_add();
        
        if (inv.coins <= 4)
        {
            system("CLS");
            inv.c_print();
            break;
        }
        else if (inv.coins > 4)
        {
            system("CLS");
            std::cout << "---Irrelevant---";
            dth_e1();
            console_death();
            return;
        }
    } while (inv.coins < 1);
//Class Header File

#ifndef INV_UTILS
#define INV_UTILS
#include "C:/Otherincludedfile.h"
#include <iostream>

class Inv
{
private:
    int longsword = 0;
public:
    int coins = 0;
    void c_add();
    void c_print();
    void print_inv();
};

#endif

//Class Functions Definitions File

void Inv::c_add()
{
    std::cin >> coins;
}

void Inv::c_print()
{
    std::cout << "You take x" << coins << " Coin(s) into your inventory.";
}

void Inv::print_inv()
{
    int inv_choice;
    std::cout << "x" << coins << " Coin(s) in your inventory.";
    std::cout << "\n0: [RETURN TO MENU]\n";
    std::cin >> inv_choice;
    switch (inv_choice)
    {
    case 0:
        system("CLS");
        menu();
        break;
    }
}

//The print menu file

void menu()
{
    std::cout << "0:{return to game}\n";
    std::cout << "1:{view inventory}\n";
    std::cout << "2:{view achievements}\n";
    std::cout << "3:{player info}\n";
    Inv inv;
    int menu_choice;

    std::cin >> menu_choice;

    switch (menu_choice)
    {
    case 0:
        system("CLS");
        break;
    case 1:
        system("CLS");
        inv.print_inv();
        return;
    case 2:
        system("CLS");
        //num_twopr(ach);
        return;
    case 3:
        system("CLS");
        plyr_print();
        return;
    }

I have narrowed the issue down to some sort of scoping issue. That, or it could attest to the fact I have no clue what I'm doing. It seems that when I call 'inv.c_add();' in 'Main game file' that I read the initial input accordingly, and using 'inv.c_print();', it will output the corresponding value correctly as if it stored it.

But when attempting to use 'inv.print_inv();' after navigating to the menu, it fails to do so and acts as if I never attempted to save a number into the object, giving me that odd long negative number or a '0' if I have the integer set to as such. Also, quick disclaimer, a lot of code from the program is not shown here as 95% of it is irrelevant and would take up the entire screen. I added all relevant code that could be part of the issue.

Apologies if I'm making this difficult to understand, I just really want to figure this out. End goal is to print the correct amount of items into my inventory menu. Thanks in advance!


Solution

  • You've created multiple Inv instances. These are separate, distinct objects. Each time you create a new instance, the data is created afresh. I presume you want to maintain the game state. In order to do that, there are several options. In all cases, we want to only have one centralised inventory object, and update it throughout the course of the game.

    1. Pass a reference to Inv in your game function.

      void visit_lich_swamp(Inv& inv) {
          // ...
      }
      
      // Called like so...
      void game_loop() {
          Inv inv;  // Our one centralised, inventory object.
      
          // Insert game logic or whatever...
          while (1) {
              visit_lich_swamp(inv);
          }
      }
      
      

      Instead of creating a new object at the start, we pass a reference (notice the & in the parameter). This will refer to the inv declared in game_loop(). I presume you have some equivalent loop somewhere.

    2. Use a class that manages visiting different areas and has relations to the player and inventory.

      class GameMap {
      public:
          void visit_lich_swamp();
          // ...
      private:
          Inv& inventory;
      };
      

      This way, visit_lich_swamp() will get access to the inventory implicitly through this. Note that you'll still need to initialise Inv.

    3. Use a global variable. This is a terrible idea for the long term and is only useful for quick 'n dirty debugging.

    You'll find yourself commonly making choices like this when you want to share variables between functions and classes. Where does the variable go? Who owns the variable? Where should it be initialised? Those are some of the questions you'll be asking yourself as you program more.

    Maybe later on you'll find yourself wanting to add more player info, such as experience, pets, achievements, etc. The second approach would be the most extensible in this case, as you could add more information (e.g. a PlayerInfo class) by just adding a new member.

    Hope this helps. :)