基对象和继承对象的向量

Vector of base and inherited objects

本文关键字:对象 向量 继承      更新时间:2023-10-16

如何创建一个既包含基类又包含派生类的vector ?

例如,在国际象棋引擎中,我目前有一个Move类,它存储一个特定的移动和一些函数来帮助它。为了节省内存,因为数以百万计的这些对象将被创建,我也有一个派生类CaptureMove扩展Move类存储更多的信息,关于什么和在哪里捕获的片段。

从我能收集到的,指向Move对象的指针应该工作,但我不太确定如何去做。

这个问题很宽泛。以下是一些想法:

基指针的向量:

如果你的类是多态的(即基类的相关函数是虚的),这工作得非常好。

vector<Move*> mp; 
mp.push_back (new Move);     // attention, you have to delete it ofr memory will leak
mp.push_back (new CaptureMove);

这是最简单的方法。然而,你必须确保当你添加一个对象时,它被正确分配(例如用new创建),并且一旦你不再需要它,你就删除它。这可能是非常麻烦的,特别是如果vector被复制并且它的一些指针仍在使用。

这种方法可能是实用的,例如,如果你以集中的方式创建和删除对象,这样向量只使用在其他地方妥善管理的指针。

共享基指针的Vector:

vector<shared_ptr<Move>> m; 
m.push_back(make_shared<Move>());
m.push_back(make_shared<CaptureMove>());
m.push_back(make_shared<Move>());

这里有一个在线演示。

它扩展了指针解决方案,使用智能指针来处理未使用对象的释放。

老实说,这是一个小开销,但它是值得的,为了有可靠的代码。如果我必须这样做的话,我个人会采取这种方法。

复合对象向量

也可以选择存储对象而不是指向对象的指针。虽然这个想法看起来很简单,但很难做到,因为不同的衍生品可能有不同的大小。而且它有严重的缺点,因为您需要知道可能存储在vector中的所有可能的基类型和派生类型,这使得这种方法不那么灵活。

你当然可以用一个复杂的联合来管理它,但更简单的方法是使用boost::variant

vector<boost::variant<Move, CaptureMove>> m; 

这种方法只有在派生类的数量非常有限的情况下才值得考虑,但是您有大量几乎相同大小的小对象(因此内存分配将成为真正的开销)。