我是一名新手程序员,仍在努力学习C ++和OOP设计基础知识。我一直在努力教自己的项目是一个C ++游戏,它有多个类,文件,状态等。但是,我一直遇到文件组织的障碍,范围从简单地在哪里创建对象到编译 - 破坏链接器错误。
以下是我收到的一些错误示例:
1>SMGA.obj : error LNK2005: "class Engine smgaEngine" (?smgaEngine@@3VEngine@@A) already defined in Engine.obj
1>SplashScreenState.obj : error LNK2005: "class Engine smgaEngine" (?smgaEngine@@3VEngine@@A) already defined in Engine.obj
1>StateManager.obj : error LNK2005: "class StateManager gameStateManager" (?gameStateManager@@3VStateManager@@A) already defined in Engine.obj
1>MSVCRTD.lib(cinitexe.obj) : warning LNK4098: defaultlib 'msvcrt.lib' conflicts with use of other libs; use /NODEFAULTLIB:library
我在网上看了一下,我看到很多〜类似的问题涉及不好的包括警卫或包含.cpp文件而不是.h文件。但是我的代码中没有这样做,所以我很茫然。
现在,我猜这个错误告诉我,我正在尝试两次创建Engine类的smgaEngine对象(以及StateManager类的gameStateManager对象),但我不确定为什么..
关于这两个对象(smgaEngine和gameStateManager)的突出之处在于我在类声明后立即在相应的类'.h文件中声明它们。这可能是问题吗? - 他们仍然在包含警卫范围内,而且我不太确定将其放在我的代码中的其他地方......这种草率编码是否会导致链接器错误?
这是可疑类之一......
#ifndef ENGINE_H
#define ENGINE_H
#include <SDL.h>
#include "Timer.h"
class Engine
{
private:
static const int screenWidth = 480;
static const int screenHeight = 270;
static const int screenBPP = 24;
bool running;
SDL_Surface *mainScreen;
SDL_Event eventHolder;
Timer fpsTimer;
public:
Engine();
~Engine();
void init();
void handleEvents();
void handleLogic();
void handleRender();
void cleanUp();
SDL_Event *getEvent();
SDL_Surface *getMainScreen();
bool isRunning();
void setRunning(bool tempRunning);
} smgaEngine;
#endif
这是另一个:
#ifndef STATEMANAGER_H
#define STATEMANAGER_H
#include "SplashScreenState.h"
#include <vector>
class GameState;
class StateManager
{
private:
std::vector<GameState*> stateStack;
SplashScreenState *splashState;
public:
StateManager();
~StateManager();
void init();
void changeState( GameState *tempNextState );
void addState( GameState *tempNextState );
void removeState();
//returns the back() element of the stateStack vector..
GameState* getTopState();
void handleEvents();
void handleLogic();
void handleRender();
} gameStateManager;
#endif
我一直在努力学习C ++和OOP,但我真的很挣扎。似乎每次我尝试使用封装类创建干净的代码时,我最终都会陷入混乱。我试图阻止高度的类耦合,但我经常最终得到链接器错误或缺乏类之间的通信能力......是否在头文件中创建类实例对象导致这些错误或者是别的什么?如果这是我的链接器错误的原因,那么我应该在哪里创建这些对象?
答案 0 :(得分:6)
您已在头文件中定义了两个全局变量smgaEngine
和gameStateManager
,并且已将这些头文件包含在两个(或更多)源文件中。所以你会得到多个定义错误。包含警卫不会阻止在不同的源文件中包含两次头文件(他们怎么可能?)他们会阻止在相同的源文件中包含两次头文件。
你非常接近正确的答案(至少你对这个问题有很好的理解)。正确的方法是这个
// header file Engine.h
class Engine
{
};
extern Engine smgaEngine;
// in one source file (say Engine.cpp)
Engine smgaEngine;
您现在拥有的是头文件中的声明(extern
使其成为声明),但源文件中的定义。您可以拥有任意数量的声明(只要它们是一致的),但您必须只有一个定义。因此,对于全局变量,在头文件中放置声明,并将定义放在其中一个源文件中。