导致这些链接器错误的原因是什么?(Visual C++ LNK2005)

MrK*_*ish 0 c++ oop linker class

我是一名新手程序员,仍在努力学习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
Run Code Online (Sandbox Code Playgroud)

我在网上看过,我看到很多〜类似的问题涉及不好的包括警卫或包含.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 
Run Code Online (Sandbox Code Playgroud)

这是另一个:

#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
Run Code Online (Sandbox Code Playgroud)

我一直在努力学习C++和OOP,但我真的很挣扎.似乎每次我尝试使用封装类创建干净的代码时,我最终都会陷入混乱.我试图阻止高度的类耦合,但我经常最终得到链接器错误或缺乏类之间的通信能力......是否在头文件中创建类实例对象导致这些错误或者是别的什么?如果这是我的链接器错误的原因,那么我应该在哪里创建这些对象?

joh*_*ohn 6

您已经定义了两个全局变量,smgaEngine并且gameStateManager在头文件中,您已将这些头文件包含在两个(或更多)源文件中.所以你会得到多个定义错误.包含防护不会阻止在不同源文件中包含两次的头文件(它们怎么可能?)它们会阻止在同一源文件中包含两次头文件.

你非常接近正确的答案(至少你对这个问题有很好的理解).正确的方法就是这样

// header file Engine.h
class Engine
{
};

extern Engine smgaEngine;

// in one source file (say Engine.cpp)
Engine smgaEngine;
Run Code Online (Sandbox Code Playgroud)

你现在有什么是声明在头文件(extern使得它的声明),而是一个定义源文件英寸 您可以拥有任意数量的声明(只要它们是一致的),但您必须只有一个定义.因此,对于全局变量,在头文件中放置声明并在其中一个源文件中放置定义.

  • 乐意效劳."无论如何,我应该避免全局变量!" 那么这就是设计问题,你会对这样的问题得到一百万种不同的意见,而且没有一种是明确的.对于OOP和设计问题,我建议保持简单(至少在你学习的时候),然后选择对你来说本能的东西.如果全局变量似乎符合您的需求并且您没有看到缺点,那么请继续使用它们.如果以后你发现全局变量导致了问题,那么至少你会对这些问题有更好的理解. (3认同)