2010-05-29 26 views
14

Come creare in C++ una classe astratta con alcuni metodi astratti che voglio sovrascrivere in una sottoclasse? Come dovrebbe apparire il file .h? C'è un .cpp, se sì, come dovrebbe essere?C++: creare una classe astratta con metodo astratto e sovrascrivere il metodo in una sottoclasse

In Java sarebbe simile a questa:

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

Traducendo questo codice in C++ è abbastanza per me.

Edit:

ho creato il codice, ma quando provo a iterare gli oggetti ottengo l'errore seguente:

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 

Con questo codice:

vector<GameObject> gameObjects; 

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

Il codice "nel mio ciclo di gioco" è ... incompleto, nella migliore delle ipotesi. Cosa sono gli 'oggetti'? Se non ne possiedi già uno, ti consiglio vivamente di ottenere uno dei libri per principianti da [La guida e l'elenco libri definitivi di C++] (http://stackoverflow.com/questions/388242/the-definitive-c-book-guide -e-list). –

+0

Si potrebbe anche consultare l'articolo di Herb Sutter, [Virtuality] (http://www.gotw.ca/publications/mill18.htm), che discute molte best practice quando si utilizzano funzioni virtuali ed ereditarietà in C++. –

risposta

20

In Java, tutti i metodi sono virtual per impostazione predefinita, a meno che non vengano dichiarati final. In C++ è il contrario: devi dichiarare esplicitamente i tuoi metodi virtual. E per renderli virtuali, devi "inizializzarli" a 0 :-) Se hai un metodo virtuale puro nella tua classe, diventa automaticamente astratto - non esiste una parola chiave esplicita per questo.

In C++ è necessario (quasi) definire sempre il distruttore per le classi di base virtual, per evitare perdite di risorse ingannevoli. Così ho aggiunto che l'esempio qui sotto:

// 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) 
{ 
    // ... 
} 
+0

Potete verificare la mia modifica? –

+2

@Martijn, non puoi avere un 'vector ' dato che questo memorizzerebbe i suoi elementi in base al valore, ma 'GameObject', essendo astratto, non può avere istanze. È necessario un 'vector ' o preferibilmente un 'vector >' per memorizzare oggetti polimorfici. Vedi anche i commenti per la risposta di James McNellis. –

+0

Perché è necessario dichiarare metodi in GameObject.h, se già dichiarati? – HasaDev

6

Il socio le funzioni devono essere dichiarate virtual nella classe base. In Java, le funzioni membro sono virtuali per impostazione predefinita; non sono in C++.

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

Il virtual effettua una funzione membro virtuale; il = 0 rende una funzione membro pura virtuale. Questa classe è astratta anche perché ha almeno una funzione membro virtuale che non ha un overrider concreto.

Poi nella classe derivata (i) internet:

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

Se una funzione membro viene dichiarata virtuale in una classe di base, è automaticamente virtuale in qualsiasi classe derivata (si può mettere virtual nella dichiarazione del classe derivata se desideri, ma è facoltativa).

+0

E posso semplicemente chiamare 'update();' per ogni elemento in un vettore di GameObjects? –

+0

No. Avresti bisogno di un vettore di GameObject * o di una classe correlata come shared_ptr o auto_ptr. – Puppy

+0

Sì, ma questo è implicito dal fatto che 'GameObject' è astratto. –

4

In C++ si utilizza la parola chiave virtuale su vostra routine, e di assegnare =0; in loro. In questo modo:

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

} 

Avere un metodo virtuale con un 0 assegnato in esso rende automagically vostra classe astratta.

Problemi correlati