2017-09-27 1 views
0

Glauben Sie mir, wenn ich Ihnen sage, dass ich online suchte, aber nicht die Antwort gefunden.Undefinierter Verweis auf xx :: xx()

Ich habe 5 Dateien:

main.cpp

Game.cpp

Game.hpp

Window.cpp

Window.hpp

Der Inhalt ist unten:

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

Dies ist der 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; 

}; 

Das Problem ist, dass wenn ich versuche, mein Projekt zu erstellen, bekomme ich einen Linker-Fehler.

/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 

Ich Kompilieren zuerst mit dem folgenden Befehl ein:

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

Keine Fehler bei der Erstellung der Bühne. Wenn ich versuche, es zu verknüpfen, erhalte ich die Fehlermeldung von oben. Der Befehl, ist dies:

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

Antwort

2

Durch die gleiche Klasse unterschiedlich an verschiedenen Orten zu definieren, Ihr Programm gegen eine Definition Regel:

[basic.def.odr]/5 Es kann sein mehr als eine Definition eines Klassentyps ... in einem Programm, vorausgesetzt, dass jede Definition in einer anderen Übersetzungseinheit erscheint und vorausgesetzt, dass die Definitionen die folgenden Anforderungen erfüllen. Bei einer solchen Entität genannt D definiert in mehr als eine Übersetzungseinheit, dann

- jede Definition von D soll bestehen aus der gleichen Folge von Token; und ...

Emphasis meins.

Remove Klassendefinition von Game.cpp, nur Mitglied Funktionsdefinitionen, wie dies verlassen:

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

Und in ähnlicher Weise für Window.

+0

Das war es, nun zusammengestellt und alles verbunden. Vielen Dank! Nur aus Neugier, ich aus Python kommen und visuell mag ich all meine Klassen Informationen an einer Stelle haben, ist das möglich in C++ oder i 100% hat in .h und definiert in CPP zu erklären? – SuburbanFilth

+0

Sie könnten alles in der H-Datei definieren, wenn Sie so geneigt sind, aber das ist nicht das, was idiomatische C++ sieht aus wie (außer, wenn Vorlagen definieren, die in der Tat müssen in einem Header implementiert werden). In den meisten C++ - Projekten würden Sie tatsächlich Funktionsdeklarationen und Klassendefinitionen in einem Header und Funktionsdefinitionen (tatsächliche Implementierung) in einer Quelldatei sehen. –

1

Sie definieren jede Klasse zweimal, was nicht korrekt ist.

In Ihren .cpp Dateien braucht es Definitionen für Funktionen, aber nicht in den Headern definiert erklärt bereitzustellen.

Z. B. sollte Windows.cpp umfassen Windows.hpp und enthalten:

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