C++ - SFML ошибка при компиляции: ‘Window’ does not name a type
Есть 2 класса:
1) Window.hpp
2) Spaceship.hpp
Подключил Window.hpp к классу Spaceship.hpp а Spaceship.hpp подключил к Window.hpp
Window.hpp:
#pragma once
#include <SFML/Graphics.hpp>
#include "Spaceship.hpp"
#include <bits/stdc++.h>
using namespace std;
class Window{
public:
Window(){
settings.antialiasingLevel=8;
window.create(sf::VideoMode(width, height), "Game", sf::Style::Close, settings);
window.setPosition(sf::Vector2i(desktop_width/2-width/2, desktop_height/2-height/2));
Background();
Spaceship();
while(window.isOpen()){
while(window.pollEvent(event)){
if(event.type==sf::Event::Closed)
window.close();
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
window.close();
}
window.clear();
window.draw(background_sprite);
window.draw(spaceship.ship_sprite);
window.display();
}
}
private:
void Background(){
background_texture.loadFromFile("textures/background.png");
background_sprite.setTexture(background_texture);
background_sprite.setPosition(0, 0);
}
public:
const int width=500, height=900;
const int desktop_width=sf::VideoMode::getDesktopMode().width, desktop_height=sf::VideoMode::getDesktopMode().height;
Spaceship spaceship;
sf::RenderWindow window;
sf::Event event;
sf::ContextSettings settings;
sf::Texture background_texture;
sf::Sprite background_sprite;
};
Spaceship.hpp:
#pragma once
#include <SFML/Graphics.hpp>
#include "Window.hpp"
#include <bits/stdc++.h>
using namespace std;
class Spaceship{
public:
Spaceship(){
Ship();
}
void Ship(){
ship_texture.loadFromFile("textures/Ship.png");
ship_sprite.setTextureRect(sf::IntRect(0, 0, 48, 32));
ship_sprite.setPosition(window.width/2-ship_sprite.getTextureRect().width/2, window.height-ship_sprite.getTextureRect().height);
}
Window window;
sf::Texture ship_texture;
sf::Sprite ship_sprite;
};
При компиляции выдаёт ощибку:
Spaceship.hpp:19:5: error: ‘Window’ does not name a type
19 | Window window;
| ^~~~~~
In file included from Window.hpp:3,
from Game.cpp:1:
Spaceship.hpp: In member function ‘void Spaceship::Ship()’:
Spaceship.hpp:16:33: error: ‘window’ was not declared in this scope
16 | ship_sprite.setPosition(window.width/2-ship_sprite.getTextureRect().width/2, window.height-ship_sprite.getTextureRect().height);
| ^~~~~~
make: *** [makefile:2: output] Error 1
Кто может подсказать как исправить?
Ответы (1 шт):
У Вас классическая циклическая зависимость. Когда создается один из классов, ему нужно знать размер второго. Но второму нужно знать размер первого. Как это решать?
Вариант первый. В одном из мест сделать указатель плюс forward declaration - то есть, просто написать перед объявлением класса краткое объявление другого - class Window; или class Spaceship;. Указатель конечно потребует вызова new/delete или использование unique_ptr.
В конструкторе Window есть такой вызов Spaceship(); - Вы просто вызываете конструктор корабля, создаете временный объект, который тут же удаляется... Это точно не то, что Вам нужно.
Но давайте посмотрим на это по другому. Класс корабля знает имеет свою переменную для window. Но оно ему нужно только что бы размеры посчитать. Так может передать эти размеры? Перепишем
class Spaceship{
public:
Spaceship(){
}
void Ship(int width, int height){
ship_texture.loadFromFile("textures/Ship.png");
ship_sprite.setTextureRect(sf::IntRect(0, 0, 48, 32));
ship_sprite.setPosition(width/2-ship_sprite.getTextureRect().width/2, height-ship_sprite.getTextureRect().height);
}
sf::Texture ship_texture;
sf::Sprite ship_sprite;
};
И теперь вызываем правильно - передав параметры.
И вместо
Background();
Spaceship();
пишем
Background();
spaceship.Ship(window.width(), window.height());
Все, осталось удалить лишний инклуд.
И ещё почитать о том, что такое конструкторы и классы.