2010-05-29 16 views
14

¿Cómo crear en C++ una clase abstracta con algunos métodos abstractos que deseo sobrescribir en una subclase? ¿Cómo debería verse el archivo .h? ¿Hay un .cpp? En caso afirmativo, ¿cómo debería ser?C++: Crear clase abstracta con método abstracto y anular el método en una subclase

En Java se vería así:

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

La traducción de este código en C++ es suficiente para mí.

Editar:

creé el código, pero cuando trato de iterar sobre los objetos consigo error siguiente:

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 este código:

vector<GameObject> gameObjects; 

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

Su código "en mi bucle de juego" es ... incompleto, en el mejor de los casos. ¿Qué es 'objetos'? Si todavía no tiene uno, le recomiendo que obtenga uno de los libros para principiantes de [The Definitive C++ Book Guide and List] (http://stackoverflow.com/questions/388242/the-definitive-c-book-guide -y-lista). –

+0

También puede consultar el artículo de Herb Sutter, [Virtuality] (http://www.gotw.ca/publications/mill18.htm), que analiza muchas mejores prácticas al usar funciones virtuales y herencia en C++. –

Respuesta

20

En Java, todos los métodos son virtual de forma predeterminada, a menos que los declare final. En C++ es al revés: necesita declarar explícitamente sus métodos virtual. Y para hacerlos puros virtuales, necesitas "inicializarlos" a 0 :-) Si tienes un método virtual puro en tu clase, se convierte automáticamente en abstracto, no hay una palabra clave explícita para él.

En C++ usted debe (casi) siempre definir el destructor para sus clases base virtual, para evitar fugas de recursos difíciles. Por lo que añade que, para el siguiente ejemplo:

// 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

¿Puedes echar un vistazo a mi edición? –

+2

@Martijn, no puede tener un 'vector ' ya que eso almacenaría sus elementos por valor, pero 'GameObject', al ser abstracto, no puede tener instancias. Necesita un 'vector ' o preferiblemente un 'vector >' para almacenar objetos polimórficos. Ver también los comentarios para la respuesta de James McNellis. –

+0

¿Por qué necesita declarar métodos en GameObject.h, si ya han declarado? – HasaDev

6

El miembro las funciones deben declararse virtual en la clase base. En Java, las funciones de los miembros son virtuales por defecto; no están en C++.

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

El virtual hace que un miembro funcione en virtual; el = 0 hace que una función miembro sea puramente virtual. Esta clase también es abstracta porque tiene al menos una función de miembro virtual que no tiene una sobreescritura final concreta.

Luego, en su clase derivada (s):

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

Si una función miembro se declaró virtual en una clase base, es automáticamente virtual en cualquier clase derivada (se puede poner virtual en la declaración en el clase derivada si lo desea, pero es opcional).

+0

¿Y puedo simplemente llamar 'update();' para cada elemento en un vector de GameObjects? –

+0

No. Necesitarías un vector de GameObject * o una clase relacionada como shared_ptr o auto_ptr. – Puppy

+0

Sí, pero eso está implícito en el hecho de que 'GameObject' es abstracto. –

4

En C++ utiliza la palabra clave virtual en sus rutinas, y asignar =0; en ellos. De este modo:

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

} 

Tener un método virtual con un 0 asignado en él automagicamente hace que su clase abstracta.

Cuestiones relacionadas