除了main.cpp之外,我还有一个使用3个头文件和3个.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 { ... };
我在Moo.h中实例化三个Foo时遇到了编译器错误:
错误C2079:'Moo :: setVarA'使用未定义的类'Foo'
我在那里包含了Foo.h,为什么它未定义?这是唯一包含Foo.h的文件。我甚至尝试通过放置'Foo类'来宣布Foo;在我宣布上课之前。
我的Foo.h文件中也有#defines,当我在Moo.h中使用它们时也会导致编译器错误。 (未声明的标识符错误C2065)。
似乎没有包含Foo.h,因为Moo.h找不到任何定义/声明的内容。发生了什么事?
我的实际代码很长,但是你去(这是一个马里奥平台游戏btw):
这将是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....
答案 0 :(得分:2)
你需要Foo课的前瞻声明。有关更多信息,请参阅“Effective C ++,Third Edition”的第31项。注意:如果你转发声明Foo,那意味着你的类Moo只能有Foo类型的指针。
如果某些内容包含Foo.h,则会发生这种情况(箭头显示依赖关系):
Foo.h --includes - &gt; mainHeader.h --includes - &gt; Moo.h - 包含 - &gt; foo.h中
请注意,当指定类Moo时,由于你的警卫而没有包含第二个Foo.h,因为在包含mainheader.h之后发生了类Foo,所以还没有声明类Foo
答案 1 :(得分:2)
调试这些情况的最佳工具是编译器的“转储预处理输出到文件”选项。如果启用此功能,您很可能会立即看到问题。检查编译器选项以了解如何启用它。
答案 2 :(得分:0)
需要注意的另一个问题是使用'using namespace'语句 - 你根本不应该在头文件中使用它们。
这是为了避免包含大量不同头文件的模块的含糊不清。
所以,是的,没有它,你需要做很多std :: vector,std :: list等,这可能很痛苦。