6

尝试搜索,没有返回(我认为)。

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

例如,我有超类 Unit。

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

但是我想要一个向量中的任何子类的实例,例如向量 UnitList 可以同时包含士兵和车辆的实例?

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

4

4 回答 4

11

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

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. 即使你可以,或者基类不是抽象的,它也不会有太大帮助,因为你会遭受对象切片的痛苦。

于 2012-04-26T17:39:35.010 回答
9

由于这些对象中的每一个都有不同的大小,因此正确的方法是使用包含指向基类的指针的容器Unit,(并确保它具有virtual析构函数。

选项 1:(boost::ptr_vector需要 boost 库,无论如何你都应该拥有)

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()));
于 2012-04-26T17:53:04.653 回答
2

您不能从字面上创建抽象类对象的向量,因为向量模板需要能够在编译时告诉编译器其元素的大小。但是,您可以通过保留指向对象的指针向量而不是对象向量来获得所需的内容。

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

于 2012-04-26T17:43:28.773 回答
1

我认为不可能这样做:

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

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

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

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

我没有测试过它,但无论如何它在我的脑海中是有道理的。

于 2012-04-26T17:44:42.833 回答