2017-09-27 29 views
0

相信我,当我告诉你我在网上搜索,但没有找到答案。未定义的引用xx :: xx()

我有5个文件:

的main.cpp

Game.cpp

Game.hpp

Window.cpp

Window.hpp

内容如下:

#include "Window.hpp" 
#include "Game.hpp" 

int main() 
{ 
    // Program entry point 
    Game game; 
    while (!game.GetWindow()->IsDone()){ 
     // game loop here 
     game.HandleInput(); 
     game.Update(); 
     game.Render(); 
    } 
    return 0; 
} 

这是Game.cpp

#include "Window.hpp" 

class Game { 
    public: 
     Game(): m_window("Chapter 2", sf::Vector2u(800,600)) { 

      m_mushroomTexture.loadFromFile("images.png"); 
      m_mushroom.setTexture(m_mushroomTexture); 
     } 
     ~Game(){} 

     void HandleInput() { 

     } 
     void Update() { 
      m_window.Update(); 
      MoveMushroom(); 
     } 
     void Render() { 
      m_window.BeginDraw(); 
      m_window.Draw(m_mushroom); 
      m_window.EndDraw(); 
     } 
     // Getting a point to the window 
     Window* GetWindow(){ 

     } 

    private: 
     void MoveMushroom(){ 
      sf::Vector2u l_windSize = m_window.GetWindowSize(); 
      sf::Vector2u l_textSize = m_mushroomTexture.getSize(); 

      if ((m_mushroom.getPosition().x > l_windSize.x - l_textSize.x and m_increment.x > 0) or \ 
       (m_mushroom.getPosition().x < 0 and m_increment.x < 0)) { 
       m_increment.x = -m_increment.x; 
      } 
      if ((m_mushroom.getPosition().y > l_windSize.y - l_textSize.y and m_increment.y > 0) or \ 
       (m_mushroom.getPosition().y < 0 and m_increment.y < 0)) { 
       m_increment.y = -m_increment.y; 
      } 
      m_mushroom.setPosition(m_mushroom.getPosition().x + m_increment.x, m_mushroom.getPosition().y + m_increment.y); 
     } 
     Window m_window; 
     sf::Texture m_mushroomTexture; 
     sf::Sprite m_mushroom; 
     sf::Vector2i m_increment; 
}; 

Game.hpp

#pragma once 

#include "Window.hpp" 
#include <SFML/Graphics.hpp> 

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

    void HandleInput(); 
    void Update(); 
    void Render(); 
    // Getting a point to the window 
    Window* GetWindow(); 

private: 
    void MoveMushroom(); 
    Window m_window; 
    sf::Texture m_mushroomTexture; 
    sf::Sprite m_mushroom; 
    sf::Vector2i m_increment; 
}; 

Window.cpp

#include <SFML/Graphics.hpp> 
#include <string> 


class Window { 
public: 
    // constructor 
    Window() {Setup("Window", sf::Vector2u(640,480));} 
    // we have 2 constructors because there 2 ways to instantiate a class 

    Window(const std::string& l_title, const sf::Vector2u& l_size) { 

     Setup(l_title, l_size); 
    } 
    ~Window() { Destroy(); } 

    void BeginDraw(){ 
     m_window.clear(sf::Color::Black); 
    } 
    void EndDraw(){ 
     m_window.display(); 
    } 

    void Update(){ 

     sf::Event event; 
     while (m_window.pollEvent(event)) { 
      if (event.type == event.Closed) { 
       m_isDone = true; 
      } else if (event.type == sf::Event::KeyPressed and event.key.code == sf::Keyboard::F5){ 
       ToggleFullscreen(); 
      } 
     } 

    } 

    bool IsDone(){ 
     return m_isDone; 
    } 
    bool IsFullscreen(){ 
     return m_isFullscreen; 
    } 

    sf::Vector2u GetWindowSize() { 
     return m_windowSize; 
    } 

    void ToggleFullscreen(){ 
     m_isFullscreen = !m_isFullscreen; 
     Destroy(); 
     Create(); 
    } 

    void Draw(sf::Drawable& l_drawable){ 
     m_window.draw(l_drawable); 
    } 

private: 
    void Setup(const std::string& l_title, const sf::Vector2u& l_size) { 
     m_windowTitle = l_title; 
     m_windowSize = l_size; 
     m_isFullscreen = false; 
     m_isDone = false; 
     Create(); 
    } 

