For what I'm working on, I'm making a class that holds a dynamic array of different sorts of pets. I have an abstract class of Animal, from which I have a few derived classes (Cat, Dog, Rabbit, Horse, etc.). I need to be able to add an instance of those derived classes to the end of the dynamic array. In the list object, I have a double pointer (Pet** pets) which is what is supposed to store the list of objects that have Pet as a base class. My thinking is that since Pet is the base class, then each pet pointer should be able to point to an object of type Cat or type Dog, etc.
I have a function in the PetArray class that is supposed to add an object to the end of the list, but I have a couple of issues:
I am totally stuck here and am not sure how to fix what's wrong. Any help anybody can provide is greatly appreciated.
Your thinking is correct, but your implementation of add()
is not optimal. If nothing else, it is leaking the old pets
array. But it is also just coded more complicated than it needs to be.
It should look more like the following instead (assuming pets
and length
were initialized properly before add()
is called, and that PetArray
is managing them correctly per the Rule of 3/5/0, and that your PetArray
object is not being corrupted from another bug elsewhere in your code):
void PetArray::add(Pet *p)
{
Pet** temp = new Pet*[length+1];
for(int i = 0; i < length; ++i)
{
temp[i] = pets[i];
}
temp[length] = p;
delete[] pets;
pets = temp;
++length;
}
UPDATE: you are not add()
'ing objects to your array correctly. You are creating your derived objects in automatic memory, not in dynamic memory. You are taking pointers to the objects right before they go out of scope and get destroyed, and then you add the now-invalid pointers to your array.
Pet* p;
...
if(species == "Cat"){
...
Cat c(name, species, age, weight, length);
p = &c;
} // <-- c is destroyed here!
// same goes for the other animal types, too...
...
add(p); // <-- p is invalid here!
This explains both problems you described. You are adding pointers to local memory that gets reused in each loop iteration, and then you crash when trying to access invalid objects.
You need to new
the objects instead, eg:
Pet* p;
...
if(species == "Cat"){
...
p = new Cat(name, species, age, weight, length);
}
// same for the other animal types, too...
...
add(p);