2009-09-26 153 views
1

我在跨平台的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 ::矢量< ExampleBase>现在,由于标准::矢量需要类是非纯虚(因为它内部分配/复制等)。我不希望我的代码的用户意外地创建ExampleBase的实例,因为这是错误的。我也想避开物体切割或任何其他黑洞的任何可能性。

  • std::auto_ptr将会完成这项工作,但之后我必须处理初始化它们,寻找一个“空闲槽”,没有迭代器等等。看起来有点疯狂,发明了。

  • boost::ptr_vector看起来前途无量,但它在Linux上构建时的行为有点古怪,因为它需要ExampleBase是非纯虚 - 我不明白为什么...所以boost::ptr_vector出来了。

这似乎是一个简单的,可能真的很常见的情况。那么做到这一点的最好方法是什么?我愿意接受任何其他标准或推动方式:以“最佳”为准。

+1

请提供您为'ptr_vector'获得的错误消息。它绝对不应该要求基类是非抽象的 - 别的是不对的。 – 2009-09-26 06:02:01

+0

谢谢,很好的答案!经由类型ABC *(抽象基类)的一个指针 – maxpenguin 2009-09-26 06:05:06

+1

删除对象简单地,如果ABC不包括虚拟析构函数不起作用。你得到的编译错误实际上是保护你免受未定义的行为。 – sellibitze 2009-09-26 07:03:26

回答

6

boost::ptr_vector是要走的路,如果你可以有提升。它应该适用于你的场景 - 如果没有,那么其他的东西是错误的,所以请发布错误信息。您可以选择std::vector< boost::shared_ptr<ExampleBase> >。这是不太理想的,因为这种refcounting会增加一些开销,特别是当矢量调整大小时,但另外一个工作解决方案。

如果实现支持TR1(的G ++最新版本和MSVC),那么你可以使用std::tr1::shared_ptr代替。这其实是优越的,因为STL实现可以自由根据一些内部知识来优化 - 例如,在MSVC,std::vector知道,它可以使用swap而不是拷贝构造函数为std::tr1::shared_ptr,并且做到了这一点,避免不断引用次数的变化。

1

boost::shared_ptr

3

有几个选项。

  • 使用boost :: ptr_vector作为你的容器。即使抽象基础类也应该工作。只要确保您的基类包含虚拟析构函数
  • 使用多个容器直接管理派生类的不同对象,并创建另一个只使用指针的容器。这可能会很麻烦,并且还会强制您考虑何时/如果指针失效。但它也具有将相同类型的物体保持在一起的优点。
  • 使用智能指针(如boost的共享所有者指针)并将其存储到您的容器中。如果你不想共享所有权:unique_ptr,C++ 0x将提供另一个很好的智能指针,其开销较少。不幸的是,在C++ 03中没有很好的模拟。
  • 使用其他形式的“句柄”,一个通过带有值语义的指针来包装和管理多态对象的对象(这可能是另一个可以命名为“clone_ptr”的智能指针)。
+0

也很好的答案 - 希望我可以标记为接受多个答案! – maxpenguin 2009-09-26 06:05:55