简体   繁体   中英

Clear a vector of derived classes using a function with a vector of class as argument

I have a class Animal , with two derived classes Cat and Dog respectively. I also have a class House which contains two lists as attributes: a list of every cat in the house ( std::vector<Cat*> ), and a list of every dog ( vector<Dog*> ).

My goal is to code a function in House which clears a list of animals ( void House::clearList( std::vector<Animal*> ) ). I'd like to avoid duplicating code as much as possible. Hence, creating one function for both list would be optimal.

I'd like to call this function in the destructor of House :

class Animal{};

class Dog : public Animal{};
class Cat : public Animal{};

class House{
    private :
        std::vector<Dog*> Dogs;
        std::vector<Cat*> Cats;
    public :
       ~House(){
            clearList(dogs);
            clearList(cats);
       }
       clearList(std::vector<Animal*> animals){
            for (auto& animal : animals){
                 animal=nullptr;
                 delete animal;
            }
       }
};

The compiler displays :

error: no matching function for call to ' House::clearList(std::vector<Cat*>&) ' note: no known conversion for argument 1 from ' std::vector<Cat*> ' to ' std::vector<Animal*> '

I can't use shared_ptr nor unique_ptr in my code.

How can I use polymorphism to solve this?

Polymorphism isn't what you are looking for. You can use a template instead, eg:

class Animal{
    public:
        virtual ~Animal(){}
};

class Dog : public Animal{};
class Cat : public Animal{};

class House{
    private :
        std::vector<Dog*> Dogs;
        std::vector<Cat*> Cats;

        template<typename T>
        void clearList(std::vector<T*> &animals){
            for (T *animal : animals){
                 delete animal;
            }
            animals.clear();
        }

    public :
        ~House(){
            clearList(dogs);
            clearList(cats);
        }
};

If you really want to use polymorphism for the function, then you would have to change the vector objects to be the same type, then you don't need the template, eg:

class Animal{
    public:
        virtual ~Animal(){}
};

class Dog : public Animal{};
class Cat : public Animal{};

class House{
    private :
        std::vector<Animal*> Dogs;
        std::vector<Animal*> Cats;

        void clearList(std::vector<Animal*> &animals){
            for (Animal *animal : animals){
                 delete animal;
            }
            animals.clear();
        }

    public :
        ~House(){
            clearList(dogs);
            clearList(cats);
        }
};

Otherwise, simply do not store pointers to begin with, and let vector 's own destructor destroy the objects for you:

class Animal{
    public:
        virtual ~Animal(){}
};

class Dog : public Animal{};
class Cat : public Animal{};

class House{
    private :
        std::vector<Dog> Dogs;
        std::vector<Cat> Cats;
};

To effectively use polymorphism, you need two things: virtual functions, and pointers or references to the base class. In your case, since you already have pointers, just make them pointers to the base class rather than the derived class. And since you want to delete these pointers, make the destructors virtual.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM