2017-09-27 1 views
0

Croyez-moi quand je vous dis que j'ai cherché en ligne, mais je n'ai pas trouvé la réponse.Référence non définie à xx :: xx()

J'ai 5 fichiers:

MAIN.CPP

Game.cpp

Game.hpp

Window.cpp

Window.hpp

Le contenu est ci-dessous:

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

C'est le 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; 

}; 

Le problème est que lorsque j'essaie de construire mon projet, j'obtiens une erreur de lien.

/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 

Je compile d'abord avec la commande suivante:

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

Aucune erreur lors de la phase de compilation. Lorsque j'essaie de le lier, je reçois le message d'erreur ci-dessus. La commande utilisée est la suivante:

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

Répondre

2

En définissant la même classe différemment dans différents endroits, votre programme viole une règle Définition:

[basic.def.odr]/5 Il peut y avoir plus d'une définition d'un type de classe ... dans un programme à condition que chaque définition apparaisse dans une unité de traduction différente, et à condition que les définitions répondent aux exigences suivantes. Étant donné une telle entité nommée D définie dans plus d'une unité de traduction, puis

- chaque définition de D doit se composent de la même séquence de jetons; et ...

Emphasis mine.

définition Supprimer classe de Game.cpp, ne laisser que des définitions de fonctions membres, comme ceci:

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

Et même pour Window.

+0

C'était-il, maintenant et tout compilé lié. Je vous remercie! Juste par curiosité, je viens de Python et visuellement j'aime avoir toutes mes infos de classe en un seul endroit, est-ce possible en C++ ou je dois 100% déclarer en .h et définir en .cpp? – SuburbanFilth

+0

Vous pouvez tout définir dans le fichier .h si vous le souhaitez, mais ce n'est pas ce à quoi ressemble le langage C++ idiomatique (sauf lors de la définition de modèles, qui doivent en fait être implémentés dans un en-tête). Dans la plupart des projets C++, vous verriez en effet les déclarations de fonction et les définitions de classe dans un en-tête et les définitions de fonctions (implémentation réelle) dans un fichier source. –

1

Vous définissez chaque classe deux fois, ce qui est incorrect.

Dans vos fichiers .cpp, il doit fournir des définitions pour les fonctions déclarées mais non définies dans les en-têtes.

Par ex, Windows.cpp devrait inclure Windows.hpp et contenir:

bool Windows::IsDone() { 
    return m_isDone; 
}