Matrefeytontias
Matrefeytontias

Reputation: 652

Force call to "highest" overloaded function instead of base function

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

Answers (2)

Amit
Amit

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

James Adkison
James Adkison

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

Related Questions