-1

I have to read from a file and instantiate objects based on the line of the file I'm reading from.

The file has the format:

num1 RandomString RandomString num2 num3 num4<br>
num1 RandomString RandomString<br>
num1 RandomString RandomString num2 num3 num4<br>

The num1 identifies the type of object I need to instantiate. For example, if num1 is a 1, then I need to create a dog object, if it is anything else then I need to make a generic animal object.

The code below is halfway there.

NOTE: I haven't bothered with making members private at the moment. Not a priority right now.

#include <vector>
etc...

class Animal {
    public:
        int num1;
        string 1;
        string 2;
        int num2;
        int num3;
        int num4;
        std::string restOfTheLine;
        Animal(fLine){
            std::stringstream stream(fLine)
            stream >> num1;
            std::getline(stream, restOfTheLine);
       getFunctions etc...
}

class Dog : public Animal{


}


int main(){

    ifstream file("file.txt");
    std::string line;
    std::vector<Animal*> animals;

    while(!file.eof()){
        std::getline(file,line);
        if(line[0]=='1'){
            Dog* dog = new Dog(line);
            animals.push_back(dog);
        } 
        else{
            Animal* animal = new Animal(line);
            animals.push_back(animal);
        }
    std::cout << animals[2]->getNum2();
       

}

so I'm checking if the first character of the line is a 1. If it is, then a dog object has to be instantiated.

When I compile it gives me an error - error:no matching function for call dog::dog, which is obviously because I haven't written anything in the derived dog class because I'm unsure how to approach it.

I have a vector of type pointer to animal, so how can I add a pointer to dog using inheritance?

  • 2
    Not related to your issue, but `while(!file.eof()){ std::getline(file,line); ... }` [is wrong](https://stackoverflow.com/questions/5605125/), it should be `while(std::getline(file,line)){ ... }` – Remy Lebeau Feb 17 '21 at 23:57
  • If there was no vector here, how would you "approach it"? You would "approach it" here exactly the same way. It is unclear what your question is. "Approach it" is too vague and nebulous to have a specific, precise answer. – Sam Varshavchik Feb 18 '21 at 00:00
  • I'm trying to populate member variables for a dog object, but i want that dog object to be part of the animals vector if that clears up any misconceptions? – CSS_Mast Feb 18 '21 at 00:02
  • Recommendation: Rather than starting with all members `public` to make access easier start with all members `private` to make debugging easier. – user4581301 Feb 18 '21 at 00:02
  • It's perfectly clear what you're trying to do. What is completely unclear is what is your ***specific*** question? A good analogy would be: you state that you want to know how to fix your car, and you clarify that you're trying to use your car to get to the other side of the town. Ok, but what, specifically, is wrong with your car? Similarly, what is your ***specific*** C++ question? – Sam Varshavchik Feb 18 '21 at 00:41

1 Answers1

1

You are trying to call a Dog() constructor that doesn't exist, just like the error message is telling you. So simply add such a constructor.

You also need a virtual destructor in Animal in order to properly destroy a Dog object via an Animal* pointer.

Try this:

#include <fstream>
#include <vector>
#include <string>
...
using namespace std;

class Animal {
    public:
        ...
        Animal(const string &fLine) {
            ...
        }

        virtual ~Animal() {}

        ...
};

class Dog : public Animal{
    public:
        Dog(const string &fLine) : Animal(fLine) {}
};

int main() {
    ifstream file("file.txt");
    std::string line;
    std::vector<Animal*> animals;

    while (std::getline(file, line)) {
        if (line.empty()) continue;
        if (line[0] == '1') {
            animals.push_back(new Dog(line));
        } 
        else {
            animals.push_back(new Animal(line));
        }
        ...
    }       

    for(size_t i = 0; i < animals.size(); ++i) {
        delete animals[i];
    }

    return 0;
}

If you are using C++11 or later, consider using std::unique_ptr to manage object destructions for you:

#include <fstream>
#include <vector>
#include <string>
#include <memory>
...
using namespace std;

class Animal {
    public:
        ...
        Animal(const string &fLine) {
            ...
        }

        virtual ~Animal() {}

        ...
};

class Dog : public Animal{
    public:
        Dog(const string &fLine) : Animal(fLine) {}
};

int main() {
    ifstream file("file.txt");
    std::string line;
    std::vector<std::unique_ptr<Animal>> animals;

    while (std::getline(file, line)) {
        if (line.empty()) continue;
        if (line[0] == '1') {
            // if using C++11:
            animals.push_back(std::unique_ptr<Animal>(new Dog(line)));
            // if using C++14 and later:
            animals.push_back(std::make_unique<Dog>(line));
        } 
        else {
            // if using C++11:
            animals.push_back(std::unique_ptr<Animal>(new Animal(line)));
            // if using C++14 and later:
            animals.push_back(std::make_unique<Animal>(line));
        }
        ...
    }       

    return 0;
}
Remy Lebeau
  • 454,445
  • 28
  • 366
  • 620