2011-07-09 5 views
4

Les classes dans mon application fonctionnent comme ceci: Creature a peu de champs avec Action s. Lorsque ces Action doivent être exécutés Creature appels someActionField->do(this). Action a la méthode viod do(Creature* cr) et toutes les informations sur ce qu'il faut faire avec ce Creature.Les classes C++ se réfèrent les unes aux autres (=> erreur + champ '...' a un type incomplet)

Donc, la créature doit avoir un champ Action et sachez que Action a la méthode do. L'action doit savoir que Creature a des domaines comme: Est-ce, HP, etc ...

J'ai

creature.h

#include "effect.h" 
#include "heedupdate.h" 

namespace Core 
{ 

class Action; 

class Creature : public NeedUpDate 
{ 
public: 
    virtual ~Creature(); 
    int HP; 
    Action onHit; 
    Action onDie; 
// ... 


}; 

} 
#endif 

Et action.h

#include "creature.h" 

namespace Core 
{ 


class Action 
{ 
public: 
Action(); 
virtual void _do(Creature* cr); 
virtual ~Action(); 
}; 

Mais dans ce cas, l'erreur `onDie' has incomplete type apparaît. Si j'inclus action.h dans creature.h - j'utilise les fichiers 'avant les uns des autres'.

Répondre

8

La classe Creature a des membres de type Action. Le compilateur doit connaître la définition complète de la classe Action pour la compiler. Un type incomplet produit avec une déclaration forward n'est pas suffisant.

La classe Action ne nécessite qu'un pointeur à un objet Creature dans cet en-tête. Dans ce cas, le compilateur doit seulement savoir que Creature sera défini à un moment donné.

Dans votre cas spécifique, vous pouvez vous contenter d'inverser l'ordre dans lequel vous déclarez vos classes.

(à savoir l'avant-déclarer Creature dans action.h, et inclure dans action.hcreature.h)

+0

pleinement déclarée Oui, je pris que juste une seconde avant posté que. :) Merci quand même. –

+0

La partie sur les références est * incorrecte *. Les références et pointeur ont besoin des mêmes connaissances. De plus, il n'y a pas de référence impliquée dans le code OP, seulement des objets complets. – Xeo

+0

@Xeo: c'était très mal formulé en effet. – Mat

3

à action.h mis class Creature; et dans l'autre #include "action.h"

Pour pointeurs vous n'avez pas besoin définition complète car il est juste un pointeur et le compilateur peut générer « code » pour elle. Si vous utilisez une classe/struct simple, le compilateur doit avoir une connaissance du type car il a besoin de savoir de quelle taille il s'agit.

2

Vous n'avez pas besoin de #include "creature.h" dans action.h. Tout ce dont vous avez besoin est une déclaration avant de la créature de classe. Vous devez #include "action.h" dans creature.h car onHit et onDie sont des instances d'Action.

3

Lorsque vous avant déclariez un type, tout le compilateur sait que ce type existe; il ne sait rien de sa taille, des membres ou des méthodes, d'où il est appelé un type incomplet

Vous ne pouvez pas utiliser un type incomplet de déclarer un membre (parce que la compilation a besoin de connaître la taille du type tout en déclarant il) et donc vous obtenez l'erreur.

Vous n'avez pas besoin de #include "creature.h" en action.h mais vous avez juste besoin de transmettre la classe Creature. Vous avez besoin de #include "action.h" dans creature.h

Vos fichiers d'en-tête doivent avoir la construction suivante:

creature.h

#include "effect.h" 
#include "action.h" 
#include "heedupdate.h" 

action.h

class creature; 

Ceci utilise deux règles:

  • On peut déclarer des fonctions ou des méthodes qui accepte/types de retour incomplets:

action.h déclare seulement une fonction qui accepte un type incomplet (Créature)

  • On ne peut déclarer un membre à un type incomplet.

creature.h doit inclure action.h parce qu'il déclare un membre de type Action.

0

Utiliser des références, ou:

 #include "effect.h" 
    #include "heedupdate.h" 

    namespace Core 
    { 

    class Action; 

    class Creature : public NeedUpDate 
    { 
    public: 
     virtual ~Creature(); 
     int HP; 
     Action & onHit; 
     Action & onDie; 
    // ... 


    }; 

    } 

#endif 

De cette façon, vous pouvez briser les dépendances et pas besoin d'une Action classe

Questions connexes