0

I am trying to create a vector of derived objects from within their base class.

class Animal
{
 // Do Stuff
}

class Dog : public Animal

{
 // Do Stuff
}

class AnimalKingdom
{
    vector<Animal> animals;
    vector<Dog> getDogs();
}

vector<Dog> AnimalKingdom::getDogs();
{

    vector<Dog*> dogs;        

    for(i = 0; i < animals.size(); i++)
    {
        Animal& a = *animals[i];

        if(typeid(a).name() == "class Dog")
        {
            dogs.push_back(*a);
        }
    }
}

But obviously *a isn't a pointer to a dog so it can't be added to dogs?

Does that make sense?

jossgray
  • 497
  • 6
  • 20

3 Answers3

0

You need to type cast Animal into a Dog. Do some reading on what static_cast and dynamic_cast are. But generally static_cast is if you know what type you are converting to, and dynamic_cast is a guess and will return null if it not that type.

for(i = 0; i < animals.size(); i++)
{
    Animal* a = &animals[i];

    if(typeid(a).name() == "class Dog")
    {
        dogs.push_back(static_cast<Dog>(a));
    }
}

Ps.Im at work so I cant check that code, looks rightish tho =D

Chris Condy
  • 626
  • 2
  • 9
  • 25
0

First, typeid(a).name() will return a string that is compiler specific. In my gcc, for example, the returned string would be something totally different. Also, think of a third class that is subclass of Dog. Your typeid(a).name() would give you "class Chihuahua", which is a dog, but is not "class Dog".

You should use dynamic_cast for querying object type. When you do dynamic_cast<Dog*>(a) you are asking "can a be correctly casted to Dog?". If yes, you will have a pointer of type Dog*, if not you will have a NULL pointer.

Finally, at class AnimalKingdom , your vector is not going to allow you to have objects of type Dog. When you create a std::vector<Animal>, you are creating a vector whose elements are of fixed type sizeof(Animal). What you need is to work with pointers. A pointer points to a memory address without forcing this address to be of any size or of the base class.

Just to make it a bit more clear: When you do Animal a; you are creating a variable that is of the type Animal and has size sizeof(Animal). When you do Animal* a you are creating an memory address that has the size 4 bytes (or 8 bytes), for any pointer this will have this size. So it is possible that the Animal* points to something different than Animal, it may point to a subclass of Animal.

This is the difference between static allocation (fixed size) and dynamic allocation (dynamic size, but note that the pointer has a fixed size).

André Puel
  • 8,741
  • 9
  • 52
  • 83
0

Your main problem is to understand you can not up-cast, This yields null. you can downcast the dog into animal and use only the min attributes of the parent though,

So this problem can be easily solved like: 1- return vector and use polymorphic flow to do whatever you want later. 2- make some bool or int to check or mark the kind of animal as below. e.g. make it 2 for dogs, This variable is defined in animal class. then use virtual functions to dynamically go to whatever you want at run time. so the below code can be good skeleton for you.

class Animal
{
    int type;
    virtual void setType()=0;
    virtual int getType()=0;
};

class Dog :public Animal
{
    void setType()
    {
        type = 2;
    }
    int gettype()
    {
        return type;
    }
}; 

Have fun.

blackmath
  • 242
  • 1
  • 10