Я хочу создать общий вектор ptr различных объектов - PullRequest
0 голосов
/ 25 марта 2020

У вас есть 2 класса Cats и Dogs, и вам нужно создать вектор общих указателей, в котором будут храниться данные из этих 2 классов. Подсказки: полиморфизм и имейте в виду, что классы могут иметь похожие поля.

Так вот, что я делал до сих пор. Я хочу вставить в этот shared_ptr vector всю информацию Cats и Dogs классов, но я не знаю как. Мне удалось только вставить в это vector данные из базового класса.

#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) {}

    friend std::ostream& operator<<(std::ostream& os, const Animal& a)
    {
        os << "Name: " << a.name << std::endl;
        os << "Age: " << a.age << std::endl;

        return os;
    }
};

class Cats: public Animal
{
    std::string race;
    std::string pref_food;
public:
    Cats(int t = 0, std::string n = "", int a = 0, std::string r = "", std::string mnprf = ""):
        Animal(t, n, a), race(r), pref_food(mnprf) {}

    friend std::ostream& operator<<(std::ostream& os, const Cats& c)
    {
        // auto n = static_cast<Animal> (c);
        os << "Name: " << c.name << std::endl;
        os << "Age: " << c.age << std::endl;
        os << "race: " << c.race << std::endl;
        os << "Fav food: " << c.pref_food << std::endl;

        return os;
    }
};

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) {}

    friend std::ostream& operator<<(std::ostream& os, const Dog& d)
    {
        os << "Name: " << d.name << std::endl;
        os << "Age: " << d.age << std::endl;
        os << "disease: " << d.disease << std::endl;
        os << "master: " << d.master << std::endl;

        return os;
    }
};

template<typename T>
void add(std::vector<std::shared_ptr<Animal>>& vec, const T& a)
{
    auto newptr = std::make_shared<Animal>(a);
    vec.push_back(newptr);
}

int main()
{
    std::vector<std::shared_ptr<Animal>> Animals;
    Dog d(1,"Rex", 12, "idk", "Oscar");
    Cats c(0,"Meaw", 11, "Sfinx", "Catfood");
    add(Animals,d);
    add(Animals,c);

    for(auto i: Animals)
    {
        std::cout << *i;
    }
}

1 Ответ

1 голос
/ 25 марта 2020

Есть несколько проблем с вашим кодом:

  1. Animal не хватает virtual методов. По крайней мере, ему нужен деструктор virtual, так что деструкторы Cats и Dog вызываются правильно, когда shared_ptr<Animal> вызывает delete на своем удерживаемом указателе Animal*.

  2. add() создает экземпляр Animal специально, независимо от T. Таким образом, ваш vector содержит только реальные Animal объекты. add() нужно вместо этого создать экземпляр T. std::shared_ptr<T> может быть присвоено std::shared_ptr<Animal>, когда T происходит от Animal. Конечно, add() является избыточным, main() может просто создавать и добавлять новые объекты непосредственно в vector без использования add().

  3. Когда 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...