Reputation: 366
Is there some way to allocate memory depending on the type of pointer passed?
Here is my problem: I have a 'bouncyball' and 'hero' class both inheriting from 'Actor'. To add a bouncyball, I call:
_actors.push_back(new Bouncyball());
For a hero, it would be:
_actors.push_back(new Hero());
Since _actors is a vector of Actor pointers, it works because of polymorphism. But I want to write a generic method to add new actors to my scene:
unsigned Scene::addActor(Actor * actor){
this->_actors.push_back(new [something]);
}
Because the parameter can be any derivative of Actor, I don't know what to allocate memory for... I can work around this with a case statement, but what if I derive other Actors later on?
Upvotes: 0
Views: 1150
Reputation: 3322
Why not create a pv class Clonable
:
template <typename T>
struct Clonable {
virtual smart_ptr<T> clone() const = 0;
}
for smart_ptr
being std::shared_ptr
, std::unique_ptr
, boost::shared_ptr
, etc.
The point is to refcount the pointer to avoid use of manual delete
s, except when writing a custom Deleter
.
Then define Actor
as:
class Actor : ..., public Clonable<Actor> {
...
public:
...
virtual smart_ptr<T> clone() const { return 0; }
...
...
}
Then, for T : public Actor
,
scene.addActor((T()).clone());
Upvotes: 0
Reputation: 4450
Nawaz's solution is fine, but an alternative is a template member function:
template<typename T>
unsigned Scene::addActor()
{
_actors.push_back(new T());
}
And then in the client code:
scene.addActor<Hero>();
It's worth noting that the template member function will need to be implemented in a header or file included by a header (such as a .inl). If you implement it directly in the class body you shouldn't write Scene:: in front of addActor().
One advantage of this method is that clients are not calling new. It's generally 'bad' if code is calling new, but isn't calling delete, and in this case delete would presumably be called by the Scene class later. This also creates a pinch point if a custom allocator needs to be used for performance reasons.
Upvotes: 2
Reputation: 361352
What is wrong with this:
unsigned Scene::addActor(Actor * actor){
this->_actors.push_back(actor);
//what do you want to return? why not make return type as void?
}
Isn't it actor
which you want to add to _actors
?
And you can call addActor()
as:
scene.addActor(new Bouncyball());
scene.addActor(new Hero());
Make sure that you declare the destructor of Actor
as virtual
, as most likely you would want to delete derived class objects through the pointer of base type (which is Actor
).
Upvotes: 3