main.cpp:(.text+0x5f): undefined reference to

5
我会帮您进行翻译。以下是需要翻译的内容:

我尝试编译一些SDL指南上的练习。

我的编译方式如下:

g++ -o main main.cpp -I/usr/local/include/SDL2 -L/usr/local/lib -lSDL2

"我得到了这个:"
/tmp/cci2rYNF.o: In function `main':
main.cpp:(.text+0x5f): undefined reference to `Game::init(char const*, int, int, int, int, int)'
collect2: error: ld returned 1 exit status

我的代码是:

main.cpp

#include "Game.h"

// our Game object
Game* g_game = 0;

int main(int argc, char* argv[])
{
    g_game = new Game();
    g_game->init("Chapter 1", 100, 100, 640, 480, 0);

    while(g_game->running())
    {
    g_game->handleEvents();
    g_game->update();
    g_game->render();
    }
    g_game->clean();

    return 0;
}

Game.h

#ifndef __Game__
#define __Game__

#include <SDL.h>

class Game
{
    public:
      Game() {}
      ~Game() {}

      bool init(const char* title, int xpos, int ypos, int width, int height, int flags);
      void render(){}
      void update(){}
      void handleEvents(){}
      void clean(){}

      // a function to access the private running variable
      bool running() { return m_bRunning; }

    private:

      SDL_Window* m_pWindow;
      SDL_Renderer* m_pRenderer;
      bool m_bRunning;
};

#endif // defined(__Game__) */

Game.cpp

#include "Game.h"

bool Game::init(const char* title, int xpos, int ypos, int width, int height, int flags)
{
    // attempt to initialize SDL
    if(SDL_Init(SDL_INIT_EVERYTHING) == 0)
    {
    std::cout << "SDL init success\n";
    // init the window
    m_pWindow = SDL_CreateWindow(title, xpos, ypos,
    width, height, flags);

    if(m_pWindow != 0) // window init success
    {
        std::cout << "window creation success\n";
        m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);
        if(m_pRenderer != 0) // renderer init success
        {
        std::cout << "renderer creation success\n";
        SDL_SetRenderDrawColor(m_pRenderer,
        255,255,255,255);
        }
        else
        {
        std::cout << "renderer init fail\n";
        return false; // renderer init fail
        }
    }
    else
    {
        std::cout << "window init fail\n";
        return false; // window init fail
    }
    }
    else
    {
    std::cout << "SDL init fail\n";
    return false; // SDL init fail
    }
    std::cout << "init success\n";
    m_bRunning = true; // everything inited successfully, start main loop

    return true;
}


void Game::render()
{
    SDL_RenderClear(m_pRenderer); // clear the renderer to the draw color
    SDL_RenderPresent(m_pRenderer); // draw to the screen
}


void Game::clean()
{
    std::cout << "cleaning game\n";
    SDL_DestroyWindow(m_pWindow);
    SDL_DestroyRenderer(m_pRenderer);
    SDL_Quit();
}

void Game::handleEvents()
{
    SDL_Event event;
    if(SDL_PollEvent(&event))
    {
      switch (event.type)
      {
        case SDL_QUIT:
          m_bRunning = false;
        break;

        default:
        break;
      }
    }
}

1
好的,你没有链接game.cpp的目标文件。 - OldProgrammer
一直都是这样:浪费了那么多时间,还是一个愚蠢的错误。我得学习一下 g++。谢谢! - IIanFumenchu
我发现g++ -o driver driver.cpp Class.cpp对我很有帮助。 - Mary X
2个回答

14

C和C++拥有“编译单元”的概念,它是编译器调用的源文件以及它所包含的所有代码(包括使用#include指令引用的代码)。

GCC、MSVC以及大多数其他编译器都会为每个编译单元生成一个中间“目标文件”(.o或.obj)。这些目标文件必须和任何库一起组合起来进行“链接”步骤,最终形成可执行文件。

使用GCC有几种方法可以做到这一点。其中之一是单行命令:

g++ -o app.exe file1.cpp file2.cpp

这个命令将file1.cpp和file2.cpp分别编译成目标文件,然后将生成的目标文件链接在一起形成名为“app.exe”的可执行文件(扩展名“.exe”并非必须,我只是为了方便而使用它)。

或者可以使用多个命令来完成此过程:

g++ -o file1.o -c file1.cpp
g++ -o file2.o -c file2.cpp
g++ -o app.exe file1.o file2.o

这会对每个cpp文件执行单独的编译步骤,然后使用“g ++”作为每个步骤的前端执行单独的链接步骤。请注意第一和第二行中的-c,它告诉编译器你要将C/C++源代码编译为.object文件。第三行,编译器前端意识到你正在请求编译目标文件,并推断出你想进行链接步骤。

对于小型项目,第一种方法通常最简单,而当你使用任何类型的构建系统并且事情开始变得复杂时,第二种方法非常有用。


13

你没有编译Game.cpp。尝试:

g++ -o main main.cpp Game.cpp -I/usr/local/include/SDL2 -L/usr/local/lib -lSDL2

问题在于,虽然你在 main.cpp 中使用了#include引入了 Game.h ,但它引用了在 Game.cpp 中定义的函数。如果不将其编译,链接器就没有所需的定义来生成可执行文件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接