-2

Edit: The problem was an issue with Visual Studio. Deleting dbFile.h and recreating it fixed the error.

Background: my main experience is using C in BASH for school, and I haven't used C++ heavily in over a year.

I'm creating an SDL2 object that includes and ofstream file that prints SDL_GetError() messages. I have a dbFile and App class each in their own header and .cpp files. I created a template for an Empty SDL Project with a Window, and on the first compile I get the following error. I'm able to resolve it by commenting/uncommenting #pragma once in dbFile.cpp.

1>Debug\dbFile.obj : warning LNK4042: object specified more than once; extras ignored
1>App.obj : error LNK2019: unresolved external symbol "public: __thiscall dbFile::dbFile(void)" (??0dbFile@@QAE@XZ) referenced in function "public: __thiscall App::App(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,unsigned short,unsigned short)" (??0App@@QAE@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@GG@Z)
1>App.obj : error LNK2019: unresolved external symbol "public: __thiscall dbFile::~dbFile(void)" (??1dbFile@@QAE@XZ) referenced in function __unwindfunclet$??0App@@QAE@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@GG@Z$1
1>App.obj : error LNK2019: unresolved external symbol "public: void __thiscall dbFile::write(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?write@dbFile@@QAEXV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) referenced in function "public: __thiscall App::App(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,unsigned short,unsigned short)" (??0App@@QAE@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@GG@Z)
1>F:\SDL\Test\Debug\Test.exe : fatal error LNK1120: 3 unresolved externals

dbFile.h

#ifndef _DB_FILE_H_
#define _DB_FILE_H_

#include <iostream>
#include <fstream>
#include <string>
#include <time.h>

using namespace std;

class dbFile
{
public:
    dbFile(void);
    ~dbFile(void);
    void write(string message);

private:
    ofstream debug;
    time_t t_0;
    char str[26];
    bool inked = false;
};

#endif // !_DB_FILE_H_

dbFile.cpp

#pragma once
#include "dbFile.h"

dbFile::dbFile(void)
{
    debug.open("./Debug.txt", ofstream::out | ios::app);
    t_0 = time(NULL);
}

void dbFile::write(string message)
{
    if (inked == false)
    {
        str[26] = {};
        ctime_s(str, sizeof str, &t_0);
        debug << str << "-------------------------------------------------------\n";
        inked = true;
    }
    debug << message << endl;
}

dbFile::~dbFile(void)
{
    if (inked == true)
    {
        debug << "End of log entry....\n" 
        << "*-----------------------------------------------------*\n\n\n";
    }
    debug.close();
}

App.h

#ifndef _APP_H_
#define _APP_H_

#include <SDL.h>
#include "dbFile.h"

class App
{
public:
    App(string NAME, unsigned short int WIDTH, unsigned short int HEIGHT);
    int GameLoop();
    ~App();

private:

    bool Init(string NAME, unsigned short int WIDTH, unsigned short int HEIGHT);

    unsigned short int  SCREEN_WIDTH    = 800;
    unsigned short int  SCREEN_HEIGHT   = 600;
    bool                QUIT_GAME       = false;

    dbFile          debugFile;
    string          APP_NAME = "\0";

    SDL_Window*     gWindow     = NULL;
    SDL_Surface*    gScreenSurf = NULL;
    SDL_Event       gEvent;
};

#endif // !_APP_H_

App.cpp

#include "App.h"

App::App(string NAME, unsigned short int WIDTH, unsigned short int HEIGHT)
{
    if ((Init(NAME, WIDTH, HEIGHT)) == false)
    {
        debugFile.write("Program failed to initialized... Now closing.");
        return;
    }
}

bool App::Init(string NAME, unsigned short int WIDTH, unsigned short int HEIGHT)
{
    bool bInit = true;

    SCREEN_WIDTH = WIDTH;
    SCREEN_HEIGHT = HEIGHT;
    APP_NAME = NAME;

    if ((SDL_Init(SDL_INIT_VIDEO)) < 0)
    {
        debugFile.write("SDL failed to initialize! Error: ");
        debugFile.write(SDL_GetError());
        bInit = false;
    }

    gWindow = SDL_CreateWindow(APP_NAME.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_OPENGL);

    if (gWindow == NULL)
    {
        debugFile.write("Failed to create window. Error: ");
        debugFile.write(SDL_GetError());
        bInit = false;
    }

    gScreenSurf = SDL_GetWindowSurface(gWindow);

    if (gScreenSurf == NULL)
    {
        debugFile.write("Failed to create Surface Screen. Error: ");
        debugFile.write(SDL_GetError());
        bInit = false;
    }

    return bInit;
}

int App::GameLoop()
{
    while (QUIT_GAME == false)
    {
        while (SDL_PollEvent(&gEvent) != 0)
        {
            if (gEvent.type == SDL_QUIT)
            {
                QUIT_GAME = true;
            }
        }
    }
    return 0;
}

App::~App()
{
    SDL_DestroyWindow(gWindow);
    SDL_Quit();
}

This code is "functional," but I'd like to figure out why the linker is complaining on the first compile. Thanks!

Community
  • 1
  • 1

1 Answers1

3

"#pragma once" is used as #ifdef *** #endif in header file. It's not for cpp file.

The link errors are because linker can't find the implementation of the dbFile's functions. Once you met these linker errors, mostly because you forget to write the implementation or forgot to link correct libraries.

Tongxuan Liu
  • 270
  • 1
  • 12
  • I know pragma isn't used for .cpp files, but it was something that fixed the LNK error. As far as I know, I have the correct header files included. Edit- It turned out to be a problem with Visual Studio. I renamed a .cpp to a .h file. Deleted the dbFile.h and creating a new file solved the problem. Thanks for the comment! – Nick Stapleton Jun 28 '16 at 20:40