I'm working on a simple game C++ game using the SFML library. This is one of my first endeavors with C++ and I'm running into some problems with defining structs in headers.
Here is the bullet.h:
#pragma once
#include <SFML\Graphics.hpp>
struct BulletTransform {
sf::RectangleShape shape;
//details
BulletTransform(float, float);
};
class Bullet {
//class definition stuff, no problems here
then I try to create an implementation in the bullet.cpp file:
#include "Bullet.h"
struct BulletTransform {
sf::RectangleShape shape;
BulletTransform::BulletTransform(float mX, float mY)
{
//constructor for shape stuff
}
};
Now when I try to compile it throws an error saying struct in the bullet.cpp being a type redefinition. I understand that I cannot define a struct with the same name twice, but I am also not sure how I can fix this issue. Do I somehow need to get a reference to the definition in the header? Or is my implementation simply wrong? Thanks in advance!
In the header file you can make the declaration. In the source file the definition - thats the rule of thumb in general. In your case for example:
in bullet.h:
struct BulletTransform {
sf::RectangleShape shape;
// cntr
BulletTransform(float mX, float mY) ;
// other methods
void Function1(float x, float y, float z);
};
in bullet.cpp:
BulletTransform::BulletTransform(float mX, float mY) {
// here goes the constructor stuff
}
void BulletTransform::Function1(float x, float y, float z) {
// ... implementation details
}
Normally you don't do some heavy stuff in the constructor - just the initialization of data members for example to some default values.
Hope this helps.
You've repeated your struct definition in your implemenation file. Don't do that. Instead, provide definitions for the individual members, like this:
#include "Bullet.h"
BulletTransform::BulletTransform(float mX, float mY)
{
//constructor for shape stuff
}
Related
After searching on nearly every page covering this error, I couldn't find a solution that matched my problem. When including the header file for the base class in the file of the derived class, I get the error: "error C2504: 'Entity': base class undefined". I have three classes, a parent class, derived class, and an inbetween class that both of the other classes need access to. I'm making an entity class for my enemies and other entities to inherit from, but even after including its header, I still get the error. I've tried forward declarations for the parent class and they don't seem to do anything to no avail. Before looking at my code, ignore common.h, player.h, skeleton.h, game.h, and resourcemanager.h. Without futher ado, here is my code:
(Entity.h)
#include "Common.h"
#include "Tile.h";
class Entity {
public:
Tile *isSideColliding(bool isSolid, string&& type);
Tile* isTopColliding(bool isSolid, string&& type);
Tile* isBottomColliding(bool isSolid, string&& type);
Sprite sprite;
RectangleShape topHitbox, bottomHitbox;
};
(Slime.h)
#pragma once
#include "Common.h"
#include "Game.h"
#include "Entity.h"
#include "Tile.h"
#include "ResourceManager.h"
class Slime: public Entity {
public:
static vector<Slime> slimeVector;
Slime(float& x, float& y);
static void draw();
static void update();
private:
static const Vector2f SPRITE_DIMENSIONS;
char dir;
//Sprite sprite;
//RectangleShape topHitbox, bottomHitbox;
/*Tile* isSideColliding(bool isSolid, string&& type);
Tile* isTopColliding(bool isSolid, string&& type);
Tile* isBottomColliding(bool isSolid, string&& type);*/
static const float GRAVITY;
static const Vector2f TERMINAL_VELOCITY;
Vector2f position, velocity;
};
(Tile.h)
#pragma once
#include "Common.h"
#include "Player.h"
#include "Skeleton.h"
#include "ResourceManager.h"
#include "Chest.h"
#include "Slime.h"
class Slime;
class Player;
class Skeleton;
class Tile {
public:
Sprite sprite;
static void draw();
static void createLevelPathing();
static void setupBackground();
static vector<Tile> tileVector;
Vector2f spriteDimensions;
bool isSolid;
string type;
private:
Tile(float& x, float& y, string&& type, bool isSolid);
Tile(int& x, int& y, bool isSolid);
static void initTiles(int& levelPosX, int& levelPosY, const Image& image);
static Image getRoomTemplate(int& templateType);
static const float POSITION_SCALAR, SCALE;
static const int START_TILE, DOWN_TILE, UP_TILE, UP_AND_DOWN_TILE, DOOR_TILE;
};
My goal is to inherit from entity to slime. I'm fairly sure my file setup is good though. Could anyone please help explain why I'm getting the error of no base class defined? Also, I would appreciate critisism on my file including and how I could better structure it. Thanks!
As Jerry pointed out in the comment, it is circular include.
This normally implies that something can be improved in the design.
For example, why does the Entity has to care about the colliding logic? Can it instead expose some functions for the Tile module to calculate colliding?
Come back to your question. I suggest to:
In Entity, forward declare the Tile class. Move the #include "tile.h" to the .cpp file. Do the same for Slime.
In Tile, remove the #include and forward declaration for Entity and Slime, it seems they're completely unused there.
Again, I still believe it is better to rethink the flow and the responsibility of classes, which one does what. From what I can remember, circular dependencies will likely bite us later.
I am doing OOP in C++ for the first time. I have noticed it's very different from other languages in which I have done OOP in the past.
It's been going great so far, but I have encountered an issue where I need a constructor to receive an object that I have created as parameter and for some reasons it refuses to compile and throws errors.
I made a deep research about the problem online, but I do not see cases that look enough like mine and answers vary a lot. I would like the proper way to solve this problem, so I can follow these conventions throughout my whole project.
Here is the header file where the error has been thrown (Player.h):
#pragma once
// Header files
#include "Square.h"
class Player
{
private:
// Private variables
Square _position;
public:
// Public constructors declarations
Player(Square position);
// Public functions declaration
void setPosition(Square position);
Square getPosition();
};
Here is the CPP file where the error has been thrown (Player.cpp):
// Header files
#include "Player.h"
// Public constructors
Player::Player(Square position) // <---------- ERROR LOCATION
{
_position = position;
}
// Public functions
void Player::setPosition(Square position)
{
_position = position;
}
Square Player::getPosition()
{
return _position;
}
Just in case, here is the header file of the parameter object (Square.h):
#pragma once
class Square
{
private:
// Private variables
int _x;
int _y;
public:
// Public constructors declarations
Square(int x, int y);
// Public functions declaration
void setX(int x);
int getX();
void setY(int y);
int getY();
};
Here is also the CPP file of the parameter object (Square.cpp):
// Header files
#include "Square.h"
// Public constructors
Square::Square(int x, int y)
{
_x = x;
_y = y;
}
// Public functions
void Square::setX(int x)
{
_x = x;
}
int Square::getX()
{
return _x;
}
void Square::setY(int y)
{
_y = y;
}
int Square::getY()
{
return _y;
}
Here are the errors thrown by the compiler:
At line 4 of the file 'Player.cpp':
Error E0291: no default constructor exists for class 'Square'
Error C2512: 'Square' : no appropriate default constructor avaible
The issue is that Player::_position needs to be constructed before your opening brace in any Player constructor. You can either
Create a default constructor (one that can be called without arguments) for Square. This may or may not be appropriate for your program.
Use an initializer list. This avoids design issues if Square can't have a default constructor for some reason.
The initializer list solution looks like this:
Player::Player(Square position)
: _position{position} { }
Looks like the default constructor is implicitly deleted. You may try adding a trivial one as follows (as public in Square.h.
Square(): _x(0), _y(0){}
~Square(){}
Given that you implemented a constructor for Square, the compiler doesn't implement the default constructor. Your only way to construct Square is using the constructor you defined.
Once you declared the Player's member variable Square _position, it shall be initialized somehow on Player's constructor. However, the compiler can't use the constructor you provided.
You can declare the default constructor yourself, by:
Square() = default;
The error code is shown in the first line of the constructor, because the compiler is trying to initialize every member of Player before executing the body of the constructor, but it can't find a suitable way to construct Square.
Another solution is to initialize the member variable directly using the constructor you provided. This way, the compiler will use your constructor when initializing Player's member variables:
Square _position = Square(0,0)
Could someone ease my struggling, please. I am trying to organize two classes (Points) to return opposite class in their methods. Cartesian point class has method that returns Polar point and vice versa.
Point2D.h
#pragma once
#include "PointPolar2D.h"
class Point2D
{
private:
double x;
double y;
public:
Point2D(double x, double y);
PointPolar2D toPolar();
~Point2D();
};
Point2D.cpp
#include "stdafx.h"
#include "Point2D.h"
#include "PointPolar2D.h"
Point2D::Point2D(double x, double y) : x(x), y(y)
{
}
PointPolar2D Point2D::toPolar()
{
return PointPolar2D(1, 4);
}
Point2D::~Point2D()
{
}
PointPolar2D.h
#pragma once
#include "Point2D.h"
class PointPolar2D
{
private:
double radius;
double angle;
public:
PointPolar2D(double radius, double angle);
Point2D toCartesian();
~PointPolar2D();
};
PointPolar2D.cpp
#pragma once
#include "Point2D.h"
class PointPolar2D
{
private:
double radius;
double angle;
public:
PointPolar2D(double radius, double angle);
Point2D toCartesian();
~PointPolar2D();
};
It does not compile. The error says: toPolar:unknown override specifier and also unexpected token(s)preceding ;
Please, help me figure out the reason. It must be something obvious or not.
I will provide any clarifications if needed.
Thanks.
EDITED
Created MCVE, as #Amit proposed. Thanks.
From the names of the classes, I'm guessing that PointPolar2D is a sub-class of Point2D.
Hence, PointPolar2D.h needs to #include Point2D.h. You also have:
#include "PointPolar2D.h"
in Point2D.h. That is circular inclusion. It leads to all kinds of problems.
Remove that line from Point2D.h and add a forward declaration.
class PointPolar2D;
You don't need the complete class definition to declare the function.
PointPolar2D toPolar();
A forward declaration would suffice.
Make sure to #include PointPolar2D.h in Point2D.cpp. You need the definition of PointPolar2D to implement Point2D::toPolar.
I don't understand why I am getting an unresolved external symbol in this specific example.
I have a Rectangle struct defined in a header file.
I have a Level class which has a pointer to a Player class as the Level creates a new player.
I my Player class, the constructor takes in a pointer to it's current level.
So since my Level includes Player.h I forward declare Level in my Player class to prevent a circular reference.
However, when I try and add a Rectangle member variable to my Player class - I get the unresolved external symbol error, but I can't see why - since the Player class includes the header - and the definition is in the header. It works fine in my Level class.
Also - if I change the member variable to a pointer it links fine.
Can someone explain to me why this is the case and how I can fix the issue?
// Rectangle.h
#pragma once
namespace Test
{
struct Rectangle
{
public:
Rectangle();
Rectangle(
int x,
int y,
int width,
int height) :
X(x),
Y(y),
Width(width),
Height(height)
{
}
int X;
int Y;
int Width;
int Height;
};
}
// Level.h
#pragma once
#include "Player.h"
#include <memory>
namespace Test
{
class Level
{
public:
Level()
{
_player.reset(new Player(this));
};
private:
std::unique_ptr<Player> _player;
};
}
// Player.h
#pragma once
#include "Rectangle.h"
namespace Test
{
class Level;
class Player
{
public:
Player(
Level* currentLevel) :
_currentLevel(currentLevel)
{
}
private:
Level* _currentLevel;
// This line causes the issue
Rectangle _localBounds;
};
}
You forgot to add braces on your Rectangle constructor. Make it like this:
Rectangle() {}
So the problem is you have the definition but not the implementation. You can indeed declare a function without braces but it is like you make a promise to the compiler that you are going to add the function's body somewhere else. That's why separating classes to .hpp and .cpp files works.
Note: Retired Ninja gave the answer first in a comment below the post.
So I'm trying to get class "Herder" to inherit from class "Mob". But I am getting compiler errors that read as follows:
error: invalid use of incomplete type 'struct Mob'
error: forward declaration of 'struct Mob'
This is what Herder.h looks like:
#ifndef HERDER_H_INCLUDED
#define HERDER_H_INCLUDED
#include <SFML/Graphics.hpp>
#include <cstdlib>
#include "Level.h"
#include "Mob.h"
class Mob;
class Herder : public Mob
{
public:
//Member functions.
Herder(Level* level, int x, int y);
void virtual GameCycle(sf::RenderWindow* App);
void virtual Die();
void Roar();
protected:
float m_RoarCountdown;
float m_RoarTime;
float m_Speed;
bool m_Roaring;
};
#endif // HERDER_H_INCLUDED
Figuring that it must be the class Mob; that is causing this, I remove it, but then I get the following error, refering to the line where the curly braces open:
error: expected class-name before '{' token
This is actually why I originally added the forward declaration - I had thought that the compiler wasn't recognizing Mob in class Herder : public Mob, so I figured I would forward declare.
I don't think it's a case of cyclical dependency, as has been the case in some cases I found via Google - "Mob.h" contains nothing to do with the Herder class whatsoever.
I have tried removing #include "Mob.h" altogether and sticking with just the forward declaration, but that doesn't work either - I get only one error, again:
error: invalid use of incomplete type 'struct Mob'
This is confusing. I've successfully gotten classes to inherit before, and this code seems analogous in all relevant ways to my previous successful attempts.
EDIT: Here are the contents of Mob.h
#ifndef MOB_H_INCLUDED
#define MOB_H_INCLUDED
#include <SFML/Graphics.hpp>
#include <cstdlib>
#include "Level.h"
class Level;
class Mob
{
public:
//Member functions.
Mob(Level* level, int x, int y);
float GetX();
float GetY();
void SetColor(sf::Color color);
void virtual GameCycle(sf::RenderWindow* App) = 0;
void virtual Die() = 0;
void Draw(sf::RenderWindow* App);
protected:
float m_X;
float m_Y;
bool m_Moving;
int m_Health;
sf::Sprite m_Sprite;
Level* pLevel;
};
#endif // MOB_H_INCLUDED
EDIT: Here are the contents of the "Level.h" file. Note that Baby is a child class of Mob in much the same way as Herder; both experience the same errors.
#ifndef LEVEL_H_INCLUDED
#define LEVEL_H_INCLUDED
#include <SFML/Graphics.hpp>
#include <cstdlib>
#include "Tile.h"
#include "Herder.h"
#include "Baby.h"
class Tile;
class Herder;
class Baby;
/// LEVEL
/// This is the collection of all data regarding a level, including layout, objects, mobs, and story elements.
///
class Level
{
public:
//Constructor
Level(int height, int width, std::string name);
//For obtaining positional data
int GetHeight();
int GetWidth();
std::string GetName();
sf::Image GetTileImage(int image);
sf::Image GetMobImage(int image);
std::vector< std::vector<Tile> >& GetGrid();
void NewHerder(int x, int y);
void NewBaby(int x, int y);
void GameCycle(sf::RenderWindow* App);
void GraphicsCycle(sf::RenderWindow* App);
private:
//Size
int m_Height;
int m_Width;
//Spatial coords
std::string m_Name;
//The grid of tiles.
std::vector< std::vector<Tile> > m_Grid;
//A vector of the images to be used for tiles.
std::vector<sf::Image> m_TileImages;
//A vector of the images to be used for tiles.
std::vector<sf::Image> m_MobImages;
//The herders
std::vector<Herder> m_Herders;
//The babies
std::vector<Baby> m_Babies;
};
#endif // LEVEL_H_INCLUDED
EDIT: Pre-emptively, here are the contents of Tile.h:
#ifndef TILE_H_INCLUDED
#define TILE_H_INCLUDED
#include <SFML/Graphics.hpp>
#include <cstdlib>
#include "Level.h"
class Level;
/// TILE
/// This is the basic environmental unit in the game
///
class Tile
{
public:
//Constructor
Tile(int col, int row, int size, int type, Level* level);
//For obtaining positional data
int GetX();
int GetY();
int GetRow();
int GetCol();
//For obtaining type data
int GetType();
//For obtaining string type data
std::string GetStringType();
//For changing type data
void SetType(int type);
void SetStringType(std::string character);
//For activities that regularly take place
void GameCycle();
//Draws the tile.
void Draw(sf::RenderWindow* App);
private:
//The level this tile belongs to.
Level* m_Level;
//Size (it's a square!)
int m_Size;
//Spatial coords
int m_X;
int m_Y;
//Grid coords
int m_Row;
int m_Col;
//Type
int m_Type;
//Visual data
sf::Sprite m_Tile;
};
#endif // TILE_H_INCLUDED
It is a cyclic dependency (Herder.h includes Level.h which includes Herder.h, etc.).
In Herder.h, simply replace this :
#include "Level.h"
with :
class Level;
and do the same in Mob.h
The general rule is to include as little header files as possible (ie. only the ones you need). If you can get by with a forward declaration eg., then use that rather than a full include.
The problem you have is a cyclic dependency which is a code smell. On the one side, to be able to derive from a type, the base definition must be available to the compiler (i.e. the compiler requires a fully defined type from which to inherit). On the other hand your base class depends on the derived class.
The technical answer is to forward declare the derived type (so that you can define the base), and then define the base. But you should really think on what you are doing: why are those two separate types related by inheritance? Why not one? Or three (split responsibilities)? If the base depends on the derived for it's own interface, that seems to indicate that they are too highly coupled. Rethink the design.
"Herder.h" and "Level.h" are #include in each other. So, I think this error is coming from the "Herder.h" which is included first. It's becoming cyclic. Remove that and see if the error goes away.