如何创建包含基类和任何派生类的向量?
例如,在国际象棋引擎中,我目前有一个Move
类,它存储一个特定的动作和一些功能来帮助它。为了节省内存,因为将要创建数百万个这样的对象,我还有一个派生类CaptureMove
,它扩展了Move
类,存储了有关捕获的内容和位置的更多信息
从我可以收集到的内容中,指向Move
对象的指针应该有效,但我不太清楚如何去做。
答案 0 :(得分: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并且它的一些指针仍在使用中。
例如,如果以集中方式创建和删除对象,则此方法很实用,因此向量仅使用在其他位置正确管理的指针。
共享基本指针的向量:
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;
这种方法只值得考虑,如果派生类的数量非常有限,但你有大量的小对象(因此内存分配将成为一个真正的开销)几乎相同的大小。