Making a vector of instances of different subclasses

旧巷老猫 提交于 2019-11-26 23:24:07

问题


Tried searching, nothing returns( i ithink).

Is it possible to make a vector of an abstract class?

For example, I have the super class Unit.

And I Have the subclasses soldier, vehicle, and bomber.

However I would want ever instance of any subclass in one vector, e.g. the vector UnitList can hold instances of both soldier and vehicle?

Is this possible? I'm using C++ if it helps.


回答1:


Yes, but you'll need to use either pointers or smart pointers (I'd go with this).

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;
}

Don't forget to delete the allocated memory.

Why you can't use actual objects:

Assume std::vector<X>. This is illegal because:

  1. If you want to initialize your vector with some number of elements, the allocation would fail. A vector stores objects internally in continuous memory. A preallocation would fail because it would mean it needed to create objects, which can't be done for abstract classes.

  2. Even if you could, or the base class wasn't abstract, it wouldn't help too much, as you'd suffer from object slicing.




回答2:


Since each of those objects is different sizes, the proper way to do this is a container containing pointers to the base class Unit, (and be sure it has a virtual destructor.

Option 1: boost::ptr_vector (requires boost libraries, which you should have anyway)

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

Option 2: std::vector<std::unique_ptr<Unit>> (requires C++11 compiler)

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



回答3:


You cannot literally create a vector of objects of an abstract class, because the vector template needs to be able to tell the compiler, at compile time, the size of its element. However, you can get what you want by keeping a vector of pointers to objects rather than a vector of objects as such.

Update: Abstract classes as such have known size. It is actually instances of their most derived types whose sizes are unknown at compile time. (Thanks @LuchianGrigore and @MooingDuck for pointing this out.)




回答4:


I don't think it's possible to do this:

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

Because Soldier, Vehicle, and Unit take up different amounts of memory.

However, it might be possible to use pointers, as all pointers take up a fixed amount of memory:

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

I haven't tested it, but it makes sense in my head anyway.



来源:https://stackoverflow.com/questions/10338548/making-a-vector-of-instances-of-different-subclasses

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!