Zulukas Zulukas - 3 months ago 16
C++ Question

Visual Studio separate .h and .cpp files for a set of functions

I'm trying to get used to Visual Studio's c++ environment and I'm having an issue with a set of functions which I wish to define into their own .h and .cpp files.

Within my project, there is a file containing some common variables and definitions called "common.h".

So far I have a simple main.cpp and I'm trying to break apart these functions to clean up my project a bit.

The .h file looks like this so far:

#pragma once

#include "common.h"

void SDLInitGameData();
void SDLCleanUp();


The .cpp to the .h above has the definitions listed in the header as well as some helper functions that I wanted to keep "private" to those functions.

Within my main.cpp I have this so far:

#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);
}


My common.h looks like this so far:

#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);


I am getting a handful of LNK2005. From my research, this is a "One Definition Rule" issue. When I would do code like this in a makefile, I would have had a rule to compile the SDLInitialize.h/cpp file and link it with main. That doesn't appear to work in Visual Studio.

Any ideas what I'm doing wrong?

Answer

In your common.h:

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

Every translation unit that includes this header file is going to define these variables in the global scope, hence the duplicate definitions at link time.

Instead, you need to declare all of these as extern, and then define them in one of the translation units.

Comments