0

I have the following class hierarchy: Crocodile Class extends from Oviparous which extends from Animal

I need to store objects of type Crocodile, Goose, Pelican, Bat, Whale and SeaLion inside a vector, so:

1- I create the global vector:

vector<Animal*> animals;

2- I add objects (Crocodile, Goose, Pelican, Bat, Whale, SeaLion) to the vector:

animals.push_back(new Crocodile(name, code, numberofEggs));

3- I loop through the vector to print each object on a table

for (size_t i = 0; i < animals.size(); ++i){
    /* now the problem is here, each animal[i] is of type = "Animal", not Crocodile, or Goose, etc..
   /* so when I try to do something like the line below it doesn't work because it can't find the method because that method is not on the Animal Class of course */
   cout << animals[i]->GetName(); // THIS WORK
   cout << animals[i]->GetNumberofEggs(); //THIS DOESN'T WORK
   /* when I debug using the line below, every object on the vector is returning "P6Animal" */
   cout << typeid(animals[i]).name(); // P6Animal instead of Crocodile
}

I think it is related with this post std::vector for parent and child class and I think the problem is object slicing, so I tried creating the vector like this:

vector<unique_ptr<Animal>> animals;
//and adding the objects like this
animals.push_back(unique_ptr<Animal>(new Crocodile(name, code, numberofEggs)));

But nothing

Any help would be great! Thank you!

Pedro
  • 3
  • 1
  • 5
    Since you're using pointers it is not a slicing problem. Using a smart pointer is better than a raw pointer though, so keep using that. I suspect what is happening is that you do not have the `GetNumberofEggs()` function in your base class. Please work on a [mcve] . – Retired Ninja Jun 25 '20 at 03:22
  • `typeid::name` is not as useful as you'd like it to be. The type really is pointer to `Animal`. Consider adding a `name` virtual function to animal. – user4581301 Jun 25 '20 at 03:34
  • 1
    Here's a small example that may help explain the `typeid` issue: https://ideone.com/UWwdXF – Retired Ninja Jun 25 '20 at 03:38
  • I'm with Ninja. But how far are you willing to go for those eggs? Animals have eggs, but a lot of them don't lay eggs, so depending on what you mean by `GetNumberofEggs`, it may not make sense in `Animal`. – user4581301 Jun 25 '20 at 03:44

2 Answers2

0

Your problem is that you try to access to specific child's method, that not defined in the parent class, from an object that has a parent type.

You should store an object as a type you want to work with, so if you store an array of Animal implies that you will work with objects using only the Animal interface, regardless of the initial object type. Otherwise, if you need to access methods from Opivarous class you should think about store your objects as Opivarous (or Crocodile, etc).

Also, you can use dynamic_cast for this purpose:

if(Crocodile* crocodile = dynamic_cast<Crocodile*>(animals[i]))
{
    cout << crocodile->GetNumberofEggs();
}

It is the simplest way to solve a problem, but it shows that there are problems with architecture in your code.

LastSymbol0
  • 14
  • 1
  • 2
0

I got it working with having a virtual "Print" method on the Animal class, then override this method from the child classes. Thank you everyone!

Pedro
  • 3
  • 1