2016-08-26 2 views
-1

Я пытаюсь привыкнуть к среде C++ Visual Studio, и у меня возникла проблема с набором функций, которые я хочу определить самостоятельно. h и .cpp.Visual Studio отдельные файлы .h и .cpp для набора функций

В моем проекте есть файл, содержащий некоторые общие переменные и определения, называемые «common.h».

До сих пор у меня простой main.cpp, и я пытаюсь разбить эти функции, чтобы немного почистить мой проект.

заголовочных файл выглядит так до сих пор:

#pragma once 

#include "common.h" 

void SDLInitGameData(); 
void SDLCleanUp(); 

.cpp в .h выше имеет определения, перечисленные в заголовке, а также некоторые вспомогательные функции, которые я хотел бы сохранить «частный» к этим функциям.

В моей 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. Из моих исследований это вопрос «Одно определение». Когда я сделаю такой код в make-файле, у меня было бы правило скомпилировать файл SDLInitialize.h/cpp и связать его с main. Это не работает в Visual Studio.

Любые идеи, что я делаю неправильно?

+0

Не имеет прямого отношения к вопросу, но '#undef main' не требуется, если вы не делаете что-то странное в другом месте кода или в настройках проекта. – dxiv

+0

Это странный случай, но, по-видимому, SDLmain.lib имеет главную функцию внутри него. Если у вас его нет, компоновщик схватится. Undef это, и он будет компилироваться просто отлично. – Zulukas

+1

Это необычно, а не лучшая практика. Во всяком случае, я искал «SDLmain» любопытством, и это не то, как вы должны это делать. Per [их FAQ] (http: //wiki.libsdl.org/FAQWindows#I_get_.22Undefined_reference_to_.27SDL_main.27.22 _...), ваш 'main' * должен * иметь прототип' int main (int argc, char * argv []) 'т.е. не просто' int main() '. – dxiv

ответ

1

В вашем common.h:

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

Каждый перевод блок, который включает в себя этот заголовочный файл будет определять эти переменные в глобальном масштабе, следовательно, дублирующие определения на этапе компоновки.

Вместо этого вам необходимо объявить все из них как extern, а затем определить их в одном из единиц перевода.

+0

Спасибо, это точно. Иногда эти ошибки компоновщика немного загадочны, а не просто говорят, что именно они пытаются сказать. :) – Zulukas

Смежные вопросы