C ++: создать абстрактный класс с помощью абстрактного метода и переопределить метод в подклассе - PullRequest
18 голосов
/ 30 мая 2010

Как создать в C ++ абстрактный класс с некоторыми абстрактными методами, которые я хочу переопределить в подклассе? Как должен выглядеть файл .h? Есть ли .cpp, если да, то как это должно выглядеть?

На Java это будет выглядеть так:

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);
}

Мне достаточно перевода этого кода на C ++.

Edit:

Я создал код, но когда я пытаюсь перебрать объекты, я получаю следующую ошибку:

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

С этим кодом:

vector<GameObject> gameObjects;

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

Ответы [ 3 ]

24 голосов
/ 30 мая 2010

В Java все методы по умолчанию virtual, если вы не объявите их final. В C ++ все наоборот: вам нужно явно объявить ваши методы virtual. И чтобы сделать их чисто виртуальными, вам нужно «инициализировать» их в 0 :-) Если у вас есть чисто виртуальный метод в вашем классе, он автоматически становится абстрактным - явного ключевого слова для него нет.

В C ++ вы должны (почти) всегда определять деструктор для ваших базовых классов virtual, чтобы избежать хитрой утечки ресурсов. Поэтому я добавил это к примеру ниже:

// 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)
{
     // ...
}
7 голосов
/ 30 мая 2010

Функции-члены должны быть объявлены virtual в базовом классе. В Java функции-члены являются виртуальными по умолчанию; их нет в C ++.

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

virtual делает функцию-член виртуальной; = 0 делает функцию-член чисто виртуальной. Этот класс также является абстрактным, потому что он имеет по крайней мере одну виртуальную функцию-член, у которой нет конкретного окончательного переопределения.

Тогда в вашем производном классе (ах):

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

Если функция-член объявлена ​​виртуальной в базовом классе, она автоматически становится виртуальной в любом производном классе (вы можете поместить virtual в объявлении в производном классе, если хотите, но это необязательно).

4 голосов
/ 30 мая 2010

В C ++ вы используете ключевое слово virtual в своих подпрограммах и присваиваете им =0;. Вот так:

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

}

Наличие виртуального метода с назначенным ему 0 автоматически делает ваш класс абстрактным.

...