    void Destroy(){ 
     m_window.close(); 
    } 

    void Create() { 
     // the same as 
     // if (m_isFullscreen) { 
     //  auto_style = sf::Style::Fullscreen; 
     // } else { 
     //  auto_style = sf::Style::Default; 
     // } 
     auto style = (m_isFullscreen ? sf::Style::Fullscreen : sf::Style::Default); 
     m_window.create({m_windowSize.x, m_windowSize.y, 32}, m_windowTitle, style); 
    } 

    sf::RenderWindow m_window; 
    sf::Vector2u m_windowSize; 
    std::string m_windowTitle; 
    bool m_isDone; 
    bool m_isFullscreen; 

}; 

Window.hpp

#pragma once 

#include <SFML/Graphics.hpp> 
#include <string> 

class Window { 
public: 
    // constructor 
    Window(); 
    // we have 2 constructors because there 2 ways to instantiate a class 
    Window(const std::string& l_title, const sf::Vector2u& l_size); 
    ~Window(); 

    void BeginDraw(); 
    void EndDraw(); 

    void Update(); 

    bool IsDone(); 
    bool IsFullscreen(); 
    sf::Vector2u GetWindowSize(); 

    void ToggleFullscreen(); 

    void Draw(sf::Drawable& l_drawable); 
private: 
    void Setup(const std::string& l_title, const sf::Vector2u& l_size); 
    void Destroy(); 
    void Create(); 

    sf::RenderWindow m_window; 
    sf::Vector2u m_windowSize; 
    std::string m_windowTitle; 
    bool m_isDone; 
    bool m_isFullscreen; 

}; 

问题是,当我尝试构建我的项目时出现链接器错误。编译过程中

g++ -std=c++11 -c main.cpp Window.cpp Game.cpp 

没有错误:

/tmp/ccxbe5nA.o: In function `main': 
main.cpp:(.text+0x26): undefined reference to `Game::Game()' 
main.cpp:(.text+0x35): undefined reference to `Game::GetWindow()' 
main.cpp:(.text+0x3d): undefined reference to `Window::IsDone()' 
main.cpp:(.text+0x53): undefined reference to `Game::HandleInput()' 
main.cpp:(.text+0x62): undefined reference to `Game::Update()' 
main.cpp:(.text+0x71): undefined reference to `Game::Render()' 
main.cpp:(.text+0x87): undefined reference to `Game::~Game()' 
main.cpp:(.text+0xac): undefined reference to `Game::~Game()' 
collect2: error: ld returned 1 exit status 

我先用下面的命令编译。当我尝试链接它时,我收到上面的错误消息。所使用的命令是这样的:

g++ main.o Game.o Window.o -o sfml-app -lsfml-graphics -lsfml-window -lsfml-system 

回答

2

通过在不同的地方不同的定义同一个班级,你的程序违反了一个定义规则:

[basic.def.odr]/5可以有在一个程序中多于一个类类型的定义......只要每个定义出现在不同的翻译单元中,并且提供的定义满足以下要求。鉴于这样的实体命名D在多于一个翻译单元,然后定义

- 的D每个定义应由令牌的相同序列的;和...

强调我的。从Game.cpp

删除类的定义,只留下成员函数的定义,像这样:

Game::Game(): m_window("Chapter 2", sf::Vector2u(800,600)) {...} 
void Game::Update() {...} 
// and so on for other members 

,类似的还有Window

+0

这是它,现在编译和链接的一切。谢谢!出于好奇,我来自Python,并且在视觉上我喜欢将我所有的课程信息放在一个地方,在C++中是可行的,还是我必须在.h中声明并且在.cpp中定义? – SuburbanFilth

+0

如果你喜欢,你可以在.h文件中定义所有的东西,但这不是习惯C++的样子(除非定义模板,事实上它必须在头文件中实现)。在大多数C++项目中,您确实可以看到头文件中的函数声明和类定义,以及源文件中的函数定义(实际实现)。 –

1

您定义每个类两次,这是不正确的。

在您的.cpp文件中,它需要为已声明但未在标头中定义的函数提供定义。

例如,Windows.cpp应包括Windows.hpp并包含:

bool Windows::IsDone() { 
    return m_isDone; 
} 
相关问题