Что не так с моими файловыми зависимостями? - PullRequest
0 голосов
/ 26 марта 2009

У меня есть программа, использующая 3 файла заголовка и 3 файла .cpp в дополнение к main.cpp. Я использую VC ++ 2008.

Вот настройки. Все три заголовка защищены с помощью #ifndef HEADERNAME_H и т. Д. Также все три заголовка имеют соответствующие файлы .cpp, которые #include их соответствующие заголовки.

/* 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 { ... };

Я получаю ошибки компилятора для создания экземпляров трех Foo внутри Moo.h:

ошибка C2079: 'Moo :: setVarA' использует неопределенный класс 'Foo'

Я тут же включил Foo.h, так почему он не определен? Это единственный файл, который включает в себя Foo.h. Я даже пытался объявить Foo, поместив 'class Foo;' до моего объявления класса Moo.

У меня также есть #defines в моем файле Foo.h, которые также вызывают ошибки компилятора, когда я использую их в Moo.h. (необъявленная ошибка идентификатора C2065).

Кажется, что Foo.h не включается, потому что Moo.h не может найти ничего определенного / объявленного в нем. Что происходит?

Мой настоящий код длинный, но вот, пожалуйста (это игра для марио платформера):

Это будет Foo.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

Это будет "Moo.h." Обратите внимание на множество закрытых членов анимации, все они вызывают ошибки:

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

Это будет "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

Вот 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....

Ответы [ 3 ]

2 голосов
/ 26 марта 2009

Лучшим инструментом для отладки подобных ситуаций является опция компиляции «Предварительно обработанный вывод в файл». Если вы включите это, вы, скорее всего, сразу увидите проблему. Проверьте параметры компилятора, чтобы узнать, как его включить.

2 голосов
/ 26 марта 2009

Вам нужно предварительное объявление для класса Foo. Для получения дополнительной информации см. Пункт 31 «Эффективное C ++, третье издание». Примечание: если вы перешли к объявлению Foo, это означает, что ваш класс Moo сможет иметь только указатели типа Foo.

Если что-то включает Foo.h, это то, что происходит (стрелки показывают зависимость):

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

Обратите внимание, что когда указан класс Moo, второй Foo.h не включен из-за вашей охраны, также класс Foo еще не был объявлен, потому что это происходит после включения mainheader.h

0 голосов
/ 07 июня 2009

Еще одна проблема, на которую следует обратить внимание, это использование операторов 'using namespace' - вы вообще не должны использовать их в заголовочных файлах.

Это позволяет избежать двусмысленности для модулей, которые содержат много разных заголовочных файлов.

Так что, да, без этого вам потребуется много std :: vector, std :: list и т. Д., Что может быть проблемой.

...