I want to access the variables from inherited classes. However, the compiler gives the error:furniture.cpp:55:9: error: 'int stool::n_StoolLegs' is private within this context one.n_StoolLegs -1;.
This is a homework assignment however, the assignment says that I need to use 4 variables of type stool. So I inherited the class. Is there maybe another option to modify to modify the inherited variables?
furniture .hpp
#include <ostream>
#include <string>
#ifndef FURNIURE_HPP
#define FURNITURE_HPP
class stool{
private:
int n_StoolLegs;
int n_seats;
public:
void setStoolLegs(int);
int getStoolLegs();
void setSeats(int);
int getSeats();
};
class table {};//not relevant
class furniture: public stool, public table
{
private:
stool one;
stool two;
stool three;
stool four;
table first;
public:
furniture(){
one.setStoolLegs(4);
one.setSeats(1);
void makeMoreHipster();
};
#endif
furniture.ccp:
#include <iostream>
#include "furniture.hpp"
//begin stool
void stool::setStoolLegs (int nLegs){
n_StoolLegs = nLegs;
};
int stool::getStoolLegs(){
return n_StoolLegs;
};
void stool::setSeats (int nSeats){
n_seats = nSeats;
};
int stool::getSeats(){
return n_seats;
};
//end stool//
// begin table
//not relevant
// end table
//start furniture
void furniture::makeMoreHipster(){
one.n_StoolLegs -1;
};
// end furniture//
With inheritance, private variables are not accessible.
Use protected.
I checked several answers on the forums about this topic, but for some reason I still cannot wrap my mind about the problem and get my works running.
My aim is to have one object of a class available in all translation units. Note, I do not seek to implement a singleton pattern here. There can be multiple instances of the class, but there will always be at least one and this one can be seen where "its header" is included.
Assume a design like this:
---logging.h---
class LogCenter {
...
}
class Logger {
private:
LogCenter& center;
public:
Logger(); //automatically assigns the ominous global LogCenter object (reference) to center.
Logger(LogCenter&); //however, any other LogCenter object would work equally fine.
}
The reason? I want that all Loggers can use this global LogCenter per default, wherever they may be used.
But now I'm unsure how to provide this global LogCenter. It has the default constructor. Do I just add a line extern LogCenter globalCenter; into the logging.h file and another LogCenter globalCenter; line into the logging.cpp file? Or just LogCenter globalCenter; in the logging.cpp and extern LogCenter globalCenter; in any file that uses it?
I am really confused, none of which I tried worked - however, the overall code works fine when I use the constructor overload with its own LogCenter instance.
EDIT: Important: extern goes with declaration (e.g. in header file). Then one single definition in an implementation file.
Check all the answers!
This is how it works:
---logging.h---
class Entry;
class LogCenter {
friend class Logger; //please don't bash my friend design right away... D:
private:
list<Entry> entries;
public:
void printLog(string file);
}
extern LogCenter SCenter;
class Logger {
private:
LogCenter& center;
public:
Logger(); //uses extern or "singleton" object.
Logger(LogCenter&);
void commitEntry(Entry); //adds the Entry object to the list in the center object.
}
-----------------
---logging.cpp---
#include "logging.h"
LogCenter SCenter;
void Logger::commitEntry(Entry e) {
entries.push_back(e); //Logger can access LogCenter fields!
}
void LogCenter::printLog(string file) {
//open file stream str
for(list<Entry>::iterator it = entries.begin();...)
str << it->getEntry() << endl;
//close file
}
--------------
---main.cpp---
#include "logging.h"
int main() {
Logger log;
Entry e("Some entry");
log.commitEntry(e);
SCenter.printLog("filename.log");
//or
LogCenter cent;
Logger log(cent);
Entry e("some entry");
log.commitEntry(e);
cent.printLog("filename.log");
return 0;
}
-------------
Using an extern variable is one option.
Another option is to have a function that returns a reference.
logging.h:
LogCenter& getGlobalLogCenter();
logging.cpp:
LogCenter& getGlobalLogCenter()
{
static LogCenter lc;
return lc;
}
//logcenter.h
#ifndef LOGCENTER_H_
#define LOGCENTER_H_
class LogCenter {
private:
int dummy;
public:
int getVal(){ return dummy; };
LogCenter() : dummy(0){};
LogCenter(int val) : dummy(val) {};
};
#endif // LOGCENTER_H_
xxx
// logcenter.cpp
#include "LogCenter.h"
LogCenter globalCenter;
xxx
//logger.h
#ifndef LOGGER_H_
#define LOGGER_H_
#include <string>
#include "LogCenter.h"
class Logger {
private:
LogCenter& center;
public:
Logger(); //automatically assigns the ominous global LogCenter object (reference) to center.
Logger(LogCenter&); //however, any other LogCenter object would work equally fine.
std::string print() { return std::string("This class uses logger ") + std::to_string(center.getVal()); };
};
#endif // LOGCENTER_H
xxx
// logger.cpp
#include "Logger.h"
extern LogCenter globalCenter;
Logger::Logger() : center(globalCenter) {};
Logger::Logger(LogCenter &logcenter) : center(logcenter) {};
xxx
// main.cpp
#include "Logger.h"
int main(int argc, char* argv[])
{
LogCenter logcenter2(2), logcenter3(3);
Logger logger1, logger2(logcenter2), logger3(logcenter3);
std::cout << logger1.print() << std::endl;
std::cout << logger2.print() << std::endl;
std::cout << logger3.print() << std::endl;
return 0;
}
output is:
This class uses logger 0
This class uses logger 2
This class uses logger 3
I recommend you to use the following C++ singleton pattern which is easy to use and even safe when using it across shared libraries:
// LogCenter.h
class /*API_MACRO_FOR_EXPORTING*/ LogCenter {
public:
static LogCenter* instance();
}
// For quick access you could define a macro
#define sLogCenter \
LogCenter::instance()
// LogCenter.cpp
LogCenter* LogCenter::instance()
{
static LogCenter instance;
return &instance;
}
// LogCenter::instance()->DoSomething();
// sLogCenter->DoSomething();
To answer your question about extern:
// LogCenter.h
// You can use multiple definitions with extern so the compiler
// knows the LogCenter is instantiated somewhere else.
extern LogCenter globalCenter;
// LogCenter.cpp
// Only 1 declaration of LogCenter
/*API_MACRO_FOR_EXPORTING*/ LogCenter globalCenter;
I would go with the second option, that is, "extern LogCenter globalCenter;" in the file where ever it is used.
The reason, if someone is including logging.h, may be for creating the new object of Logcenter class, but does not intend to use the globalCenter object, then why he needs the extern declaration for globalCenter object.
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 }
I have been trying to make a game engine for some time, and for the most part it has been turning out quite well, considering it's the first one i've made. But when I started to make an event send/recieve system with derived classes contained in a base class pointer vector array, I had some trouble making the reciever get the class type and use the proper function; here's what I have:
This is my base class Object:
object.h:
#include "all.h" //Contains '#include "SDL/SDL.h"' and constant variables.
#include <vector>
#include "mask.h" //An unimportant class used for collision checking
class Body;
class Room;
class Object//Objects that belong here are those without step events.
{
public:
vector<vector<Room> > *world_map;//Should hold the address of the world map.
Room *room;//The room holding this object.
unsigned int x;
unsigned int y;
unsigned int pos;//Position of the object in the room's list.
int depth;//The deeper it is, the later it will be drawn.
virtual void draw(SDL_Surface *buffer,int viewx, int viewy){}
virtual void interact(Body *body);//Sends a pointer of this object to the
//the obj_event function of the body calling it.
Object(unsigned int xx=0, unsigned int yy=0,int d=0):x(xx),y(yy),depth(d){}
};
#endif // INSTANCE_H_INCLUDED
object.cpp:
#include "object.h"
#include "body.h"
void Object::interact(Body *body)
{
body->obj_event(this);
}
This is my derived class Body:
body.h:
#ifndef BODY_H_INCLUDED
#define BODY_H_INCLUDED
#include "all.h"
#include "object.h"
class Entity;
class Enemy;
class Player;
class Body : public Object//Objects that belong here are those with step events.
{
public:
int priority;//Decides which body will perform their step event first.
virtual void step()=0;
Body(int xx=0, int yy=0, int d=0, int p=0):Object(xx,yy,d),priority(p){}
//These scripts are for handling objects and bodies it has called through
//interact()
virtual void obj_event(Object *object){}
virtual void obj_event(Entity *entity){}
virtual void obj_event(Enemy *enemy){}
virtual void obj_event(Player *player){}
};
#endif // BODY_H_INCLUDED
there is no body.cpp
This is my derived class of Body, Entity:
entity.h:
#ifndef ENTITY_H_INCLUDED
#define ENTITY_H_INCLUDED
#include "all.h"
#include "body.h"
#include "items.h"
#include <vector>
#include "mask.h"
class Entity : public Body
{
public:
vector<Item> inv;
unsigned int width;
unsigned int height;
Mask mask;
Entity(int xx,int yy,int w,int h,int d=0,int p=0);
void step();
void collide_action(Entity *entity);
virtual void obj_event(Player *player);
virtual void obj_event(Enemy *enemy);
};
#endif // ENTITY_H_INCLUDED
entity.cpp:
#include "entity.h"
#include "room.h"
#include "player.h"
#include "enemy.h"
Entity::Entity(int xx,int yy,int w,int h,int d,int p):Body(xx,yy,d,p),width(w),height(h),mask(xx,yy,w,h,m_rectangle)
{}
void Entity::step()
{
for(int iii=0;iii<room->inv.size();iii++)//Iterates through objects
{
room->inv[iii]->interact(this);
mask.update(x,y,width,height);
}
for(int iii=0;iii<room->index.size();iii++)//Iterates through bodies
{
room->index[iii]->interact(this);
mask.update(x,y,width,height);
}
}
void Entity::collide_action(Entity *entity)
{
if(entity!=this)
{
if (mask_collide(mask,entity->mask))
{
short xchange;
short ychange;
if (entity->x<x)
{
xchange=width-(x-entity->x);
}
else
{
xchange=(entity->x-x)-width;
}
if (entity->y<y)
{
ychange=height-(y-entity->y);
}
else
{
ychange=(entity->y-y)-height;
}
if(abs(xchange)<abs(ychange))
x+=xchange;
else
y+=ychange;
}
}
}
void Entity::obj_event(Player *player)
{
collide_action(player);
}
void Entity::obj_event(Enemy *enemy)
{
collide_action(enemy);
}
This is my derived class of Entity, Player:
player.h:
#ifndef PLAYER_H_INCLUDED
#define PLAYER_H_INCLUDED
#include "all.h"
#include "body.h"
#include "items.h"
#include <vector>
#include "mask.h"
#include "entity.h"
enum keylist
{
kl_left=0,
kl_up=1,
kl_right=2,
kl_down=3,
};
class Player : public Entity
{
public:
SDLKey keys[4]; //List of action's corresponding keys.
Player(int xx,int yy,int w,int h,int d=0,int p=0);
void step();
void draw(SDL_Surface *buffer,int viewx,int viewy);
void interact(Body *body);
};
#endif // PLAYER_H_INCLUDED
player.cpp:
#include "player.h"
#include "room.h"
Player::Player(int xx,int yy,int ww,int hh,int dd,int pp):Entity(xx,yy,ww,hh,dd,pp)
{
//Default keys, can be changed.
keys[kl_left]=SDLK_LEFT;
keys[kl_up]=SDLK_UP;
keys[kl_right]=SDLK_RIGHT;
keys[kl_down]=SDLK_DOWN;
}
void Player::step()
{
Uint8 *key=SDL_GetKeyState(NULL);
if (key[keys[kl_left]])
x-=1;
if (key[keys[kl_right]])
x+=1;
if (key[keys[kl_up]])
y-=1;
if (key[keys[kl_down]])
y+=1;
mask.update(x,y,width,height);
Entity::step();
}
void Player::draw(SDL_Surface *buffer,int viewx,int viewy)
{
FillRect(buffer,x-viewx,y-viewy,width,height,0xFF0000);
}
void Player::interact(Body *body){body->obj_event(this);}
I have another class Enemy, but it's pretty much exactly like player (without the keyboard controls).
Now here's my problem (not error), for every object I want any body to perform an event for, I need to make virtual functions of ALL of them in this base class, that way if any object calls body->obj_event(this), it will pick the proper function with the most derived argument.
For example, if Player called object->interact(this) of an enemy, the enemy would first use it's base class Object's virtual function interact(Body*), which would then check the derived classes if they have an identical function (which enemy does), and then enemy calls body->obj_event(this) of the player body through it's base class, Body. The player body would then first use it's base class Body's virtual function obj_event(Enemy*), which would then check the derived classes if they have an identical function (which Entity does), and then Entity executes obj_event(Enemy*). At least that's how I understand it.
What I'd like to have is a way for any derived class to call interact of any other derived class through it's base function, and would then have it call it's obj_event function for the derived class, without having to have any of the Base classes know about their derived classes.
As I mentioned, this is my first time making an engine, and I'm probably using methods that are completely hectic and error-prone. I was thinking that templates might be able to help out in this situation, but don't know how to implement them.
I have a class that contain two private int , one is const (m_id) and the other one is static (next_id).
I want to set m_id to next_id and increment next_id each time I create an object of the class.
But since it's a const I can't set it like that :
Class::Class()
{
m_id = next_id++;
}
I need to set it like that
Class::Class() :m_id(next_id)
{
next_id++;
}
But that's not good either because I can't access private static like that.
Someone told me that const is not intented to be used for that, so to simply remove it. Is that really the only solution?
edit : here the full header and source
header
#ifndef ENTITY_H_LEA12OED
#define ENTITY_H_LEA12OED
#include "EntityKey.h"
#include "ComponentManager.h"
class Entity
{
public:
Entity ();
virtual ~Entity ();
private:
ekey m_key;
ComponentManager m_componentManager;
const int m_id;
static int next_id;
};
#endif /* end of include guard: ENTITY_H_LEA12OED */
source
#include "Entity.h"
Entity::Entity() :m_id(next_id++)
{
}
Entity::~Entity()
{
}
(of course EntityKey and ComponentManager doesn't have anything to do with my question)
(edit 2: corrected some errors in the code due to testing)
You need to define next_id, or else it will compile, but not link. Like so:
class Class
{
/* whatever */
};
Class::Class() :m_id(next_id++)
{
/* whatever */
}
int Class::next_id = 0;