【问题标题】:Visual Studio separate .h and .cpp files for a set of functionsVisual Studio 为一组函数分离 .h 和 .cpp 文件
【发布时间】:2016-08-26 02:03:31
【问题描述】:

我正在尝试习惯 Visual Studio 的 c++ 环境,但我遇到了一组函数的问题,我希望将这些函数定义到他们自己的 .h 和 .cpp 文件中。

在我的项目中,有一个包含一些常用变量和定义的文件,名为“common.h”。

到目前为止,我有一个简单的 main.cpp,我正在尝试分解这些函数以稍微清理我的项目。

.h 文件目前看起来像这样:

#pragma once

#include "common.h"

void SDLInitGameData();
void SDLCleanUp();

上面的 .h 的 .cpp 具有标题中列出的定义以及我希望对这些函数保持“私有”的一些辅助函数。

到目前为止,在我的 main.cpp 中:

#include <iostream>

#include "common.h"
#include "SDLInitialize.h"

int main()
{
    SDLInitGameData();
    system("pause");
    SDLCleanUp();
    return 0;
}

void ReportError(const char* ccpErrorMessage, const TInitializationError xReturnStatus)
{
    cerr << ccpErrorMessage << ": ";

    if (xReturnStatus == SDL_TTF_INIT_ERROR_CODE)
    {
        cerr << TTF_GetError();
    }
    else if (xReturnStatus == SDL_INITFRAMEFRATE_ERROR_CODE)
    {
        cerr << "Unable to initialize FPSManager Object.";
    }
    else
    {
        cerr << SDL_GetError();
    }

    cerr << "\n";

    SDLCleanUp();
    exit(xReturnStatus);
}

到目前为止,我的 common.h 看起来像这样:

#pragma once

#include "SDL.h"
#include "SDL_ttf.h"
#include "SDL2_gfxPrimitives.h"
#include "SDL2_framerate.h"

#include <stdint.h>

#ifdef _WIN32
#include "Windows.h"
#endif

//Program will not compile without this
#ifdef main
#undef main
#endif /* main */

#define SCRN_TITLE "Title"
#define SCRN_WIDTH 640
#define SCRN_HEIGHT 480

#define FPS_CAP 30

struct TGameData
{
    static SDL_Window* Window;
    static SDL_Renderer* Renderer;
    static FPSmanager* Manager;
} gxGameData;

SDL_Window* TGameData::Window = nullptr;
SDL_Renderer* TGameData::Renderer = nullptr;
FPSmanager* TGameData::Manager = nullptr;

enum TInitializationError
{
    SDL_INIT_ERROR_CODE = 1,
    SDL_CREATEWINDOW_ERROR_CODE,
    SDL_CREATERENDERER_ERROR_CODE,
    SDL_INITFRAMEFRATE_ERROR_CODE,
    SDL_TTF_INIT_ERROR_CODE
};

void ReportError(const char* ccpErrorMessage, const TInitializationError xReturnStatus);

我得到了一把 LNK2005。根据我的研究,这是一个“单一定义规则”问题。当我在 makefile 中执行这样的代码时,我会有一个规则来编译 SDLInitialize.h/cpp 文件并将其与 main 链接。这在 Visual Studio 中似乎不起作用。

任何想法我做错了什么?

【问题讨论】:

  • 与问题没有直接关系,但应该不需要#undef main,除非你在代码的其他地方或项目设置中做了一些奇怪的事情。
  • 这是一个奇怪的案例,但显然 SDLmain.lib 中有一个 main 函数。如果你没有它,链接器会抱怨。取消它,它会编译得很好。
  • 这很不寻常,不是最佳做法。不管怎样,我好奇地查了SDLmain,这不是你应该做的。根据their FAQ,您的main 必须具有原型int main(int argc, char *argv[]),即不仅仅是int main()

标签: c++ visual-studio-2015 one-definition-rule


【解决方案1】:

在你的 common.h 中:

SDL_Window* TGameData::Window = nullptr;
SDL_Renderer* TGameData::Renderer = nullptr;
FPSmanager* TGameData::Manager = nullptr;

包含此头文件的每个翻译单元都将在全局范围内定义这些变量,因此在链接时重复定义。

相反,您需要将所有这些声明为extern,然后在其中一个翻译单元中定义它们。

【讨论】:

  • 谢谢,确实做到了。有时这些链接器错误有点神秘,而不仅仅是说出他们想要说的是什么。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
相关资源
最近更新 更多