基础对象和继承对象的向量

Posted

技术标签:

【中文标题】基础对象和继承对象的向量【英文标题】:Vector of base and inherited objects 【发布时间】:2015-08-01 09:15:51 【问题描述】:

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

例如,在国际象棋引擎中,我目前有一个 Move 类,它存储了一个特定的移动和一些帮助它的函数。为了节省内存,因为将要创建数百万个这样的对象,我还有一个派生类 CaptureMove,它扩展了 Move 类,存储了有关捕获的内容和位置的更多信息。

据我所知,指向Move 对象的指针应该可以工作,但我不太确定如何去做。

【问题讨论】:

这有点宽泛。如何去做是你制作一个指针向量,并将指针存储在其中。 您应该注意对象切片。一种常见的方法是使用类似std::vector<std::unique_ptr<Move>> 【参考方案1】:

这个问题相当广泛。这里有一些想法:

基指针向量:

如果您的类是多态的(即基类的相关函数是虚拟的),这将非常有效。

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<shared_ptr<Move>> m; 
m.push_back(make_shared<Move>());
m.push_back(make_shared<CaptureMove>());
m.push_back(make_shared<Move>());

这里是online demo。

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

老实说,这有点开销,但确实值得,以便获得可靠的代码。如果我必须这样做,这是我个人会采取的方法。

复合对象的向量

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

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

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

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

【讨论】:

以上是关于基础对象和继承对象的向量的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中具有继承的对象向量

将继承的类对象的向量传递给期望基类向量的函数

将对象存储在向量中,编译器说元素不存在

从继承的对象中检索信息

Python基础(二十三):面向对象之继承介绍

C++继承问题