未定义的引用xx :: xx()
问题描述:
相信我,当我告诉你我在网上搜索,但没有找到答案。未定义的引用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
答
通过在不同的地方不同的定义同一个班级,你的程序违反了一个定义规则:
[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
。
答
您定义每个类两次,这是不正确的。
在您的.cpp
文件中,它需要为已声明但未在标头中定义的函数提供定义。
例如,Windows.cpp
应包括Windows.hpp
并包含:
bool Windows::IsDone() {
return m_isDone;
}
这是它,现在编译和链接的一切。谢谢!出于好奇,我来自Python,并且在视觉上我喜欢将我所有的课程信息放在一个地方,在C++中是可行的,还是我必须在.h中声明并且在.cpp中定义? – SuburbanFilth
如果你喜欢,你可以在.h文件中定义所有的东西,但这不是习惯C++的样子(除非定义模板,事实上它必须在头文件中实现)。在大多数C++项目中,您确实可以看到头文件中的函数声明和类定义,以及源文件中的函数定义(实际实现)。 –