1

Say I have two different objects that are completely different, Sprite and PhysicsData.

I write an empty base class and a container class that can push and remove objects to/from a container.

I create two of these containers to store the two different objects - Sprite and PhysicsData. (Different objects aren't together in the same class)

class base
{
};

class ContainerManager
{
public:
    std::vector<base*> list;
    void Push(base *object);
    void Remove(base *object);
};

class PhysicsData : public base
{
    void applyGravity();
};

class Sprite : public base
{
    void Draw();
};

ContainerManager SpriteContainer;
ContainerManager PhysicsDataContainer;

Sprite aSprite;
SpriteContainer.Push(&aSprite);

PhysicsData SomeData;
PhysicsDataContainer.Push(&SomeData);

Is this the way that this should bet done?

  • Does it give you any errors or what? – dreamzor Oct 16 '12 at 20:59
  • 2
    Don't use just `pre` for code. Format it by putting 4 spaces in front of it. – chris Oct 16 '12 at 21:00
  • I have only just begun with c++ and was curious. –  Oct 16 '12 at 21:01
  • I don't get it. You define a common base so you could (presumably) squash different objects in the same container. But then you make two containers and store them separately. What gives? Why not just have two containers of different types? – jrok Oct 16 '12 at 21:05
  • I recommend looking at [Boost.Variant](http://www.boost.org/libs/variant/) and avoiding polymorphism here altogether. – ildjarn Oct 16 '12 at 21:07
  • @jrok so I can use the ContainerManager class –  Oct 16 '12 at 21:08
  • 1
    A `std::vector` has got the same interface no matter what type it holds, so what does ContainerManager buy you? – jrok Oct 16 '12 at 21:09

4 Answers4

3

This is not a C++ way. You should use templates.

For you to know, STL (which you are calling to when using std:: namespace prefix) is, actually, Standard Template Library :). A lot of template classes are already there, e.g. for the push / remove operations see std::list<T>

You use it like this:

std::list<Sprite> SpriteContainer;
std::list<PhysicsData> PhysicsDataContainer;

and so on.

There is a cool guide about C++ templates, if you still want to do your own class for some more functionality.
And there is a reference to std::list, (i don't think i need to explain the usage of std::vector for you) if the question was the actual thing you've wanted to do.

dreamzor
  • 5,795
  • 4
  • 41
  • 61
  • The class's functions also handle other things such as calling a function in the object being passed to it. –  Oct 16 '12 at 21:11
  • I see, then you still need to use templates. Just follow the link and read the guide carefully. It's not the most trivial thing in C++. – dreamzor Oct 16 '12 at 21:12
  • @andrew This is also possible with templates. Think of a template as something with a placeholder for (in your case) a type T not yet known when typing down the templated class; but you still can call functions on the "unknown" type T (let's say `T::foo()`. Just make sure that those functions *do* exist when you instantiate a concrete class. When saying `ContainerManager` for example, the function called, here `foo()`, has to exist in `Sprite`. – leemes Oct 16 '12 at 21:14
3

You're having Templates in C++ and still worrying about having a common base class for a trivial container??

template <class T>
class Container{
  private:
    vector<T> list;
  public:
    void Push(T data);
    T Pop();
};
Aniket Inge
  • 25,375
  • 5
  • 50
  • 78
  • A pop function in C++ generally shouldn't return the value it removes, because if it does then it's not possible for it to offer the strong exception guarantee in the case where `T`'s copy constructor can throw. That said, as of C++11 any type whose copy constructor can throw probably *ought* to have a nothrow move constructor, so the issue goes away provided you only use recently-written and well-behaved types. – Steve Jessop Oct 16 '12 at 23:57
1

If you put a single virtual function into the base class, you'll be able to use dynamic_cast to get back the proper pointer if you mix different types in the same container. A virtual destructor would be a good idea because then you could delete the object if it were dynamically allocated, without having to cast it back to the original pointer.

If you're not going to mix types within a single container, I agree with dreamzor that a template class would be better. That's the way all the standard containers are implemented.

Community
  • 1
  • 1
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
0

That looks like technically correct code but you are not doing any type checking. So as you can see PhysicsData is showing up in your SpriteContainer. You probably do not want this.

There is more than one way to keep PhysicsData out of your SpriteContainer. One way is to use templates. With templates you would state what type of base objects the container should work with at compile time.

Another method is to inherit from your ContainerManager two types of ContainerManagers, one called PhysicsContainerManager and one called SpriteContainerManager. These two child classes can do type check to verify that the objects being passed are in fact either a SpriteContainer or a PhisicsData. This link shows how to do type check in c++ C++ equivalent of instanceof

thanks jose

Community
  • 1
  • 1
Jose Martinez
  • 11,452
  • 7
  • 53
  • 68
  • The SomeData isn't actually meant to be going in to SpriteContainer. My bad. Thanks for pointing that out! –  Oct 16 '12 at 21:22