2009-03-25 6 views
0

J'ai un programme utilisant 3 fichiers d'en-tête et 3 fichiers .cpp en plus de main.cpp. J'utilise VC++ 2008.Quel est le problème avec mes dépendances de fichiers?

Voici la configuration. Les trois en-têtes sont gardés aveC#ifndef HEADERNAME_H, etc. De plus, tous les trois en-têtes ont des fichiers .cpp correspondants, qui #incluent leurs en-têtes respectifs.

/* main.cpp */ 
    #include "mainHeader.h" 

/* mainHeader.h */ 
    #include <windows.h> 
    #include <iostream> 
    //Others... 
    #include "Moo.h" 

/* Moo.h */ 
    #include "mainHeader.h" 
    #include "Foo.h" 

    class Moo { 
     private: 
     int varA; 
     Foo myFoo1; 
     Foo myFoo2; 
     Foo myFoo3; 

     Public: 
     void setVarA(int); // defined in Moo.cpp 
     //etc 
    }; 

/* Foo.h */ 
    #include "mainHeader.h" 
    class Foo { ... }; 

Je reçois des erreurs du compilateur pour instancier les trois l'intérieur de Foo de Moo.h:

erreur C2079: 'Moo :: setVarA' utilise la classe non définie 'Foo'

I Foo inclus .h juste là, alors pourquoi est-ce indéfini? C'est le seul fichier qui inclut Foo.h. J'ai même essayé de déclarer Foo en plaçant 'classe Foo'; avant ma déclaration de classe Moo.

J'ai aussi #defines dans mon fichier Foo.h qui causent aussi des erreurs de compilateur quand je les utilise dans Moo.h. (erreur d'identificateur non déclarée C2065).

Il semble que Foo.h ne soit pas inclus car Moo.h ne trouve rien de défini/déclaré dedans. Que se passe-t-il?

