Home > Software engineering >  Attempting to Reference a Class Object Within Another Class to Avoid a 2nd Instance of that Class
Attempting to Reference a Class Object Within Another Class to Avoid a 2nd Instance of that Class

Time:05-22

1. Explanation of error and my logic

I am having trouble figuring out why using a referenced object from one class into a separate class is not working the way I thought it would. I have included streamlined code below for this example with a Main.cpp and 2 other classes, named InventoryStorage and ShoppingExperience.

The InventoryStorage class stores names from a .txt file into a vector, and has a typical getter that I can make an object for in Main.cpp to output these names: invStObj.getFileInvData(i)

My problem is that I wish to use this getter in several other classes as well, WITHOUT making a new instance of the object, InventoryStorage invStObj; that was made in Main.cpp

Instead, I attempted to make a reference for this object, InventoryStorage& invStRefObj = invStObj; that my other class ShoppingExperience.cpp will use in order to utilize the getFileInvData() function in this class as well.

When I run this code, it should output the desired output but instead, the actual output is cut short when it reaches the Item List in Inventory part. My reference object in my 2nd class will not work with the getter function from the 1st class properly.
cout << invStObj.getFileInvData(i) << endl; that is in Main.cpp properly outputs "test items" followed by the names
cout << invStRefObj.getFileInvData(i) << endl; from ShoppingExperience class just outputs "Item List in Inventory" and then errors without outputting any names

Desired Output.................................................... Actual Output

test items                          test items
book                                book
movie                               movie 
food                                food
game                                game

Item List in Inventory              Item List in Inventory
book  
movie  
food  
game

I receive an error, "vector subscript out of range" because my ShoppingExperience.cpp is trying to use the getter with a new empty vector. Using a reference of the object did not seem to protect it from creating a new instance of that class which is what I was trying to prevent in the first place.
Please refer to my code located below for clarification

2. Question: Is it possible to reference to an object from another class similar to my failed attempt? Is there some alternate format or function that I can use to achieve this? I would like Main.cpp and my ShoppingExperience.cpp to use the same object and class instance for the InventoryStorage class functions

3. InventoryStorage.h, InventoryStorage.cpp, Main.cpp, ShoppingExperience.h, ShoppingExperience.cpp are shown below in their entirety for citation

InventoryStorage.h

#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
using std::string; 
using std::vector;


class InventoryStorage
{
public:
    InventoryStorage();
    void storeFileInvData(string);      //opens and stores file names to vector, invDataCl 
    string getFileInvData(int);         //returns names from vector, invDataCl

private:
    string fileNameCl;
    string lineCl;
    vector<string> invDataCl;
};

InventoryStorage.cpp

#include "InventoryStorage.h"

InventoryStorage::InventoryStorage() {

}

void InventoryStorage::storeFileInvData(string fileNameTmp) {
    fileNameCl = fileNameTmp;
    std::ifstream openInvFileCl;
    openInvFileCl.open(fileNameCl);

    while (getline(openInvFileCl, lineCl, ',')) {
        lineCl.erase(remove(lineCl.begin(), lineCl.end(), ' '));
        invDataCl.push_back(lineCl);
    }
}

string InventoryStorage::getFileInvData(int invDataTmp) {
    return invDataCl[invDataTmp];
}

Main.cpp

#include <iostream>
#include "InventoryStorage.h"
#include "ShoppingExperience.h"

using namespace std;

int main() {
    
    InventoryStorage invStObj;                         //obj to create instance of InventoryStorage class
    InventoryStorage& invStRefObj = invStObj;          //reference to obj that I can use in other classes, so that I can use same instance
    invStObj.storeFileInvData("inventoryData.txt");

    cout << "test items" << endl;
    for (int i = 0; i < 4; i  ) {
        cout << invStObj.getFileInvData(i) << endl;    //object and getter work fine in main, output names
    }

    cout << "\n";

    ShoppingExperience shopExpObj;                     //program errors, ShoppingExperience class will not out any names
                                                       //ShoppingExperience class uses the reference object unsuccessfully
    return 0;
}

ShoppingExperience.h

#pragma once
#include <iostream>
using std::cout;
using std::endl;

class ShoppingExperience {
public:
    ShoppingExperience();

private:
};

ShoppingExperience.cpp

#include "ShoppingExperience.h"
#include "InventoryStorage.h"

ShoppingExperience::ShoppingExperience() {

    InventoryStorage invStRefObj;                   //trying to reference first instance of object for InventoryStorage class inside ShoppingExperience class

    cout << "Item List in Inventory" << endl;       //only outputs "Item List in Inventory"
    for (int i = 0; i < 4; i  ) {
        cout << invStRefObj.getFileInvData(i) << endl;
    }
                                        //no names are outputted, then errors and program stops
}                                       //vector subscript out of range (the vector is empty)
                                        //doesn't appear to be using object of same instance like I thought the referenced object would ensure

CodePudding user response:

InventoryStorage invStRefObj is a completely new object unrelated to the reference declared in main. You need to pass the object via reference to the constructor of ShoppingExperience:

In main:

ShoppingExperience shopExpObj(invStObj);

In the header:

class ShoppingExperience {
public:
    ShoppingExperience(InventoryStorage& invStRefObj);

private:
};

In the cpp:

ShoppingExperience::ShoppingExperience(InventoryStorage& invStRefObj) {

    cout << "Item List in Inventory" << endl;       //only outputs "Item List in Inventory"
    for (int i = 0; i < 4; i  ) {
        cout << invStRefObj.getFileInvData(i) << endl;
    }
}

Note that it's not necessary to create a reference in main. You can just pass an object directly to a function/method/constructor that expects a reference.

You should avoid putting using namespace in header files as these will then apply to all places that header is included.

  • Related