C++实现纯虚拟类的实例集合
我正在跨平台 C++ 中工作,并且定义了一些类,如下所示:(对于本示例进行了极大简化)
class ExampleBase
{
public:
ExampleBase( int blah ) : blah_test(blah) { }
virtual void DoSomething( ) = 0;
private:
int blah_test;
};
class ExampleImplementer : public ExampleBase
{
public:
ExampleImplementer( ) : ExampleBase( 5 ) { }
virtual void DoSomething( ) { /* unique implementation here */ }
};
最初我只有一个类,我在 std::vector 中存储了一堆实例并通过 const 传递参考。但现在我需要有一个基类(我想保持纯虚拟)和许多多态实现类。
拥有任何实现实例的集合,并且仍然具有无泄漏的简单内存管理(例如分配堆栈 std::vector)的最佳方法是什么?
显然我不能有一个 std::vector<示例库>现在,由于 std::vector 要求该类是非纯虚拟的(因为它进行内部分配/复制等)。我不希望我的代码的用户意外创建 ExampleBase 的实例,因为这是错误的。我还想避免任何对象切片或任何其他讨厌的可能性。
std::auto_ptr
数组可以完成这项工作,但随后我必须处理所有初始化,寻找“空闲槽”,没有迭代器等。这似乎有点疯狂重新发明所有这些轮子。boost::ptr_vector
看起来很有希望,但是它的行为有点奇怪,因为在 Linux 上构建时它需要 ExampleBase 是非纯虚拟的 - 我不明白为什么......所以boost::ptr_vector
已经过时了。
这似乎是一个简单的情况,而且可能确实很常见。那么最好的方法是什么?我对任何其他标准或增强方式持开放态度:以“最好”为准。
I am working in cross platform C++, and have some classes defined like so: (heavily simplified for this example)
class ExampleBase
{
public:
ExampleBase( int blah ) : blah_test(blah) { }
virtual void DoSomething( ) = 0;
private:
int blah_test;
};
class ExampleImplementer : public ExampleBase
{
public:
ExampleImplementer( ) : ExampleBase( 5 ) { }
virtual void DoSomething( ) { /* unique implementation here */ }
};
Originally I had only a single class, which I stored a bunch of instances of in a std::vector and passed around by const reference. But now I need to have a base class (that I want to keep pure virtual) and a number of polymorphic implementing classes.
What is the best way to have a collection of any implementing instances, and still have leak free easy memory management like having a stack allocated std::vector?
Obviously I can't have a std::vector< ExampleBase > now, since std::vector requires the class to be non-pure virtual (since it does internal allocation/copying etc.). I don't want users of my code to accidentally create instances of ExampleBase because that is wrong. I also want to steer clear from any possibilities of object slicing or any other nasties.
An array of
std::auto_ptr
would do the job, but then I have to deal with initializing them all, looking for a "free slot", no iterators etc. It seems a bit crazy to do all of this wheel re-inventing.boost::ptr_vector
looked promising, however it behaves a little weirdly in that when building on Linux it needs ExampleBase to be non-pure virtual - and I don't understand why... Soboost::ptr_vector
is out.
This seems to be a simple, and probably really common situation. So what is the best way to do this? I am open to any other std or boost way of doing this: whichever is "best".
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您可以使用 Boost,那么
boost::ptr_vector
就是您的最佳选择。它应该适用于您的场景 - 如果不适用,则说明有其他问题,因此请发布错误消息。或者,您可以选择
std::vector< boost::shared_ptr; >
。这不太理想,因为引用计数会增加一些开销,特别是在调整向量大小时,但除此之外是一个可行的解决方案。如果您的实现支持 TR1(最新版本的 g++ 和 MSVC),那么您可以使用
std::tr1::shared_ptr
代替。这实际上可能是优越的,因为 STL 实现可以根据一些内部知识自由优化 - 例如,在 MSVC 中,std::vector
知道它可以使用swap
代替std::tr1::shared_ptr
的复制构造函数,并且这样做,避免了不断的引用计数变化。boost::ptr_vector
is the way to go if you can have Boost. It should work for your scenario - if it does not, then something else is wrong, so please post the error message.Alternatively, you can go for
std::vector< boost::shared_ptr<ExampleBase> >
. This is less ideal, because that refcounting will add some overhead, especially when vector is resized, but otherwise a working solution.If your implementation supports TR1 (latest versions of g++ and MSVC), then you can use
std::tr1::shared_ptr
instead. This can actually be superior, because STL implementation is free to optimize based on some inner knowledge - for example, in MSVC,std::vector
knows that it can useswap
instead of copy constructor forstd::tr1::shared_ptr
, and does just that, avoiding constant refcount changes.有几个选择。
There are a couple of options.
boost::shared_ptr
boost::shared_ptr
如果您可以使用 boost,请尝试指针容器
http:// /www.boost.org/doc/libs/1_40_0/libs/ptr_container/doc/ptr_container.html
If you can use boost, try pointer containers
http://www.boost.org/doc/libs/1_40_0/libs/ptr_container/doc/ptr_container.html