将派生类对象存储在基类变量中

新手上路,请多包涵

我想将几个类的实例存储在一个向量中。由于所有类都继承自同一个基类,这应该是可能的。

想象一下这个程序:

 #include <iostream>
#include <vector>
using namespace std;

class Base
{
    public:
    virtual void identify ()
    {
        cout << "BASE" << endl;
    }
};

class Derived: public Base
{
    public:
    virtual void identify ()
    {
        cout << "DERIVED" << endl;
    }
};

int main ()
{
    Derived derived;

    vector<Base> vect;
    vect.push_back(derived);

    vect[0].identify();
    return 0;
}

我希望它打印 "DERIVED" ,因为 identify() 方法是 virtual 。相反 vect[0] 似乎是一个 Base 实例,它打印 "BASE"

我想我可以编写自己的容器(可能源自 vector )以某种方式能够做到这一点(也许只保存指针……)。

我只是想问一下是否有更多的 C++‘ish 方式来做到这一点。而且我想完全兼容 vector (只是为了方便其他用户使用我的代码)。

原文由 drakide 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 707
2 个回答

您所看到的是 Object Slicing

您将派生类的对象存储在一个向量中,该向量应该存储基类的对象,这会导致对象切片,并且正在存储的对象的派生类特定成员被切掉,因此存储在向量中的对象只是充当基类的对象。

解决方案:

您应该在向量中存储指向基类对象的指针:

 vector<Base*>

通过存储指向 Base 类的指针,就不会进行切片,并且您也可以实现所需的多态行为。

由于您要求 C++ish 这样做的方式,正确的方法是使用合适的 智能指针,而不是在向量中存储原始指针。这将确保您不必手动管理内存, RAII 会自动为您完成。

原文由 Alok Save 发布,翻译遵循 CC BY-SA 3.0 许可协议

正如这里提到的所有其他人一样,由于复制构造时会发生对象切片,您无法完成将 派生 对象插入到 向量中。

如果目标是避免内存分配,您可以使用 std::variant ,但向量将不再是

using HierarchyItem = std::variant<Base, Derived>;

int main()
{
    vector<HierarchyItem> vect;
    vect.push_back(Derived());

    std::visit([](auto &&hier_item){ hier_item.identify(); }, vect[0]);

    return 0;
}

原文由 Angelos Gkaraleas 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题