I want to separate Game class into header and source. To do that I need to be able to define the functions outside the class, but, strangely, I can't!
main.cpp
#include "app.hpp"
int main ()
{
Game game(640, 480, "Snake");
game.run();
return 0;
}
app.hpp
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
class App
{
friend class Game;
public:
App(const int X, const int Y, const char* NAME);
void run(void);
private: // Variables
sf::RenderWindow window;
sf::Event event;
sf::Keyboard kboard;
};
#include "game.hpp"
And now the question part.
game.hpp.
class Game // this snippet works perfectly
{
public:
Game(const int X, const int Y, const char* TITLE) : app(X, Y, TITLE)
{ /* and the initialization of the Game class itself... */}
void run()
{ app.run(); /* And the running process of Game class itself*/};
private:
App app;
};
class Game // this snippet produces compiler errors of multiple definitions...
{
public:
Game(const int X, const int Y, const char* TITLE);
void run();
private:
App app;
};
Game::Game(const int X, const int Y, const char* TITLE) : app(X, Y, TITLE) {}
void Game::run() { app.run(); } // <<< Multiple definitions ^^^
Why?
What is the reasoning for the multiple definitions error?
Because you are defining the functions in the header file and when you include the header in translation units a copy of the function is created in each translation unit, thus leading to multiple definitions and violation of one definition rule.
What is the solution?
You can define the functions separately but in a cpp file. You declare functions in header file and define them in source cpp file.
Why first example works?
The only standard compliant way to bypass one definition rule is to use inline functions. When you define the functions inside the class body, they are implicitly inline and the program can successfully bypass one definition rule and the multiple definition linking error.
Because you're defining class Game twice.
Here's how you lay out the separation:
Class.hpp
class Class
{
public:
Class();
void foo();
};
Class.cpp
Class::Class() { //Do some stuff}
void Class::foo() { //Do other stuff }
Related
I'm new to C++ and to practice I decided to write a simple console game. I originally wrote it all in the main.cpp file, but now I've decided to split all the classes up to make it simpler to read. I looked up a few tutorials on how to correctly do this but I seem to have run into an error that I haven't been able to find a solution to.
Here is a base class for a "block". Blocks of different textures inherit from this base block.
This is the code for the header file:
#pragma once
#include <iostream>
class BaseBlock { //Base block class
private:
int PosX, PosY;
protected:
std::string Appearance;
bool IsActive;
public:
BaseBlock(int x, int y);
virtual inline int getX();
virtual inline int getY();
virtual inline bool getIsActive();
virtual inline std::string getAppearance();
virtual inline void setActive(bool isactive);
};
Here is its .cpp file:
#include "clsBaseBlock.h"
BaseBlock::BaseBlock(int x, int y) {
PosX = x;
PosY = y;
Appearance = ' ';
IsActive = false;
}
inline int BaseBlock::getX() { return PosX; }
inline int BaseBlock::getY() { return PosY; }
inline bool BaseBlock::getIsActive() { return IsActive; }
inline std::string BaseBlock::getAppearance() { return Appearance; }
inline void BaseBlock::setActive(bool isactive) { IsActive = isactive; }
Here is the code for the header of one of the derived classes:
#pragma once
#include "clsBaseBlock.h"
class BlockWeak : public BaseBlock { // Third derived block class
public:
BlockWeak(int x, int y) : BaseBlock(x, y) {} //Here is the inheritance
};
Here is its .cpp file:
#include "clsBlockWeak.h"
BlockWeak::BlockWeak(int x, int y): BaseBlock(x,y){
Appearance = "\xB1";
IsActive = true;
}
From this code I get all sorts of errors in the header file of the derived classes like:
-syntax error : 'symbol' : expected member function definition to end with '}'
-trailing 'char' illegal in base/member initializer list
Then in the .cpp file I get:
-type "int" unexpected
-unexpected end of file found
Any information on how to correct my code would be much appreciated.
BlockWeak(int x, int y) : BaseBlock(x, y) {} //Here is the inheritance
No, it's not. Here is the inheritance:
class BlockWeak : public BaseBlock
The following is a full definition of a constructor, which you have also provided in the .cpp file thus potentially breaking the One Definition Rule
BlockWeak(int x, int y) : BaseBlock(x, y) {}
You should probably remove the part starting from :, including the {} and move those into the definition
So I am trying to implement a program that has a scoreboard and two players, I am trying to make it so that the two players share a scoreboard using the singleton pattern. However when I try to use methods on the global scoreboard defined in the player classes I always get a "run failed" message.
These are my two header files, I can provide the full implementation if it's necessary.
#ifndef PLAYER_H
#define PLAYER_H
#include "scoreboard.h"
#include <string>
#include <fstream>
class Player{
private:
std::ifstream file1;
std::ifstream file2;
static Scoreboard* _game;
public:
static Scoreboard* Game();
void makeMove(const char,const std::string);
};
#endif
#ifndef SCOREBOARD_H
#define SCOREBOARD_H
class Scoreboard{
private:
int aWin;
int bWin;
int LIMIT;
int curCounter;
public:
void resetWins();
void addWin(char);
void makeMove(const int, char);
void startGame(const int, const int);
int getWin(char);
int getTotal();
int getLimit();
};
#endif /* SCOREBOARD_H */
in player.cc
Scoreboard* Player::_game = 0;
Scoreboard* Player::Game(){
if (_game = 0)
{
_game = new Scoreboard;
_game->resetWins();
}
return _game;
}
Along with the makeMove method
Your Scoreboard instance does not need to be a pointer:
static Scoreboard _game;
// ...
static Scoreboard& Game() { return _game; }
Or alternatively, just leave out the class declaration of _game:
// you can either make this function static or non-static
Scoreboard& Game()
{
static Scoreboard game; // but this variable MUST be static
return game;
}
That will do the same thing without the memory management issues.
This will create a single instance of Scoreboard for all Players. If you only ever wanted to have a single instance of Scoreboard (e.g. if you had a Referees class that needed to see the scoreboard as well), you would modify your scoreboard class:
class Scoreboard
{
private:
// all your data members
Scoreboard() {} // your default constructor - note that it is private!
public:
// other methods
Scoreboard& getInstance()
{
static Scoreboard instance;
return instance;
}
};
Then, to access it in your other classes, you would include the scoreboard header and use it as:
#include "Scoreboard.h"
void my_func()
{
Scoreboard& scoreboard = Scoreboard::getInstance();
scoreboard.DoSomething();
}
In Player::Game, you have written
if (_game = 0)
that is setting _game = 0 and evaluating to false, so that you don't actually create the scoreboard. Change it for:
if (_game == 0)
I can't seem to find the answer but maybe I'm searching the wrong terminology. I am not finding the answer I am looking for in the hits.
I have a bunch of derived classes for a menu system.
I have a CControl derived class that is parent of a CEditBox and a CLabel class. CLabel is nothing more than attaching the text onto an SDL_Surface and then binding it to a texture for openGL to render. CEditBox would be a field for displaying text or gathering text from users like a password box. Obviously, CEditBox could make use of a label for handling the text rendering inside the box. CControl is derived from CComponent.
I cannot declare CLabel inside CEditBox unless I include CLabel in the header but I think I keep getting linker errors doing that even though I have all of my headers wrapped in #ifndef #define class #endif syntax but I'm also a noob. Instead, I have a CComponent* pointer declared since they are derived from that class.
Fine. Now in the constructor for the CEditBox I have:
#include "CLabel.h" //include in .CPP is fine I reckon.
CEditBox::CEditBox() {
CLabel Field; //Create CLabel
InputType = ALL; //Not important for my question related to allowed symbols
Label = &Field; //CComponent pointer to CLabel
}
When this constructor function returns, wouldn't CLabel go out of scope, and thus Feild would be destroyed and now my pointer is pointing at an undefined block of memory? What would be an appropriate way to do this? Is there a better solution?
Thank you
Linker problem
I don't know that the problem exists anymore, but some think this is a more important issue. Well here is the actual code now and you guys can tell me if you think it is done incorrectly.
Base Class CMenuObject
#ifndef _CMENUOBJECT_H_
#define _CMENUOBJECT_H_
class CMenuObject {
protected:
const char* ClassName;
public:
CMenuObject();
virtual const char* Object();
};
#endif
Next Class is CComponent
#ifndef _CCOMPONENT_H_
#define _CCOMPONENT_H_
#include "CMenuObject.h"
class CComponent : public CMenuObject {
protected:
const char* _Name;
int _Tag;
static int _ComponentCount;
static int _IDCount;
public:
CComponent();
virtual const char* Name();
virtual int Tag();
virtual void Tag(int t);
};
#endif
Then comes CControl These would be objects that users would interact with or in some way need control the display (i.e. a timer doesn't need user input) and is a mammoth. Don't mind the function pointer stuff because I have no idea what i'm doing with that yet.. this is my first guess approach to handling events. I think it's limiting because I can't figure out what to do if the function needs to take a parameter but I may not have to, etc... We can gloss over this detail for now.
#ifndef _CCONTROL_H_
#define _CCONTROL_H_
#include "CComponent.h"
class CControl : public CComponent {
protected:
int _X,_Y,_Width,_Height;
float R,G,B,A;
void (*OnClk)();
void (*OnDblClk)();
void (*OnMOver)();
void (*OnMHover)();
void (*OnKDown)();
void (*OnKUp)();
void (*OnFcs)();
bool Visible;
CComponent* Pappy;
public:
CControl();
//Render Control
virtual void Show(); // Show Component
virtual void Hide(); // Hide Component
virtual void OnRender(); // Render Component
virtual bool IsVisible(); // Get Current Visibility Status
//Paramater Control
//Write
virtual void X(int x); // Set Component's X coordinate
virtual void Y(int y); // Set Component's Y coordinate
virtual void Width(int w); // Set Component's Width
virtual void Height(int h); // Set Component's Height
//Read
virtual int X(); // Get Component's X coordinate
virtual int Y(); // Get Component's Y coordinate
virtual int Width(); // Get Component's Width
virtual int Height(); // Get Component's Height
//Display Control
virtual void Color(float r, float g, float b); // Set Color of Component- Multicolored objects, this will be the base or bkg color. Makes alpha 1.0f.
virtual void Color(float r, float g, float b, float a); // Same as above but allows for input of an alpha value.
//Font Control
virtual void FontName(const char* font); // Name of font to use
virtual void FontSize(int pt); // Pt size of font. Or maybe pixel, no idea.
virtual void Text(const char* msg); // Text message to render
//Read
virtual const char* Text(); // Read Text Message
//Interactive Control // These will register call back functions for user events
virtual void OnClick(void (*func)()); // On Single Click
virtual void OnDoubleClick(void (*func)()); // On Double Click
virtual void OnMouseOver(void (*func)()); // On Mouse Over
virtual void OnMouseHover(void (*func)()); // On Mouse Hover
virtual void OnKeyDown(void (*func)()); // On Key Down
virtual void OnKeyUp(void (*func)()); // On Key Up
virtual void OnFocus(void (*func)()); // On Focus
//Other
virtual void Parent(CComponent); // Set Parent
virtual CComponent* Parent(); // Get Parent
};
#endif
Finally my end game headers of CLabel and CEditBox.
#ifndef _CLABEL_H_
#define _CLABEL_H_
#include "CTexture.h"
#include "CFont.h"
#include "CControl.h"
class CLabel : public CControl {
private:
const char* vText;
CFont Font;
CTexture Text_Font;
SDL_Surface* Surf_Text;
int X,Y,vWidth,vHeight;
public:
CLabel();
CLabel(const char* text);
virtual void OnRender();
virtual void OnCleanup();
virtual void Text(const char* msg);
virtual const char* Text();
virtual void FontName(const char* fname);
virtual void FontSize(int pt);
virtual void FontColor(float r, float g, float b);
};
#endif
AND
#ifndef _CEDITBOX_H_
#define _CEDITBOX_H_
#include "CControl.h"
class CEditBox : public CControl {
protected:
CComponent* Label;
int InputType;
public:
CEditBox();
~CEditBox();
virtual void OnRender();
//virtual void OnCleanup();
virtual void OnLoop();
virtual void Text(const char* msg);
virtual const char* Text();
virtual void FontColor(float r, float g, float b);
virtual void OnClick(void (*func)()); // On Single Click
virtual void OnDoubleClick(void (*func)()); // On Double Click
virtual void OnMouseOver(void (*func)()); // On Mouse Over
virtual void OnMouseHover(void (*func)()); // On Mouse Hover
virtual void OnKeyDown(void (*func)()); // On Key Down
virtual void OnKeyUp(void (*func)()); // On Key Up
virtual void OnFocus(void (*func)()); // On Focus
enum {
ALL = 0, //abcdefghijklmnopqrstuvwxyz (and caps) 1234567890!##$%^&*()_+-=[]{}<>\/|"';:,.?
ALPHA_NUMERIC, //abcdefghijklmnopqrstuvwxyz (and caps) 1234567890
ALPHA, //abcdefghijklmnopqrstuvwxyz (and caps)
NUMERIC, //1234567890
PASSWORD, //abcdefghijklmnopqrstuvwxyz (and caps) 1234567890!##$%&. -- Render as *
IP //1234567890 . Maybe fix feild width and force xxx.xxx.xxx.xxx format.
};
};
#endif
[SOLVED]
Today, I found the one dang header not wrapped in #ifndef #define #endif. (it was CTexture which gets called again in CFont. Anyway, the restructure was also incredibly beneficial because I've figured out how to use inheritance and base class pointers, and how derived classes can work with each other. Not to mention many many more things. :)
The route I'm taking for derived class interplay is using a base class pointer that can access the derived classes functions via virtual functions. I use new and delete because that's what I am comfortable with. For everyone that contributed, thank you! They are all good answers.
Stereo typical approaches would be:
the pimpl idiom (Why should the "PIMPL" idiom be used?)
using unique_ptr (Rule of Zero)
Showing the second approach:
//////////// CEditBox.hpp header file
#include <memory>
#include <string>
class CLabel; // forward declaration
class CEditBox
{
public:
CEditBox(std::string const&);
private:
std::unique_ptr<CLabel> _label;
};
The forward declaration avoids the need to include CLabel.hpp. The unique_ptr manages the lifetime _label so we don't have to remember to delete it.
//////////// CLabel.hpp header file
#include <string>
#include "CLabel.hpp"
class CLabel
{
public:
CLabel(std::string const& name)
: _name(name)
{
}
private:
std::string _name;
};
Just a sample, nothing to see here. Let's move on:
///////////// CEditBox.cpp source file
#include "CEditBox.hpp"
#include "CLabel.hpp"
CEditBox::CEditBox(std::string const& name)
: _label(new CLabel(name))
{
}
That's the magic: we integrate it all by include CLabel.hpp as well, and construct it in the initializer list.
///////////// main.cpp source file
#include "CEditBox.hpp"
int main()
{
CEditBox box("Hello world"); // no need to 'know' CLabel here
}
Proof of the pudding is in the compilation: http://ideone.com/zFrJa8
Your thinking is on the correct track. The right approach would be allocating this object dynamically, i.e.
Label = new CLabel;
Don't forget to free memory in destructor:
delete Label;
If I understand your problem correctly, you have two classes which have member variables with each other's class?
For instance:
// A.h
#ifndef A_H
#define A_H
#include "B.h"
class A {
public:
...
private:
B* pB;
};
#endif // A_H
And:
// B.h
#ifndef B_H
#define B_H
#include "A.h"
class B {
public:
...
private:
A* pA;
};
#endif // B_H
And compiling these together causes some form of linker error? If this is the case you can circumvent this by forward declaring the class, so instead of including A.h and B.h you simple write class B; above your declaration of class A and class A; above your declaration of class B, then include the headers in your cpp files. So A.h would look like:
// A.h
#ifndef A_H
#define A_H
class B;
class A {
public:
...
private:
B* pB;
};
#endif // A_H
CLabel Field; should be a member of CEditBox. The real question is the one where you mention 'linker errors' (or whatever it is). That's the problem you should be solving.
I suspect this is a very minor issue, but I have spent several hours trying to fix it and have not found anything.
In Game.h (a header file), I have the following:
#pragma once
#include "PlayEngine.h"
class Game {
public:
int Init();
int Run();
int Shutdown();
private:
enum State { ST_MENU, ST_PLAYING } state;
PlayEngine* playengine_;
};
The compiler throws a syntax error on PlayEngine* playengine_, complaining that there is a missing ; before the *. PlayEngine is a class I have defined in other places.
What am I missing?
Replace
#include "PlayEngine.h"
with
class PlayEngine;
A declaration is enough for this case. (and I'm betting the source is a circular inclusion)
Remove state at the end of your enum declaration. and declare the variable separate.
#pragma once
#include "PlayEngine.h"
class Game {
public:
int Init();
int Run();
int Shutdown();
private:
enum State { ST_MENU, ST_PLAYING };
State state;
PlayEngine* playengine_;
};
I tried to look at the similar problems listed here on Stackoverflow and on Google but they deal mostly with templates and that's not my case. I'm using GCC 4.4.5 on Debian Testing 64bit.
So, I have two classes - CEntity:
#ifndef CENTITY_H_INCLUDED
#define CENTITY_H_INCLUDED
#include "global_includes.h"
// game
#include "CAnimation.h"
#include "Vars.h"
#include "vector2f.h"
#include "Utils.h"
class CAnimation;
class CEntity
{
public:
CEntity();
virtual ~CEntity();
void _update(Uint32 dt);
void updateAnimation(Uint32 dt);
void addAnimation(const std::string& name, CAnimation* anim);
void addAnimation(const std::string& name, const CAnimation& anim);
void removeAnimation(const std::string& name);
void clearAnimations();
bool setAnimation(const std::string& name);
SDL_Surface* getImage() const;
const vector2f& getPos() const;
const vector2f& getLastPos() const;
F getX() const;
F getY() const;
F getLastX() const;
F getLastY() const;
SDL_Rect* getHitbox() const;
SDL_Rect* getRect() const;
F getXSpeed() const;
F getYSpeed() const;
void setPos(const vector2f& pos);
void setPos(F x, F y);
void setPos(F n);
void setX(F x);
void setY(F y);
void setHitboxSize(int w, int h);
void setHitboxSize(SDL_Rect* rect);
void setHitboxWidth(int w);
void setHitboxHeight(int h);
void setSpeed(F xSpeed, F ySpeed);
void setXSpeed(F xSpeed);
void setYSpeed(F ySpeed);
void stop();
void stopX();
void stopY();
void affectByGravity(bool affect);
void translate(const vector2f& offset);
void translate(F x, F y);
bool collide(CEntity& s);
bool collide(CEntity* s);
protected:
CAnimation* mCurrentAnimation;
SDL_Surface* mImage;
vector2f mPos;
vector2f mLastPos;
SDL_Rect* mHitbox; // used for collisions
SDL_Rect* mRect; // used only for blitting
F mXSpeed;
F mYSpeed;
bool mAffByGrav;
int mHOffset;
int mVOffset;
private:
std::map<std::string, CAnimation*> mAnims;
};
#endif // CENTITY_H_INCLUDED
and CPlayerChar which inherits from CEntity:
#ifndef CPLAYERCHAR_H_INCLUDED
#define CPLAYERCHAR_H_INCLUDED
#include "global_includes.h"
// game
#include "CEntity.h"
class CEntity;
class CPlayerChar : public CEntity
{
public:
CPlayerChar();
virtual ~CPlayerChar();
virtual void update(Uint32 dt) = 0;
virtual void runLeft() = 0;
virtual void runRight() = 0;
virtual void stopRunLeft() = 0;
virtual void stopRunRight() = 0;
virtual void attack() = 0;
virtual void stopAttack() = 0;
virtual void attack2() = 0;
virtual void stopAttack2() = 0;
virtual void ground() = 0;
virtual void midair() = 0;
void jump();
void stopJump();
protected:
// looking right?
bool mRight;
bool mJumping;
bool mOnGround;
bool mGrounded;
};
#endif // CPLAYERCHAR_H_INCLUDED
When I try to compile it, GCC throws this error:
CPlayerChar.h:12: error: invalid use of incomplete type ‘struct CEntity’
CPlayerChar.h:9: error: forward declaration of ‘struct CEntity’
I tried it first without the forward declaration 'class CEntity;' in CPlayerChar.h on line 9, but then it would throw this instead
CPlayerChar.h:12: error: expected class-name before ‘{’ token
So the forward declaration has to be there. Also, CEntity is clearly a class, not a struct.
You have a circular inclusion in your header files.
But without all the header files we will not be able to fix it.
I would start here.
#include "CAnimation.h"
Looking at your header you don't actually need this. You only use CAnimation by reference or pointer so the forward declaration you have should be sufficient. Move the include into the source file (ie out of the header).
The next place I would look is:
#include "global_includes.h"
Any global includes that are included in a header file better be very simple. Should only contain simple types and not include any other header files (unless they are just as simple). Anything complex is going to lead to problems with circular dependencies.
General rule of thumb
A header file should only include header files that it absolutely needs. Otherwise they should be included from the source file. You only absolutely need a header file if it defines a class that is used as a parent class you have members objects of that class, or you use parameter objects of that class.
I use the term object to distinguish from references or pointers. If you are using these you do not need to include the header file. You only need to do a forward declaration.
You probably have got a loop in your includes in such way that CPlayerChar doesnt know who really is CEntity, it just knows that it exists, but doesnt know what is it.
If you remove the "class CEntity" declaration, you will see that GCC will complain that CEntity doesnt exists.
You must check that nothing that CEntity includes include CPlayerChar.
You have to ensure that the full definition of the class CEntity is visible at the point where you define the class CPlayerChar. (So check your inclusions.)
This is because you can only inherit from fully defined classes, but not from just forward-declared ones.
The only time you can get away with forward-declarations in place of full definitions is when you make pointers or references to a type, but only if you never access any of its members, or (thanks to #Alf) when declaring a function with incomplete return type.