C++实现纯虚拟类的实例集合

发布于 2024-08-06 01:47:45 字数 1052 浏览 4 评论 0原文

我正在跨平台 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... So boost::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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

稀香 2024-08-13 01:47:45

如果您可以使用 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 use swap instead of copy constructor for std::tr1::shared_ptr, and does just that, avoiding constant refcount changes.

醉态萌生 2024-08-13 01:47:45

有几个选择。

  • 使用 boost::ptr_vector 作为容器。它甚至应该适用于抽象基类。只需确保您的基类包含虚拟析构函数
  • 使用直接管理派生类的不同对象的多个容器,并创建另一个仅使用指针的容器。这可能很麻烦,并且还迫使您考虑指针何时/是否无效。但它还有一个优点,可以将同一类型的对象保持在一起。
  • 使用智能指针(如 boost 的共享所有权指针)并将其存储到容器中。 C++0x 将提供另一个不错的智能指针,它的开销较小,如果您不想共享所有权,则适用:unique_ptr。不幸的是,C++03 中没有对此进行良好的模拟。
  • 使用某种其他形式的“句柄”,这是一个通过具有值语义的指针包装和管理多态对象的对象(这将是另一个可以命名为“clone_ptr”的智能指针)。

There are a couple of options.

  • Use boost::ptr_vector as your container. It should work even with abstract base classe. Just make sure that your base class includes a virtual destructor.
  • Use multiple containers that directly manage different objects of derived classes and create another one that only uses pointers. This might be cumbersome and also forces you to think about when/if pointers are invalidated. But it also has the advantage of keeping objects of the same type close together.
  • Use a smart pointer (like boost's shared ownership pointer) and store it into your container. C++0x will offer another nice smart pointer with less overhead that's applicable if you don't want to share ownership: unique_ptr. Unfortunately, there's no good emulation of this in C++03.
  • Use some other form of "handle", an object that wraps and manages a polymorphic object through a pointer with value semantics (This would be another smart pointer you could name "clone_ptr").
清醇 2024-08-13 01:47:45

boost::shared_ptr

boost::shared_ptr

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文