制作不同子类的实例的向量

时间:2012-04-26 17:38:39

标签: c++ oop class abstract

尝试搜索,没有任何回报(我正在寻找)。

是否可以制作抽象类的向量?

例如,我有超级单位。

我有士兵,车辆和轰炸机的子类。

但是我想要在一个向量中的任何子类的实例,例如向量UnitList可以保存士兵和车辆的实例吗?

这可能吗? 如果它有帮助,我正在使用C ++。

4 个答案:

答案 0 :(得分:8)

是的,但你需要使用指针或智能指针(我会选择这个)。

struct X
{
    virtual ~X() {}  //<--- as pointed out in the comments
                     // a virtual destructor is required
                     // for correct deletion
    virtual void foo() = 0;
};
struct Y : X
{
    virtual void foo() { }
};

int main()
{
    std::vector<X*> a;
    a.push_back(new Y);
    a[0]->foo();
    for ( int i = 0 ; i < a.size() ; i++ )
        delete a[i];
    return 0;
}

不要忘记删除已分配的内存。

为什么你不能使用实际的对象:

假设std::vector<X>。这是非法的,因为:

  1. 如果要使用一定数量的元素初始化矢量,则分配将失败。向量在内部将对象存储在连续内存中。预分配将失败,因为这意味着它需要创建对象,这对于抽象类是无法完成的。

  2. 即使你可以,或者基类不是抽象的,也不会太多,因为你会受到对象切片的影响。

答案 1 :(得分:7)

由于每个对象的大小不同,执行此操作的正确方法是包含指向基类Unit的指针的容器(并确保它具有virtual析构函数。

选项1:boost::ptr_vector(需要升级库,无论如何都需要)

ptr_vector<Unit> units;
units.push_back(new Soldier());

选项2:std::vector<std::unique_ptr<Unit>>(需要C ++ 11编译器)

std::vector<std::unique_ptr<Unit>> units;
units.emplace_back(std::unique_ptr<Unit>(new Soldier()));

答案 2 :(得分:2)

您无法逐字地创建抽象类对象的向量,因为向量模板需要能够在编译时告诉编译器元素的大小。但是,你可以通过保持指向对象的指针向量而不是对象向量来获得你想要的东西。

更新:抽象类具有已知大小。它实际上是大多数派生类型的实例,其大小在编译时是未知的。 (感谢@LuchianGrigore和@MooingDuck指出这一点。)

答案 3 :(得分:1)

我认为不可能这样做:

std::vector<Unit> unit_list;
unit_list.push_back(Soldier(params));

因为士兵,车辆和单位会占用不同的内存量。

但是,也许可以使用指针,因为所有指针占用了固定数量的内存:

std::vector<Unit*> unit_list;
unit_list.push_back(new Soldier(params));

我还没有对它进行测试,但无论如何它在我脑海中都是有意义的。