maxpenguin
maxpenguin

Reputation: 5149

C++ Collection of instances implementing a pure virtual class

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?

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".

Upvotes: 1

Views: 972

Answers (4)

sellibitze
sellibitze

Reputation: 28127

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").

Upvotes: 3

Pavel Minaev
Pavel Minaev

Reputation: 101665

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.

Upvotes: 6

Chris Bednarski
Chris Bednarski

Reputation: 3434

If you can use boost, try pointer containers

http://www.boost.org/doc/libs/1_40_0/libs/ptr_container/doc/ptr_container.html

Upvotes: 1

Khaled Alshaya
Khaled Alshaya

Reputation: 96929

boost::shared_ptr

Upvotes: 1

Related Questions