Mon code actuel est long, mais là, vous allez (c'est un jeu de plate-forme Mario BTW):

Ce serait .h:

//************************** 
// Animation.h 
//************************** 
// Header to Animation class 

#ifndef ANIMATION_H 
#define ANIMATION_H 

#include "../Headers/MarioGame.h" 

#define MAX_ANIMATIONS 58 

extern char* fileAnimations[MAX_ANIMATIONS]; 
extern char marioAnims[MAX_ANIMATIONS][3000]; 
extern char background [3700000]; 

class Animation 
{ 
private: 
    int imageCount; 

public: 
    DWORD lastAnimTick; 
    int lastAnim; 
    int anims[4][2]; 
    DWORD animsTime[4]; 

    // Constructor 
    Animation(); 

    // Mutators 
    void addImage(int left, int right, DWORD time); 
    void defaultAnimation(); 

    // Accessors 
    int getImage(bool facingLeft); 
    int getImageCount(); 
    int getCurLoc(); 
}; 

#endif // ANIMATION_H 

Ce serait "Moo.h." Notez les nombreux membres d'animation privées, toutes les erreurs causant:

//************************** 
// Mario.h 
//************************** 
// Header to Mario class 

#ifndef MARIO_H 
#define MARIO_H 

#include "../Headers/MarioGame.h" 
#include "../Headers/Animation.h" 

enum { MARIO_TYPE_SMALL, 
     MARIO_TYPE_BIG, 
     MARIO_TYPE_LEAF }; 

class Animation; 

class Mario 
{ 
private: 
    #pragma region Variable Declarations 
     float xPos; 
     float yPos; 

     float xVel; 
     float yVel; 

     float lastXVel; //used for determining when walk/run decceleration is complete 

     float xAccel; 
     float yAccel; 

     float xSize; 
     float ySize; 

     float halfW; 
     float halfH; 

     bool grounded; 
     bool walking; 
     bool running; 
     bool pRunning; 
     bool jumping; 
     bool hunching; 
     bool gliding; 
     bool flying; 
     bool decelerating; 
     int facing; 

     DWORD pRunTimer; 
     int pChargeLevel; 

     DWORD jumpStart; 

     DWORD glideStart; 

     int type; 

     bool updateXMovement; 
     bool updateYMovement; 

     bool screenUpLock; 

     char marioAnims[MAX_ANIMATIONS][3000]; 

     Animation smallStand; 
     Animation smallWalk; 
     Animation smallRun; 
     Animation smallPRun; 
     Animation smallJump; 
     Animation smallSkid; 

     Animation bigStand; 
     Animation bigWalk; 
     Animation bigRun; 
     Animation bigPRun; 
     Animation bigJump; 
     Animation bigSkid; 
     Animation bigHunch; 

     Animation leafStand; 
     Animation leafWalk; 
     Animation leafRun; 
     Animation leafPRun; 
     Animation leafJump; 
     Animation leafSkid; 
     Animation leafHunch; 
     Animation leafTailWhack; 
     Animation leafGlide; 
     Animation leafFly; 
     Animation leafFalling; 

     Animation* lastAnim; 
    #pragma endregion 

public: 
    //Constructor 
    Mario(); 

    //Mutators 
    void setGlideStart(DWORD g); 
    void setHunching(bool h); 
    void setGliding(bool g); 
    void setFlying(bool f); 
    void setType(int t); 
    void setPChargeLevel(int c); 
    void setPRunTimer(DWORD t); 
    void setScreenUpLock(bool s); 
    void setUpdateXMovement(bool m); 
    void setUpdateYMovement(bool m); 
    void setDecelerating(bool d); 
    void setPos(float x, float y); 
    void setVel(float x, float y); 
    void setAccel(float x, float y); 
    void setSize(float x, float y); 
    void setJumping(bool j); 
    void setJumpStart(DWORD s); 
    void setGrounded(bool g); 
    void setWalking(bool w); 
    void setRunning(bool r); 
    void setPRunning(bool r); 
    void setLastXVel(float l); 
    void setFacing(int f); 
    void defaultAnimations(); 

    //Accessors 
    DWORD getGlideStart(); 
    bool getHunching(); 
    bool getGliding(); 
    bool getFlying(); 
    int getType(); 
    int getPChargeLevel(); 
    DWORD getPRunTimer(); 
    bool getScreenUpLock(); 
    bool getUpdateXMovement(); 
    bool getUpdateYMovement(); 
    bool getDecelerating(); 
    float getXPos(); 
    float getYPos(); 
    float getXVel(); 
    float getYVel(); 
    float getXAccel(); 
    float getYAccel(); 
    bool getJumping(); 
    DWORD getJumpStart(); 
    float getXSize(); 
    float getYSize(); 
    float getHalfW(); 
    float getHalfH(); 
    bool getGrounded(); 
    bool getWalking(); 
    bool getRunning(); 
    bool getPRunning(); 
    float getLastXVel(); 
    int getFacing(); 
    int getAnimation(); 
}; 

#endif // MARIO_H 

Ce serait "mainHeader.h":

//************************** 
// MarioGame.h 
//************************** 
// Header to MarioGame functions 
// Contains Includes, Defines, Function Declarations, Namespaces for program 

#ifndef MARIOGAME_H 
#define MARIOGAME_H 

//*===================== 
// Defines 
//*===================== 
#define WINDOWED  0     // predefined flags for initialization 
#define FULLSCREEN  1 

#define WNDCLASSNAME "MarioGame"   // window class name 
#define WNDNAME   "Mario Game"  // string that will appear in the title bar 

#define NUM_OF_KEYS  5 
#define KEY_SPACE  0 
#define KEY_UP   1 
#define KEY_DOWN  2 
#define KEY_RIGHT  3 
#define KEY_LEFT  4 
#define KEY_CONTROL  5 

#define GRIDW   2.0f 
#define GRIDH   2.0f 

#define PATHING_SIZE 33 

//*===================== 
// Includes 
//*===================== 
#include <windows.h> 

#include <gl/gl.h> 
#include <gl/glu.h> 

#include <iostream> 
#include <fstream> 
#include <vector> 
#include <math.h> 
#include <WAVEMIX.H> 

#include "../Console/guicon.h" 
#include "../Headers/Mario.h" 



//*===================== 
// Function Declarations 
//*===================== 
LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); 
HWND createWindow(HINSTANCE &hinst, int width, int height, int depth); 

void renderFrame(); 
void think(); 
void loadTextures(); 
void WMInit(HINSTANCE, HWND); 

void resize (int width, int height); 
void shutdown(); 

