Hello I am trying to teach myself about the how's and why's of OOP in C++. So I am trying to seperate most of my code into specific classes and methods that do specific things.
I've also been reading/watching lots about best practice for OOP, and I can see how it gives a great advantage for making changes to things later, or re-using classes/components in other projects or other game objects.
From what I understand it is NOT good practice to put #include's to all the needed header files , inside my header files. Rather I should 'forward-declare' them in .h and then fully define them in the .cpp files. This will avoid cycles of header pastes, which gives compiler errors.
However there are MANY threads on SFML help forums directly contradicting this advice. https://en.sfml-dev.org/forums/index.php?topic=21705.0 , https://en.sfml-dev.org/forums/index.php?topic=2043.0 (and more). Thing is, I ran into compiler errors doing it their way. And had to use #pragma once everywhere (even in very small project).
I found a way to properly forward declare (https://stackoverflow.com/questions/13848451/how-to-forward-declare-a-c-template-class/13848492), and it works in the most part. Here's where it gets wierd for me....
My Guy class, it works . I have successfull forward declared a RenderWindow, Texture, Sprite and Vector2 all in sf namespace:
Guy.h:
namespace sf
{
class RenderWindow;
class Texture;
class Sprite;
template <typename> class Vector2;
}
class Guy
{
public:
Guy();
void Start();
void Update();
void Draw(sf::RenderWindow& Window);
const sf::Vector2<float> GetPosition();
void SetPosition(float x, float y);
private:
sf::Texture Texture;
sf::Sprite Sprite;
};
Guy.cpp:
#include "SFML/Graphics.hpp"
#include "SFML/System.hpp"
#include "Guy.h"
#include "Constants.h"
Guy::Guy()
{
Texture.loadFromFile("Textures/guy.png");
Sprite.setTexture(Texture, true);
Sprite.setOrigin(Sprite.getTextureRect().width * 0.5f, Sprite.getTextureRect().height * 0.5f);
SetPosition(15 * Constants::PPU, 18 * Constants::PPU);
}
void Guy::Start()
{
}
void Guy::Update()
{
}
void Guy::Draw(sf::RenderWindow& Window)
{
Window.draw(Sprite);
}
const sf::Vector2<float> Guy::GetPosition()
{
return Sprite.getPosition();
}
void Guy::SetPosition(float x, float y)
{
Sprite.setPosition(x, y);
}
That all worked for me, but then I tried to move the #includes on my 'LevelManager' class (this time I had to forward declare stuff from sf and std namespace, maybe this is why?)...
LevelManager.h:
namespace sf
{
class RenderWindow;
class View;
class Texture;
}
namespace std
{
class string;
template <typename, typename> class vector;
}
class Guy;
class Tile;
class LevelManager
{
public:
void Start();
void Update();
void Draw(sf::RenderWindow& Window);
sf::View& GetGameView();
private:
sf::View GameView;
Guy Guy;
std::string Level1;
sf::Texture TileTexture_Sky;
sf::Texture TileTexture_Ground;
std::vector<Tile> LevelTiles;
};
LevelManager.cpp:
#include <string>
#include "SFML/Graphics.hpp"
#include "Guy.h"
#include "Tile.h"
#include "Constants.h"
#include <iostream>
#include "ViewTools.h"
#include "LevelManager.h"
void LevelManager::Start()
{
Level1 = "";
GameView.setSize(Constants::VIEW_WIDTH, Constants::VIEW_HEIGHT);
GameView.setCenter(GameView.getSize().x / 2, GameView.getSize().y / 2);
GameView = ViewTools::GetLetterBoxView(GameView, Constants::WINDOW_WIDTH, Constants::WINDOW_HEIGHT);
Guy.Start();
GameView.setCenter(Guy.GetPosition());
TileTexture_Sky.loadFromFile("Textures/tile_sky.png");
TileTexture_Ground.loadFromFile("Textures/tile_ground.png");
// .......Rest of class...
// ......
// ......
And this gives me hundred+ errors. It got very hard for me to debug, because it seems on Guy.cpp if I re-order the #includes , this can break them. They needed to have SFML/Graphics.hpp first I think (?I'm confused?). I tried many orders in LevelManager but couldnt get rid of errors. I also tried many variations of the wordings for forward declaration without success.
If I #include SFML/Graphics.hpp (and Guy.h & Tile.h) in LevelManager.h , then the problem is gone... but one day I will have to include it in two headers unless I realise why it is like this.
The SFML forums where not super-helpful. They seem to tell you just do it in .h and use #pragma once.
My Question: Should I find a way to #include "SFML/Graphics.hpp" and the other two headers in the LevelManager.cpp, or move them back to the LevelManager.h? I do also have other queries about why sometimes the forward declarations work fine, and other times they don't (but I cannot get the question written concisely, i will have to form a new question for this and post all the code i think).
At any rate, thank you for all and any help
class
tostruct
(ortypedef
), you need to adapt all forward declarations. Additionally, the C++ standard says that you should not use forward declarations forstd
types, e.g.,std::string
orstd::vector
. \$\endgroup\$