Есть несколько проблем с вашим кодом:
Animal
не хватает virtual
методов. По крайней мере, ему нужен деструктор virtual
, так что деструкторы Cats
и Dog
вызываются правильно, когда shared_ptr<Animal>
вызывает delete
на своем удерживаемом указателе Animal*
.
add()
создает экземпляр Animal
специально, независимо от T
. Таким образом, ваш vector
содержит только реальные Animal
объекты. add()
нужно вместо этого создать экземпляр T
. std::shared_ptr<T>
может быть присвоено std::shared_ptr<Animal>
, когда T
происходит от Animal
. Конечно, add()
является избыточным, main()
может просто создавать и добавлять новые объекты непосредственно в vector
без использования add()
.
Когда main()
вызывает operator<<
на Animal
, он не будет вызывать operator<<
, определенный Cats
или Dog
, только operator<<
, определенный Animal
. Это можно исправить, если operator<<
in Animal
вызвать метод virtual
, который Cats
и Dog
переопределяет. Нет необходимости определять operator<<
в производных классах, когда базовый класс также имеет operator<<
.
Попробуйте вместо этого:
#include <iostream>
#include <vector>
#include <memory>
class Animal
{
protected:
int tip;
std::string name;
int age;
public:
Animal(int t, std::string n, int a): tip(t), name(n), age(a) {}
virtual ~Animal() {}
virtual void print(std::ostream& os) const
{
os << "Name: " << name << std::endl;
os << "Age: " << age << std::endl;
}
friend std::ostream& operator<<(std::ostream& os, const Animal& a)
{
a.print(os);
return os;
}
};
class Cat : public Animal
{
std::string race;
std::string pref_food;
public:
Cat(int t = 0, std::string n = "", int a = 0, std::string r = "", std::string mnprf = ""):
Animal(t, n, a), race(r), pref_food(mnprf) {}
void print(std::ostream& os) const override
{
Animal::print(os);
os << "race: " << race << std::endl;
os << "Fav food: " << pref_food << std::endl;
}
};
class Dog : public Animal
{
std::string disease;
std::string master;
public:
Dog(int t = 1, std::string n = "", int a = 0, std::string b = "", std::string s = ""):
Animal(t, n, a), disease(b), master(s) {}
void print(std::ostream& os) const override
{
Animal::print(os);
os << "disease: " << disease << std::endl;
os << "master: " << master << std::endl;
}
};
template<typename T>
void add(std::vector<std::shared_ptr<Animal>> &vec, const T &a)
{
auto newptr = std::make_shared<T>(a);
vec.push_back(newptr);
}
int main()
{
std::vector<std::shared_ptr<Animal>> Animals;
Dog d(1,"Rex", 12, "idk", "Oscar");
Cat c(0,"Meaw", 11, "Sfinx", "Catfood");
add(Animals, d);
add(Animals, c);
/* alternatively:
Animals.push_back(std::make_shared<Dog>(1,"Rex", 12, "idk", "Oscar"));
Animals.push_back(std::make_shared<Cat>(0,"Meaw", 11, "Sfinx", "Catfood"));
*/
for(auto &i: Animals)
{
std::cout << *i;
}
return 0;
}
Вывод:
Name: Rex
Age: 12
disease: idk
master: Oscar
Name: Meaw
Age: 11
race: Sfinx
Fav food: Catfood
Live Demo