void keyLeft(bool); 
void keyRight(bool); 
void keySpace(bool); 
void keyDownArrow(bool); 

bool checkBoundary(float, float); 
void onPlayerDeath(); 

class Mario; 

//*===================== 
// Namespaces 
//*===================== 

using namespace std; 

//*===================== 
// Global Variable Declarations 
//*===================== 
extern Mario Player; 

extern HDC hdc; 
extern HGLRC hglrc; 
extern HWND hwnd; 

extern int SCRW; 
extern int SCRH; 
extern int SCRD; 

extern DWORD oldTick; 
extern DWORD oldTick2; 
extern DWORD oldPTime; 

extern float pixelZoom; 

extern float screenPosX; 
extern float screenPosY;   

extern float playerScrollMultiplier;  

extern float playerTerminalWalkVel; 
extern float playerWalkAccel;  

extern float playerRunAccel;    
extern float playerTerminalRunVel; 

extern float playerDecel; 

extern float playerPVel; 
extern DWORD playerPRunAchieveTime;  

extern float playerJumpUpVel; 
extern float playerJumpTime; 

extern float gravityAccel; 
extern float playerTerminalFallVel; 

extern float playerTerminalGlideFallVel; 


extern bool keyDown[NUM_OF_KEYS]; 
extern bool lastSpace;   

extern bool drawPathingMap;    

extern float pathing [PATHING_SIZE][5][2];  

#endif   // MARIOGAME_H 

Voici main.cpp:

//************************** 
// main.cpp 
//************************** 
// Primary implementation file; handles Win32 interface 


#include "../Headers/MarioGame.h" 
//*===================== 
// WinMain 
//*===================== 
int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int nshowcmd) 
{ 
    ... 
} 

//And other functions.... 
+0

S'il vous plaît plus du code réel, plutôt que pseudo-code qui se rapproche de ce que vous pensez que l'original (défectueux) fait. Toutes les erreurs subtiles que le code réel contient ne seront pas propagées. –

+0

@Adam: En fait, un test de fonctionnement est meilleur. Je ne vais pas lire tout son code. –

Répondre

2

Vous avez besoin d'un avant déclaration pour la classe Foo. Pour plus d'informations, reportez-vous à l'article 31 de "Effective C++, Third Edition". Note: si vous renvoyez declare Foo cela signifie que votre classe Moo ne pourra avoir que des pointeurs de type Foo.

Si quelque chose comprend .h c'est ce qui se passe (les flèches indiquent la dépendance):

.h --includes -> mainHeader.h --includes -> Moo.h --includes- -> .h

Notez que lorsque la classe Moo est spécifié la deuxième .h ne sont pas inclus en raison de vos gardes, aussi la classe Foo n'a pas été déclarée encore parce que cela arrive après y compris mainheader.h

+0

D'abord, est-il possible de faire cela sans déclaration directe et sans pointeurs, mais des classes réelles? Deuxièmement, qu'en est-il d'un #define dans Foo.h qui n'est pas trouvé par Moo.h ??? –

+0

Si vous êtes en mesure de vous assurer que Foo.h est TOUJOURS inclus avant Moo.h, vous ne devriez pas avoir de problème. Votre exemple montre seulement Moo.h, y compris Foo.h, mais je ne pense pas que ce soit le cas. Comme d'autres l'ont suggéré, vous devriez poster un exemple plus complet qui échoue. – Trent

+0

Merci beaucoup, vous avez vu le problème, mais il a fallu le fichier de vidage du préprocesseur (merci Dan Olsen) pour moi de le voir. –

2

le Le meilleur outil pour déboguer ce genre de situations est l'option "Vider le fichier de sortie pré-traité vers un fichier" du compilateur. Si vous l'activez, vous verrez très probablement le problème immédiatement. Vérifiez les options du compilateur pour savoir comment l'activer.

+0

Bon conseil, cela m'a aidé à voir le problème. –

0

Un autre problème à surveiller est l'utilisation des instructions 'using namespace' - vous ne devriez pas les utiliser du tout dans les fichiers d'en-tête. Ceci permet d'éviter les ambiguïtés pour les modules qui contiennent beaucoup de fichiers d'en-têtes différents.Donc, oui, sans cela, vous devrez faire beaucoup de std :: vector, std :: list etc, ce qui peut être pénible.

Questions connexes