【问题标题】:I want to create a shared ptr vector of different objects我想创建不同对象的共享 ptr 向量
【发布时间】:2020-03-25 18:01:36
【问题描述】:

您有 2 个类 Cats 和 Dogs,需要创建一个共享指针向量来存储这 2 个类的数据。提示:多态性并记住类可以有相似的字段。

这就是我到目前为止所做的。我想在 shared_ptr vector 中插入 CatsDogs 类的所有信息,但我不知道如何。我只设法在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;
    }
}

【问题讨论】:

  • 记住你学到的关于多态性的知识......不清楚为什么你首先在堆栈上创建Dog d(...)Cats c(...),然后复制它们来构造智能指针。从一开始就使用shared_ptr
  • std::make_shared&lt;Animal&gt; 更改为std::make_shared&lt;T&gt; 将是一个好的开始
  • 你为什么要创建这么多对象并通过add函数绕道而行?你不需要比Animals.push_back(std::make_shared&lt;Dog&gt;(1,"Rex", 12, "idk", "Oscar"); 更复杂的东西。如果确实需要add,那么要复制的对象的类型是T,而不是Animal
  • 如果您要存储指向诸如Animal 之类的基类的指针,该类应该有一个虚拟析构函数。

标签: c++ vector shared-ptr insertion


【解决方案1】:

您的代码存在一些问题:

  1. Animal 缺少任何 virtual 方法。至少,它需要一个virtual 析构函数,以便shared_ptr&lt;Animal&gt; 在其持有的Animal* 指针上调用delete 时正确调用CatsDog 的析构函数。

    李>
  2. add() 正在专门创建Animal 的实例,而不管T。所以你的 vector 只包含真正的 Animal 对象。 add() 需要创建 T 的实例。当T 派生自Animal 时,可以将std::shared_ptr&lt;T&gt; 分配给std::shared_ptr&lt;Animal&gt;。当然,add() 是多余的,main() 可以直接创建新对象并将其添加到其vector,而完全不使用add()

  3. main()Animal上调用operator&lt;&lt;时,它不会调用CatsDog定义的operator&lt;&lt;,只会调用Animal定义的operator&lt;&lt;。这可以通过让operator&lt;&lt;Animal 中调用virtual 方法来解决,该方法CatsDog 覆盖。当基类也有operator&lt;&lt;时,不需要在派生类中定义operator&lt;&lt;

试试这个:

#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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-15
    • 1970-01-01
    • 2017-04-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多