Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
As the title says when I run my program, visual studio, give me that error. The class that produce that error is the following:
class UsesScene {
BaseScene & scene;
public:
UsesScene(BaseScene& scene) : scene(scene) {}
void Start() { scene.Start(); }
void EventHandler(SDL_Event ev) { scene.EventHandler(ev); }
void Update() { scene.Update(); }
void Draw(SDL_Renderer* renderer) { scene.Draw(renderer); }
};
The popup appears after } at the end of the initialization of the Start void.
Another code that can interact with these classes is the following:
void GameManager::regScene(UsesScene scene) {
if (display != NULL) {
UsesScene* ptr = &scene;
UsesScene** pptr = &ptr;
display = *pptr;
}
else
{
UsesScene* ptr = &scene;
UsesScene** pptr = &ptr;
buffer = *pptr;
}
}
the display & buffer are declared as
class GameManager
{
private:
SDL_Window* window;
SDL_Renderer* renderer;
UsesScene* display;
UsesScene* buffer;
bool isRunning;
bool reStart;
};
and for access to the display or buffer's parameter I use the following syntax:
display->Start();
and the last thing that has to do with this class is this part of code:
TestScene tScene;
UsesScene testScene(tScene);
this->regScene(testScene);
Test Scene simply extends BaseScene:
class BaseScene
{
private:
bool sceneloop = false;
public:
virtual void Start() { std::cout << "BasceScene::Start()" << std::endl; };
virtual void EventHandler(SDL_Event event) {};
virtual void Update() {};
virtual void Draw(SDL_Renderer* renderer) {};
void _toggleLoopMode() { sceneloop = !sceneloop; }
bool _sceneloop() { return sceneloop; }
};
How I can solve this?
ps:
some code that doesn't interfere with the Display and Buffer wasn't reported, if you need: free to ask
So, after a few hours of coding, thanks to Remy Lebeau, I've finally resolved this issue.
First I've changed the regScene() method and now looks like this:
void GameManager::regScene(UsersScene *scene) {
if (SceneManager::_display == NULL)
_display = scene;
else
_buffer = scene;
}
And then I pass the scene like this:
TestScene tScene;
UsersScene testScene(tScene);
sManager->regScene(&testScene);
Thanks to all.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
Using the example below, I would like to call the function printTop() from my 'Bottom' object. It seems perhaps I could use a pointer to the parent object?
class Bottom {
public:
void printBottom(){std::cout << "print bottom";};
};
class Top {
public:
void printTop(){std::cout << "print top";};
private:
Bottom bottom;
};
Thanks.
If this is truly where your heart is at, it can be done (doesn't mean i'd advocate it):
class Top;
class Bottom {
public:
Bottom( const Top& topLevelObj ) : _topLevelObj(topLevelObj) { }
void printBottom() const {std::cout << "print bottom";};
void printTop() const;
private:
const Top& _topLevelObj;
};
class Top {
public:
Top() : _bottom(*this) {}
void printTop() const {std::cout << "print top";};
private:
Bottom _bottom;
};
void Bottom::printTop() const { _topLevelObj.printTop(); }
Firstly your code will not execute due to an error in your code, figure it out.
Secondly, you cannot call function printTop() from your Bottom object because you have no access to printTop() from the Bottom class.
You could maybe rewrite the code in this way:
class Top {
public:
void printTop(){ std::cout << "print top"; }
};
class Bottom {
public:
void printBottom(){ std::cout << "print bottom"; }
Top top;
};
int main()
{
Bottom B;
B.top.printTop();
return 0;
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I'm writing a cheat for an offline game, and have a class called Player which is responsible for getting and setting values in another process. However, my design for this class is very poor because the use of the class Player looks very messy and ugly, very difficult to read, and maintain
// declare variables here to read
if (Player.getthis() && Player.getthat() && Player.getthat() ... and so on)
//do stuff
class Player {
...
public:
...
// either of these calls can fail, so I return TRUE on success and FALSE on failure
BOOL GetHealth(float& health);
BOOL SetHealth(float& health);
...
};
So my question is, what is a better way of doing this?
Also: I don't necessarily need to read every single value of Player in memory, only a few at a time. That is why I don't have a single method such as BOOL UpdatePlayer() which will read everything and update the player
Here is how I would do it:
class Player {
public:
class AccessException : public std::exception {
friend class Player;
public:
virtual const char *what() const noexcept {
return "Error getting property with key " + key;
}
private:
AccessException(const std::string &key)
: key(key)
{}
std::string key;
};
float GetHealth() {
if (is_error) {
throw AccessException("health");
}
return health;
}
float GetPosX() {
if (is_error) {
throw AccessException("posX");
}
return posX;
}
};
void do_stuff() {
try {
float health = player.GetHealth();
float posX = player.GetPosX();
// Use health and posX...
} catch (const AccessException &ex) {
std::cerr << ex.what() << std::endl;
}
}
I have an array of happy people.
Each happy person has a virtual function called updateHappiness() which is used to update their happiness attribute.
Each person likes their own thing.
Rain lovers are happy persons who really like hearing the sound of the rain and it increases their happiness level. They inherit from the happy person class.
As a consequence, they need to know when it is raining while updating their happiness by overloading the updateHappiness() function with updateHappiness(bool isRaining) as in this post : overload virtual function with different parameters in c++, however, this is a problem because there are many kinds of people and we would like to update them all by calling the same function for every person.
We could have the parameter stored inside of the person class and pass it in the class constructor as in this post : Override number of parameters of pure virtual functions however rain is not a constant state and we would have to call a function updateRainState(bool isRaining) which would cause the same problem as before.
We could pass the parameter bool isRaining to every person even though they don't care about the rain but it would also be a problem because some people like the rain, some people like seeing the daylight, some people like it when their friends are happy... so it would add many useless parameters and it seems like a waste.
Finally, the best solution I could think of is to have a static function in the weather class to get the rain state without passing it as a parameter but it would look like a global variable and some people say that it is really bad!
What would you do to solve this problem ?
Here is an example code of what the classes are like :
class HappyPerson
{
public:
HappyPerson(): m_happinness(0) {}
virtual void updateHappinness() { m_happinness++; }
protected:
int m_happinness;
};
class Weather
{
public:
static int isRaining() { return raining; }
private:
static bool raining;
};
bool Weather::raining(0);
class RainLover : public HappyPerson
{
public:
RainLover() : HappyPerson() {}
void updateHappinness() { m_happinness++; if (Weather::isRaining()) m_happinness++; }
};
int main()
{
std::vector<HappyPerson*> happyPeople;
happyPeople.push_back(new RainLover);
// ... add many other persons
std::vector<HappyPerson*>::iterator it;
for (it = happyPeople.begin(); it != happyPeople.end(); it++)
{
(*it)->updateHappinness();
}
}
You should consider taking a completely different approach - use event callbacks instead.
When something in particular changes, only interested people are affected, so you should not waste time and effect trying to passing around the change to everyone else.
If a person's happiness depends on the Weather, then have the person register for Weather change events.
If a person's happiness depends on another person's happiness, then have the person register for the other person's happiness change events.
And so on.
For example:
class HappyPerson;
class HappinessChangeListener
{
public:
void happinessChanged(HappyPerson *person, bool isHappier) = 0;
};
class HappyPerson
{
public:
HappyPerson();
virtual ~HappyPerson() {}
void updateHappiness(int amount);
void registerHappinessChangeListener(HappinessChangeListener *listener);
void unregisterHappinessChangeListener(HappinessChangeListener *listener);
);
protected:
int m_happinness;
std::vector<HappinessChangeListener*> happinessChangeListeners;
void happinessChanged(bool isHappier);
};
...
HappyPerson::HappyPerson()
: m_happinness(0)
{
}
void HappyPerson::updateHappiness(int amount)
{
if (amount != 0)
{
m_happinness += amount;
happinessChanged(amount > 0);
}
}
void HappyPerson::registerHappinessChangeListener(HappinessChangeListener *listener)
{
happinessChangeListeners.push_back(listener);
}
void HappyPerson::unregisterHappinessChangeListener(HappinessChangeListener *listener)
{
std::vector<HappinessChangeListener*>::iterator i = std::find(happinessChangeListeners.begin(), happinessChangeListeners.end(), listener);
if (i != happinessChangeListeners.end())
happinessChangeListeners.erase(i);
}
void HappyPerson::happinessChanged(bool isHappier)
{
for(std::vector<HappinessChangeListener*>::iterator i = happinessChangeListeners.begin(); i != happinessChangeListeners.end(); ++i)
i->happinessChanged(this, isHappier);
}
class Weather;
class WeatherChangeListener
{
public:
void weatherChanged(Weather *weather) = 0;
};
class Weather
{
public:
Weather();
void rainStarted();
void rainStopped();
bool isRaining();
void registerWeatherChangeListener(WeatherChangeListener *listener);
void unregisterWeatherChangeListener(WeatherChangeListener *listener);
protected:
bool m_raining;
std::vector<WeatherChangeListener*> weatherChangeListeners;
void weatherChanged();
};
...
Weather::Weather()
: m_raining(false)
{
}
void Weather::rainStarted()
{
if (!m_rRaining)
{
m_rRaining = true;
weatherChanged();
}
}
void Weather::rainStopped()
{
if (m_rRaining)
{
m_rRaining = false;
weatherChanged();
}
}
bool Weather::isRaining()
{
return m_raining;
}
void Weather::registerWeatherChangeListener(WeatherChangeListener *listener)
{
weatherChangeListeners.push_back(listener);
}
void Weather::unregisterWeatherChangeListener(WeatherChangeListener *listener)
{
std::vector<WeatherChangeListener*>::iterator i = std::find(weatherChangeListeners.begin(), weatherChangeListeners.end(), listener);
if (i != weatherChangeListeners.end())
weatherChangeListeners.erase(i);
}
void Weather::weatherChanged()
{
for(std::vector<WeatherChangeListener*>::iterator i = weatherChangeListeners.begin(); i != weatherChangeListeners.end(); ++i)
i->weatherChanged(this);
}
class RainLover : public HappyPerson, public WeatherChangeListener
{
public:
RainLover(std::shared_ptr<Weather> &weather);
~RainLover();
void weatherChanged(Weather *weather);
protected:
std::shared_ptr<Weather> m_weather;
};
...
RainLover::RainLover(std::shared_ptr<Weather> &weather)
: HappyPerson(), m_weather(weather)
{
m_weather->registerWeatherChangeListener(this);
}
RainLover::~RainLover()
{
m_weather->unregisterWeatherChangeListener(this);
}
void RainLover::weatherChanged(Weather *weather)
{
updateHappiness(weather->isRaining() ? 1 : -1);
}
class HappyLover : public HappyPerson, public HappinessChangeListener
{
public:
HappyLover(std::shared_ptr<HappyPerson> &person);
~HappyLover();
void happinessChanged(HappyPerson *person, bool isHappier);
protected:
std::shared_ptr<HappyPerson> m_person;
};
...
HappyLover::HappyLover(std::shared_ptr<HappyPerson> &person)
: HappyPerson(), m_person(person)
{
m_person->registerHappinessChangeListener(this);
}
HappyLover::~HappyLover()
{
m_person->unregisterHappinessChangeListener(this);
}
void HappyLover::happinessChanged(HappyPerson *person, bool isHappier)
{
updateHappiness(isHappier ? 1 : -1);
}
int main()
{
std::shared_ptr<Weather> weather(new Weather);
std::vector<std::shared_ptr<HappyPerson>> happyPeople;
happyPeople.push_back(std::shared_ptr<HappyPerson>(new RainLover(weather)));
// or: happyPeople.push_back(std::make_shared<RainLover>(weather));
happyPeople.push_back(std::shared_ptr<HappyPerson>(new HappyLover(happyPeople[0])));
// or: happyPeople.push_back(std::make_shared_ptr<HappyLover>(happyPeople[0]));
// ... add many other persons
weather->rainStarted();
...
weather->rainStopped();
...
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have a template class,in fsm.h file
and derived class in derivata.h file;
the compiler throws errors:
derivata.h: In constructor ‘deri::deri()’:
derivata.h:46: error: no matching function for call to ‘fsm<pin_steps>::fsm()’
fsm.h:30: note: candidates are: fsm<step_type>::fsm(step_type) [with step_type = pin_steps]
fsm.h:12: note: fsm<pin_steps>::fsm(const fsm<pin_steps>&)
fsm.h:
#ifndef FSM_H_
#define FSM_H_
template<class step_type> class fsm {
protected:
step_type step;
step_type step_old;
step_type step_tmp;
bool step_pulse;
char name[256];
public:
fsm(step_type);
void set_name(char *parent, char *myname);
void test();
virtual void update(){cout << "base\n";};
void show(){cout << step << ' ' << step_tmp << '\n'; };
void init(step_type st_current) {step = st_current;};
//virtual ~fsm();
};
//constructor
template <class step_type> fsm<step_type>::fsm(step_type) {
step = step_old = step_tmp = (step_type)0 ;
step_pulse = false;
}
template <class step_type> void fsm<step_type>::set_name(char *parent, char *myname) {
sprintf(name, "%s.%s", parent, myname);
}
template <class step_type> void fsm<step_type>::test() {
if (step != step_old) {
step_pulse = true;
step_tmp = step_old;
} else step_pulse = false;
step_old = step;
}
#endif /* FSM_H_ */
and a derived class from template class:
#include "fsm.h"
#ifndef DERIVATA_H_
#define DERIVATA_H_
enum taglio_steps {
ST_TAGLIO_CHECK_MOTORE,
ST_TAGLIO_ZERO_MOTORE,
ST_TAGLIO_WAIT_ZERO_MOTORE
};
enum pin_steps {
ST_PIN_BOOT,
ST_PIN_RETURN
};
class deri : public fsm<pin_steps>{
private:
bool cmd_prelevamento_done;
bool cmd_scorrimento_done;
float posizione_pinza_i;
float posizione_pinza_f;
public:
deri(){
cmd_prelevamento_done = false;
cmd_scorrimento_done = false;
posizione_pinza_i = 0;
posizione_pinza_f = 0;
};
void update(){cout << "deri\n";};
// virtual ~deri();
};
#endif /* DERIVATA_H_ */
Your base class doesn't have a non-parameter constructor, but in your derived class you are calling one (it is called automatically).
Change this:
deri(){
cmd_prelevamento_done = false;
cmd_scorrimento_done = false;
posizione_pinza_i = 0;
posizione_pinza_f = 0;
};
To this (pseudocode, I am not sure about correct syntax, I do not use this too often):
deri(): fsm<pin_steps>(ST_PIN_BOOT) {
cmd_prelevamento_done = false;
cmd_scorrimento_done = false;
posizione_pinza_i = 0;
posizione_pinza_f = 0;
};
The base class doesn't have a default constructor which is needed if (in constructor of a derived class) you don't specify which one should be called. If you dont' want fsm to be default-constructible, do this instead:
deri() : fsm(ST_PIN_BOOT) // call fsm::fsm(pin_steps)
{
// ...
}
The compiler error seems pretty clear. You are not calling the fsm<> constructor, and there are no default constructors for fsm. Your options are thus:
Create a default constructor: fsm::fsm() { ... }
Or, more likely in your case: call the constructor in the deri initalization list, like this:
deri() : fsm(step_type_here)
{
cmd_prelevamento_done = false;
cmd_scorrimento_done = false;
posizione_pinza_i = 0;
posizione_pinza_f = 0;
};
I would also recommend putting the other member variable initializations in the initializer list too.
That code is too big but i think you need a default constructor in the base class. Looks like Something like this
public:
fsm(); //added
fsm(step_type);
void set_name(char *parent, char *myname);
void test();
virtual void update(){cout << "base\n";};
void show(){cout << step << ' ' << step_tmp << '\n'; };
void init(step_type st_current) {step = st_current;};
//virtual ~fsm();
I'm writing an xml parser and I need to add objects to a class generically, switching on the actual type of the object. Problem is, I'd like to keep to an interface which is simply addElement(BaseClass*) then place the object correctly.
void E_TableType::addElement(Element *e)
{
QString label = e->getName();
if (label == "state") {
state = qobject_cast<E_TableEvent*>(e);
}
else if (label == "showPaytable") {
showPaytable = qobject_cast<E_VisibleType*>(e);
}
else if (label == "sessionTip") {
sessionTip = qobject_cast<E_SessionTip*>(e);
}
else if (label == "logoffmedia") {
logoffMedia = qobject_cast<E_UrlType*>(e);
}
else {
this->errorMessage(e);
}
}
This is the calling class, an object factory. myElement is an instance of E_TableType.
F_TableTypeFactory::F_TableTypeFactory()
{
this->myElement = myTable = 0;
}
void F_TableTypeFactory::start(QString qname)
{
this->myElement = myTable = new E_TableType(qname);
}
void F_TableTypeFactory::fill(const QString& string)
{
// don't fill complex types.
}
void F_TableTypeFactory::addChild(Element* child)
{
myTable->addElement(child);
}
Element* F_TableTypeFactory::finish()
{
return myElement;
}
void F_TableTypeFactory::addAttributes(const QXmlAttributes &attribs) {
QString tName = attribs.value(QString("id"));
myTable->setTableName(tName);
}
Have you considered using polymorphism here? If a common interface can be implemented by each of your concrete classes then all of this code goes away and things become simple and easy to change in the future. For example:
class Camera {
public:
virtual void Init() = 0;
virtual void TakeSnapshot() = 0;
}
class KodakCamera : Camera {
public:
void Init() { /* initialize a Kodak camera */ };
void TakeSnapshot() { std::cout << "Kodak snapshot"; }
}
class SonyCamera : Camera {
public:
void Init() { /* initialize a Sony camera */ };
void TakeSnapshot() { std::cout << "Sony snapshot"; }
}
So, let's assume we have a system which contains a hardware device, in this case, a camera. Each device requires different logic to take a picture, but the code has to support a system with any supported camera, so we don't want switch statements littered throughout our code. So, we have created an abstract class Camera.
Each concrete class (i.e., SonyCamera, KodakCamera) implementation will incluse different headers, link to different libraries, etc., but they all share a common interface; we just have to decide which one to create up front. So...
std::unique_ptr<Camera> InitCamera(CameraType type) {
std::unique_ptr<Camera> ret;
Camera *cam;
switch(type) {
case Kodak:
cam = new KodakCamera();
break;
case Sony:
cam = new SonyCamera();
break;
default:
// throw an error, whatever
return;
}
ret.reset(cam);
ret->Init();
return ret;
}
int main(...) {
// get system camera type
std::unique_ptr<Camera> cam = InitCamera(cameraType);
// now we can call cam->TakeSnapshot
// and know that the correct version will be called.
}
So now we have a concrete instance that implements Camera. We can call TakeSnapshot without checking for the correct type anywhere in code because it doesn't matter; we know the correct version for the correct hardware will be called. Hope this helped.
Per your comment below:
I've been trying to use polymorphism, but I think the elements differ too much. For example, E_SessionTip has an amount and status element where E_Url just has a url. I could unify this under a property system but then I lose all the nice typing entirely. If you know of a way this can work though, I'm open to suggestions.
I would propose passing the responsibility for writing the XML data to your types which share a common interface. For example, instead of something like this:
void WriteXml(Entity *entity) {
switch(/* type of entity */) {
// get data from entity depending
// on its type and format
}
// write data to XML
}
Do something like this:
class SomeEntity : EntityBase {
public:
void WriteToXml(XmlStream &stream) {
// write xml to the data stream.
// the entity knows how to do this,
// you don't have to worry about what data
// there is to be written from the outside
}
private:
// your internal data
}
void WriteXml(Entity *entity) {
XmlStream str = GetStream();
entity->WriteToXml(stream);
}
Does that work for you? I've done exactly this before and it worked for me. Let me know.
Double-dispatch may be of interest. The table (in your case) would call a virtual method of the base element, which in turns calls back into the table. This second call is made with the dynamic type of the object, so the appropriate overloaded method is found in the Table class.
#include <iostream>
class Table; //forward declare
class BaseElement
{
public:
virtual void addTo(Table* t);
};
class DerivedElement1 : public BaseElement
{
virtual void addTo(Table* t);
};
class DerivedElement2 : public BaseElement
{
virtual void addTo(Table* t);
};
class Table
{
public:
void addElement(BaseElement* e){ e->addTo(this); }
void addSpecific(DerivedElement1* e){ std::cout<<"D1"; }
void addSpecific(DerivedElement2* e){ std::cout<<"D2"; }
void addSpecific(BaseElement* e){ std::cout<<"B"; }
};
void BaseElement::addTo(Table* t){ t->addSpecific(this); }
void DerivedElement1::addTo(Table* t){ t->addSpecific(this); }
void DerivedElement2::addTo(Table* t){ t->addSpecific(this); }
int main()
{
Table t;
DerivedElement1 d1;
DerivedElement2 d2;
BaseElement b;
t.addElement(&d1);
t.addElement(&d2);
t.addElement(&b);
}
output: D1D2B
Have a Look at the Visitor Pattern, it might help you