views:

320

answers:

3

Hi,

How to create in C++ an abstract class with some abstract methods that I want to override in a subclass? How should the .h file look? Is there a .cpp, if so how should it look?

In Java it would look like this:

abstract class GameObject
{
    public abstract void update();
    public abstract void paint(Graphics g);
}

class Player extends GameObject
{
    @Override
    public void update()
    {
         // ...
    }

    @Override
    public void paint(Graphics g)
    {
         // ...
    }

}

// In my game loop:
List<GameObject> objects = new ArrayList<GameObject>();
for (int i = 0; i < objects.size(); i++)
{
    objects.get(i).update();
}
for (int i = 0; i < objects.size(); i++)
{
    objects.get(i).paint(g);
}

Translating this code to C++ is enough for me.

Edit:

I created the code but when I try to iterate over the objects I get following error:

Game.cpp:17: error: cannot allocate an object of abstract type ‘GameObject’
GameObject.h:13: note:   because the following virtual functions are pure within ‘GameObject’:
GameObject.h:18: note:         virtual void GameObject::Update()
GameObject.h:19: note:         virtual void GameObject::Render(SDL_Surface*)
Game.cpp:17: error: cannot allocate an object of abstract type ‘GameObject’
GameObject.h:13: note:   since type ‘GameObject’ has pure virtual functions
Game.cpp:17: error: cannot declare variable ‘go’ to be of abstract type ‘GameObject’
GameObject.h:13: note:   since type ‘GameObject’ has pure virtual functions

With this code:

vector<GameObject> gameObjects;

for (int i = 0; i < gameObjects.size(); i++) {
    GameObject go = (GameObject) gameObjects.at(i);
    go.Update();
}
+4  A: 

The member functions need to be declared virtual in the base class. In Java, member functions are virtual by default; they are not in C++.

class GameObject
{
public:
    virtual void update() = 0;
    virtual void paint(Graphics g) = 0;
}

The virtual makes a member function virtual; the = 0 makes a member function pure virtual. This class is also abstract because it has at least one virtual member function that has no concrete final overrider.

Then in your derived class(es):

class Player : public GameObject
{
public:
    void update() { }          // overrides void GameObject::update()
    void paint(Graphics g) { } // overrides void GameObject::paint(Graphics)
}

If a member function is declared virtual in a base class, it is automatically virtual in any derived class (you can put virtual in the declaration in the derived class if you'd like, but it's optional).

James McNellis
And can I just call `update();` for each element in a vector of GameObjects?
Martijn Courteaux
No. You'd need a vector of GameObject* or a related class like shared_ptr or auto_ptr.
DeadMG
Yes, but that's implied by the fact that `GameObject` is abstract.
James McNellis
+4  A: 

In Java, all methods are virtual by default, unless you declare them final. In C++ it's the other way around: you need to explicitly declare your methods virtual. And to make them pure virtual, you need to "initialize" them to 0 :-) If you have a pure virtual method in your class, it automatically becomes abstract - there is no explicit keyword for it.

In C++ you should (almost) always define the destructor for your base classes virtual, to avoid tricky resource leaks. So I added that to the example below:

// GameObject.h

class GameObject
{
public:
    virtual void update() = 0;
    virtual void paint(Graphics g) = 0;
    virtual ~GameObject() {}
}

// Player.h
#include "GameObject.h"

class Player: public GameObject
{
public:
    void update();

    void paint(Graphics g);
}

// Player.cpp
#include "Player.h"

void Player::update()
{
     // ...
}

void Player::paint(Graphics g)
{
     // ...
}
Péter Török
@Péter Török: Can you please check out my edit?
Martijn Courteaux
@Martijn, you can't have a `vector<GameObject>` since that would store its elements by value, but `GameObject`, being abstract, can have no instances. You need a `vector<GameObject*>` or preferably a `vector<shared_ptr<GameObject*>>` to store polymorphic objects. See also the comments for James McNellis' answer.
Péter Török
+1  A: 

In C++ you use the keyword virtual on your routines, and assign =0; into them. Like so:

class GameObject {
public:
    virtual void update()=0;
    virtual void paint(Graphics g)=0; 

}

Having a virtual method with a 0 assigned into it automagically makes your class abstract.

T.E.D.