utilisation invalide de type incomplète / déclaration anticipée
J'ai essayé de regarder les problèmes similaires énumérés ici sur Stackoverflow et sur Google, mais ils ont la plupart du temps avec des modèles et ce n'est pas mon cas. Je suis en utilisant GCC 4.4.5 sur Debian Testing 64 bits.
Donc, j'ai deux classes - CEntity:
#ifndef CENTITY_H_INCLUDED
#define CENTITY_H_INCLUDED
#include "global_includes.h"
//game
#include "CAnimation.h"
#include "Vars.h"
#include "vector2f.h"
#include "Utils.h"
class CAnimation;
class CEntity
{
public:
CEntity();
virtual ~CEntity();
void _update(Uint32 dt);
void updateAnimation(Uint32 dt);
void addAnimation(const std::string& name, CAnimation* anim);
void addAnimation(const std::string& name, const CAnimation& anim);
void removeAnimation(const std::string& name);
void clearAnimations();
bool setAnimation(const std::string& name);
SDL_Surface* getImage() const;
const vector2f& getPos() const;
const vector2f& getLastPos() const;
F getX() const;
F getY() const;
F getLastX() const;
F getLastY() const;
SDL_Rect* getHitbox() const;
SDL_Rect* getRect() const;
F getXSpeed() const;
F getYSpeed() const;
void setPos(const vector2f& pos);
void setPos(F x, F y);
void setPos(F n);
void setX(F x);
void setY(F y);
void setHitboxSize(int w, int h);
void setHitboxSize(SDL_Rect* rect);
void setHitboxWidth(int w);
void setHitboxHeight(int h);
void setSpeed(F xSpeed, F ySpeed);
void setXSpeed(F xSpeed);
void setYSpeed(F ySpeed);
void stop();
void stopX();
void stopY();
void affectByGravity(bool affect);
void translate(const vector2f& offset);
void translate(F x, F y);
bool collide(CEntity& s);
bool collide(CEntity* s);
protected:
CAnimation* mCurrentAnimation;
SDL_Surface* mImage;
vector2f mPos;
vector2f mLastPos;
SDL_Rect* mHitbox; //used for collisions
SDL_Rect* mRect; //used only for blitting
F mXSpeed;
F mYSpeed;
bool mAffByGrav;
int mHOffset;
int mVOffset;
private:
std::map<std::string, CAnimation*> mAnims;
};
#endif //CENTITY_H_INCLUDED
et CPlayerChar qui hérite de CEntity:
#ifndef CPLAYERCHAR_H_INCLUDED
#define CPLAYERCHAR_H_INCLUDED
#include "global_includes.h"
//game
#include "CEntity.h"
class CEntity;
class CPlayerChar : public CEntity
{
public:
CPlayerChar();
virtual ~CPlayerChar();
virtual void update(Uint32 dt) = 0;
virtual void runLeft() = 0;
virtual void runRight() = 0;
virtual void stopRunLeft() = 0;
virtual void stopRunRight() = 0;
virtual void attack() = 0;
virtual void stopAttack() = 0;
virtual void attack2() = 0;
virtual void stopAttack2() = 0;
virtual void ground() = 0;
virtual void midair() = 0;
void jump();
void stopJump();
protected:
//looking right?
bool mRight;
bool mJumping;
bool mOnGround;
bool mGrounded;
};
#endif //CPLAYERCHAR_H_INCLUDED
Quand j'essaie de le compiler, le compilateur GCC génère cette erreur:
CPlayerChar.h:12: error: invalid use of incomplete type ‘struct CEntity’
CPlayerChar.h:9: error: forward declaration of ‘struct CEntity’
Je l'ai essayé, d'abord sans l'en avant de la déclaration de la classe CEntity;' CPlayerChar.h sur la ligne 9, mais alors il faudrait jeter cela à la place
CPlayerChar.h:12: error: expected class-name before ‘{’ token
De sorte que la déclaration anticipée doit être là. Aussi, CEntity est clairement une classe, pas un struct.
Dans des classes C++ et les structures sont presque identiques; de ne pas vous attardez sur le message d'erreur.
Je suppose que la définition de classe pour
Vous avez quelques inclusion circulaire dans vos fichiers d'en-tête. Un fichier d'en-tête ne doit inclure d'autres fichiers d'en-tête si elle est explicitement des besoins. Si vous pouvez utiliser une déclaration anticipée alors ce qui doit être privilégiée.
Je suppose que la définition de classe pour
CEntity
est dans le fichier CEntity.h
? Si pas, c'est votre problème.Vous avez quelques inclusion circulaire dans vos fichiers d'en-tête. Un fichier d'en-tête ne doit inclure d'autres fichiers d'en-tête si elle est explicitement des besoins. Si vous pouvez utiliser une déclaration anticipée alors ce qui doit être privilégiée.
OriginalL'auteur rivon | 2011-08-08
Vous devez vous connecter pour publier un commentaire.
Vous avez une inclusion circulaire dans vos fichiers d'en-tête.
Mais sans tous les fichiers d'en-tête, nous ne serons pas en mesure de le réparer.
Je voudrais commencer ici.
Regarder votre en-tête, vous n'avez pas réellement besoin de cela. Vous utilisez uniquement CAnimation par référence ou pointeur de sorte que la déclaration anticipée vous avez devrait être suffisant. Déplacer l'inclure dans le fichier source (c'est à dire de l'en-tête).
Le prochain lieu je regarde est:
À l'échelle mondiale comprend qui sont inclus dans un fichier d'en-tête est mieux d'être très simple. Ne doit contenir que des types simples et de ne pas inclure toutes les autres fichiers d'en-tête (sauf s'ils sont tout aussi simple). Tout ce complexe va entraîner des problèmes de dépendances circulaires.
Règle générale
Un fichier d'en-tête ne doit inclure que les fichiers d'en-tête qu'il a absolument besoin. Sinon, ils doivent être inclus dans le fichier source. Vous ne absolument besoin d'un fichier d'en-tête si on définit une classe qui est utilisé comme une classe parente, vous avez des membres des objets de cette classe, ou vous utilisez le paramètre des objets de cette classe.
J'utilise le terme
object
à distinguer des références ou des pointeurs. Si vous utilisez ces vous n'avez pas besoin d'inclure le fichier d'en-tête. Vous avez seulement besoin de faire une déclaration anticipée.Qui aide, mais ne suffit pas. Vous devez également déclarer avant types. Aussi seulement, y compris les en-têtes que vous avez spécifiquement besoin et en avant de déclarer d'autres types.
OriginalL'auteur Martin York
Vous avez probablement obtenu une boucle dans votre comprend de manière à ce que CPlayerChar ne sait pas qui est vraiment CEntity, il sait juste qu'il existe, mais ne sait pas ce qu'il est.
Si vous supprimez la "classe CEntity" déclaration, vous verrez que GCC va se plaindre que CEntity n'existe pas.
Vous devez vérifier que rien de ce qui CEntity comprend inclure CPlayerChar.
OriginalL'auteur André Puel
Vous devez vous assurer que l'intégralité de la définition de la classe
CEntity
est visible à l'endroit où vous définissez la classeCPlayerChar
. (Afin de vérifier votre inclusions.)C'est parce que vous ne pouvez hériter de entièrement défini par les classes, mais pas juste à l'avant-déclaré.
Le seul moment où vous pouvez obtenir loin avec l'avant-déclarations en place de définitions complètes, c'est quand vous faites des pointeurs ou des références à un type, mais seulement si vous n'accédez jamais à l'un de ses membres, ou (merci à @Alf) lors de la déclaration d'une fonction incomplète de type de retour.
T
est un type incomplète, puis la déclaration d'une fonctionT foo()
est parfaitement droit. Pour l'appeler, vous devez avoirT
terminé (saufT
est le type spécialvoid
, qui officiellement est un type incomplète qui ne peut jamais être terminé), mais c'est une autre question. 🙂Merci! C'est utile. Qu'en fonction des paramètres a, de ces être incomplètes?
oui ............
OriginalL'auteur Kerrek SB