Reputation: 652
I have a base class and many other classes (all derivating from the base class) which all implement the same function with the same parameters. My problem is as follows :
class Entity
{
public:
int getx();
int gety();
};
class Enemy : public Entity
{
public:
int getx();
int gety();
};
class Player : public Entity
{
public:
int getx();
int gety();
};
// all of the implementations actually differ
int distance(Entity *e1, Entity *e2)
{
return e2->getx() + e2->gety() - e1->getx() - e2->gety();
// here, it is always Entity::getx and Entity::gety that are called
}
What I want is that if I call, say, distance(e, p)
with e
an Enemy
and p
a Player
, the respective function overloads are called, and not Entity's implementation.
How would I achieve this, if it is actually possible ? I searched quite a bit on here, and the closest question I found was making use of templates in quite a different context, so it didn't really help me : Template function overload for base class
Thanks by advance.
Upvotes: 1
Views: 817
Reputation: 46351
What you're trying to do is actually one of the basic concepts in OOP: Virtual Functions.
The idea is exactly as you described it:
A virtual function is a function that's being replaced by subclasses implementation when accessed via a base class pointer.
The syntax is pretty straight forward, simply add the keyword virtual
to your base class function declaration. It is good practice (although not a requirement) to also mark overriding functions (those of the subclasses) with the override
keyword.
Here's a reference of virtual functions.
You can change your code to:
class Entity
{
public:
virtual int getx();
virtual int gety();
};
class Enemy : public Entity
{
public:
int getx() override;
int gety() override;
};
class Player : public Entity
{
public:
int getx() override;
int gety() override;
};
// all of the implementations actually differ
int distance(Entity *e1, Entity *e2)
{
return e2->getx() + e2->gety() - e1->getx() - e2->gety();
// Now, the proper getx & gety are being called
}
Upvotes: 1
Reputation: 9602
As @Amit states in the comments you're looking for virtual functions. You can update your Entity
class as follows:
class Entity
{
public:
// Add a virtual destructor to allow deletion through base pointer to work correctly
// (e.g., E* e = new Player(); delete e;)
virtual ~Entity();
virtual int getx() const = 0; // 'const' isn't related to your question but
virtual int gety() const = 0; // good to have, '= 0' is optional but helpful if
// the base class isn't providing an implementation
};
Assuming C++11, it's also good to use override
in the derived classes.
class Enemy : public Entity
{
public:
// 'const' only necessary if specified in the base class
// 'virtual' is more documentation it would still be virtual if omitted
// 'override' enforces that the signature matches a virtual function
virtual int getx() const override;
virtual int gety() const override;
};
Upvotes: 0