0

I am attempting to make a vector that stores a base class and then passes it to another class which then accesses the derived class from the vector of base classes I have found multiple Stack Overflow questions covering this but they are all missing certain aspects like passing this across classes or storing multiple objects in a vector. CPP File

vector<Item*> Items::cM() {
    vector<Item*> M;
    string line;
    string filePath = "...";
    ifstream stream(filePath);
    while (getline(stream, line)) {
        vector <string> IV= UtilFunctions::splitString(line, ',');
        const char *t= IV[0].c_str();
        switch (*t) {
        case 'a': {
            StarterFood tmpStarter = StarterFood(*a,b,c);//Simplified
            Item* b = &tmpStarter;
            M.push_back(b);
            //If I use b here and do b->toString() works as expected
            break;
        }
        
        }
        
    }
    return M;
}

Main

int main(){
    vector <Item*> i= Items::cM();
    items[0]->toString();//This is an overloaded function that all of the derived classes 
    //Throws the error Access violation reading location 0xCCCCCCCC.
    have such as starterfood
    system("pause");
    return 0;
}

If anymore information is needed please feel free to ask. Thanks I have also tried passing a pointer and then de referencing the pointer but I think that slices my object leaving just the base class and I have tried to implement unique_ptr but i get a syntax error saying there is no overload that returns unique_ptr from starterFood. The error is Access violation reading location 0xCCCCCCCC.

David Benz
  • 49
  • 6
  • 3
    `Item* b = &tmpStarter;` You are storing a pointer to a temporary and trying to access it after it goes out of scope. – Passerby Nov 05 '21 at 23:10
  • I did think that but this is the only attempt so far that dosen't throw a syntax error what would I do to fix this. I tried just passing &tmpStarter but that just pulls out the base class toString – David Benz Nov 05 '21 at 23:11
  • @Passerby Not a pointer to a temporary, but to a local variable that goes out of scope. A pointer to a temporary would look more like `&StarterFood(*a,b,c)`. Not a huge difference, though, since the end result is still a dangling pointer. – JaMiT Nov 05 '21 at 23:20
  • 1
    Some relevant reading (I'm undecided which would be a suitable duplicate for this one): [Appending vector of pointers inside member function of a class causing odd behaviour](https://stackoverflow.com/questions/38447328/) -- [printf() seems to change a variable](https://stackoverflow.com/questions/44608839/) -- [What is difference between instantiating an object using new vs. without](https://stackoverflow.com/questions/3673998/) – JaMiT Nov 05 '21 at 23:26
  • Thanks for the reading material, I am aware of the first issue which is that it goes out of reference my issue is i'm not sure how to prevent that. – David Benz Nov 05 '21 at 23:27
  • 2
    Using `unique_ptr` is likely a good idea. I'd advise revising your question to show that approach and ask about the (first) error you got that way. – JaMiT Nov 05 '21 at 23:27
  • The issue that I get when i use unique_ptr is that when i push_back the object on to M i get told there is no override of starterFood that returns unqiue_ptr – David Benz Nov 05 '21 at 23:30

1 Answers1

0

As suggested i used unique_ptr i had to use make_unique on the derived class and move in the derived class when storing in a vector and replaced all vector<Item*> with vector<unique_ptr> but it now works.

vector<unique_ptr<Item>> Items::cM() {
    vector<unique_ptr<Item>> M;
    string line;
    string filePath = "...";
    ifstream stream(filePath);
    while (getline(stream, line)) {
        vector <string> IV= UtilFunctions::splitString(line, ',');
        const char *t= IV[0].c_str();
        switch (*t) {
        case 'a': {
            unique_ptr<StarterFood> tmpStarter = make_unique<StarterFood> 
            (*a,b,c);
            M.push_back(std::move(tmpStarter));
            break;
        }
        
        }
        
    }
    return M;
}

Then in main

    vector<unique_ptr<Item>> i= Items::cM();
    items[0]->toString();//This is an overloaded function that all of the 
    derived classes
    system("pause");
    return 0;

This solves the issue of object slicing with my original attempt.

David Benz
  • 49
  • 6