C++ member of class updated outside class - c++

I have a question about pointers and references in C++. I am a programmer who normally programs in C# and PHP.
I have two classes (for now) which are the following.
The X/Y in Controller are continuously changing but i want them up to date in the Commands. I have multiple commands like Forward, Turn, Backward etc.
When i make the commands i give them the controller but the state (X, Y) of the controller are updating every second.
How can i fix that the controller attribute in the Commands are getting updated also every second?
class Forward : ICommand
{
Controller ctrl;
void Execute() {
int CurrentX = ctrl.X;
int CurrentY = ctrl.Y;
//Check here for the current location and calculate where he has to go.
}
}
class Controller
{
int X;
int Y;
void ExecuteCommand(ICommand command) {
command.Execute();
}
}
Main.cpp
Controller controller;
Forward cmd1 = new Forward(1, controller);
Turn cmd2 = new Turn(90, controller);
Forward cmd3 = new Forward(2, controller);
controller.Execute(cmd1);
controller.Execute(cmd2);
controller.Execute(cmd3);
I have read something about pointers and references and i think i have to use this but don't know how to use it in this situation.
(code can have some syntax errors but that's because i typed over. Everything is working further except for the updating).

If you use references rather than copy objects you can see changes.
#include <iostream>
using namespace std;
class ICommand
{
public:
virtual ~ICommand() = default;
virtual void Execute() = 0;
};
class Controller
{
public:
int X = 0;
int Y = 0;
void ExecuteCommand(ICommand & command) {
// ^-------
command.Execute();
}
};//,--- semicolons required
class Forward : public ICommand //note public
{
const int step;
Controller ctrlCopy;
Controller & ctrlReference;
public:
Forward(int step, Controller & ctrl) :
step(step),
ctrlCopy(ctrl), //this is a copy of an object
ctrlReference(ctrl) //this is a reference to an object
{
}
void Execute() {
std::cout << "copy: " << ctrlCopy.X << ", " << ctrlCopy.Y << '\n';
std::cout << " ref: " << ctrlReference.X << ", " << ctrlReference.Y << '\n';
//Check here for the current location and calculate where he has to go.
ctrlCopy.X += 10;
ctrlReference.X += 10;
}
};//<--- semicolons required
int main() {
Controller controller;
Forward cmd1(1, controller);
//Turn cmd2(90, controller); //Left for the OP to do
Forward cmd3(2, controller);
controller.ExecuteCommand(cmd1);
//controller.ExecuteCommand(cmd2);
controller.ExecuteCommand(cmd3);
//Do it again to show the copy and reference difference
std::cout << "Once more, with feeling\n";
controller.ExecuteCommand(cmd1);
controller.ExecuteCommand(cmd3);
}
Giving
copy: 0, 0
ref: 0, 0
copy: 0, 0 // [1]
ref: 10, 0 // [2]
Once more, with feeling
copy: 10, 0
ref: 20, 0
copy: 10, 0
ref: 30, 0
1 shows that the copy has X and Y of 0, while the reference shown in [2] has moved by the stated step (in controller.ExecuteCommand(cmd3))
Note, we don't need to use new to make this work (don't forget delete if you use new).
Also, void ExecuteCommand(ICommand command) now takes a reference instead otherwise the by-value copy does "slicing" (e.g. see here)

Related

C++ referencing instances created within a function's scope

Context
The context of the problem is that I am currently writing a small library for use with the Arduino in order to act as a game controller. The problem I am encountering has more to do with C++ than anything Arduino specific however.
I've included the libraries' header and source code below, followed by the Arduino code. I've truncated it where possible.
Problem
In short, only the last switch / action I define actually gets properly handles.
These actions get defined in the Arduino setup function. For example:
controller.addSwitchContinuous(10, 0); // Pin 10; btn index 0
means that pin 10 gets mapped to button 0. When pin 10 is switched closed this is treated as the button being pressed. This works fine for a single action but when I start adding more only the last action actually works. So in the following example only pin 9 is recognized:
controller.addSwitchContinuous(10, 0); // <-- Doesn't work
controller.addSwitchContinuous(9, 1); // <-- Works
This goes for any arbitrary number of actions:
controller.addSwitchContinuous(10, 0); // <-- Doesn't work
controller.addSwitchContinuous(9, 1); // <-- Doesn't work
controller.addSwitchContinuous(8, 2); // <-- Doesn't work
controller.addSwitchContinuous(7, 3); // <-- Works
Potential causes
I am fairly novice with C++ so this I suspect I'm doing something wrong with pointers. More specifically, something seems wrong with how the Joystick_ instance gets passed around.
I have been fiddling with the constructor and trying to use references instead of pointers but I couldn't get it to work properly.
I can confirm the iteration in JFSF::loop does iterate over all actions, if I modify it with:
void JFSF::loop()
{
for (int n = 0; n < _nextActionIndex; n++)
{
if (_actions[n])
{
_actions[n]->loop();
_joystick->setButton(n, PRESSED); // Debug: Set button pressed, regardless of switch.
}
}
if (_doSendState)
{
_joystick->sendState();
}
}
then buttons 0 through n get pressed as expected. It is possible that loop() isn't properly being called, but I would expect it to fail for the N = 1 case as well in that case. Furthermore the fact the last action always succeeds would suggest the iteration is ok.
Full code
// JFSF.h
#ifndef JFSF_h
#define JFSF_h
// ... include for Arduino.h and Joystick.h; bunch of defines
namespace JFSF_PRIV
{
class AbstractAction
{
public:
virtual void loop();
};
/* A Switch that essentially acts as a push button. */
class SwitchContinuousAction : public AbstractAction
{
public:
SwitchContinuousAction(Joystick_ *joystick, int pin, int btnIndex);
void loop();
private:
Joystick_ *_joystick;
int _pin;
int _btnIndex;
};
} // namespace JFSF_PRIV
class JFSF
{
public:
JFSF(Joystick_ *joystick, bool doSendState); // doSendState should be true if Joystick_ does not auto send state.
void loop();
void addSwitchContinuous(int inputPin, int btnIndex);
private:
Joystick_ *_joystick;
JFSF_PRIV::AbstractAction *_actions[MAX_ACTIONS];
int _nextActionIndex;
bool _doSendState;
};
#endif
Source file (trimmed):
// JFSF.cpp
#include "Arduino.h"
#include "Joystick.h"
#include "JFSF.h"
#define PRESSED 1
#define RELEASED 0
// Private classes
namespace JFSF_PRIV
{
SwitchContinuousAction::SwitchContinuousAction(Joystick_ *joystick, int pin, int btnIndex)
{
_joystick = joystick;
_pin = pin;
_btnIndex = btnIndex;
pinMode(_pin, INPUT_PULLUP);
}
void SwitchContinuousAction::loop()
{
int _state = digitalRead(_pin) == LOW ? PRESSED : RELEASED;
_joystick->setButton(_btnIndex, _state);
}
} // namespace JFSF_PRIV
JFSF::JFSF(Joystick_ *joystick, bool doSendState)
{
_joystick = joystick;
_nextActionIndex = 0;
_doSendState = doSendState;
}
void JFSF::addSwitchContinuous(int inputPin, int btnIndex)
{
JFSF_PRIV::SwitchContinuousAction newBtnAction(_joystick, inputPin, btnIndex);
_actions[_nextActionIndex++] = &newBtnAction;
}
void JFSF::loop()
{
for (int n = 0; n < _nextActionIndex; n++)
{
if (_actions[n])
{
_actions[n]->loop();
}
}
if (_doSendState)
{
_joystick->sendState();
}
}
For completeness sake, this is the code for the Arduino, but it is pretty much just declarations:
#include <JFSF.h>
// ... A bunch of const declarations used below. These are pretty self explanatory.
// See: https://github.com/MHeironimus/ArduinoJoystickLibrary#joystick-library-api
Joystick_ joystick(HID_REPORT_ID,
JOYSTICK_TYPE_JOYSTICK, // _JOYSTICK, _GAMEPAD or _MULTI_AXIS
BTN_COUNT, HAT_SWITCH_COUNT,
INCLUDE_X_AXIS, INCLUDE_Y_AXIS, INCLUDE_Z_AXIS,
INCLUDE_RX_AXIS, INCLUDE_RY_AXIS, INCLUDE_RZ_AXIS,
INCLUDE_RUDDER, INCLUDE_THROTTLE,
INCLUDE_ACCELERATOR, INCLUDE_BRAKE, INCLUDE_STEERING);
JFSF controller(&joystick, !DO_AUTO_SEND_STATE);
void setup() {
joystick.begin(DO_AUTO_SEND_STATE);
controller.addSwitchContinuous(10, 0); // <-- Doesn't work
controller.addSwitchContinuous(9, 1); // <-- Works
}
void loop() {
controller.loop();
}
References
ArduinoJoystickLibrary (Source for Joystick_) can be found here: https://github.com/MHeironimus/ArduinoJoystickLibrary#joystick-library-api
I dont really understand your code. Please read How to create a Minimal, Complete and Verifiable example. Anyhow, the following is certainly wrong and likely the cause of your problem:
void JFSF::addSwitchContinuous(int inputPin, int btnIndex)
{
JFSF_PRIV::SwitchContinuousAction newBtnAction(_joystick, inputPin, btnIndex);
_actions[_nextActionIndex++] = &newBtnAction;
}
Lets rewrite it a bit for clarity:
void foo(){
T bar;
container[index] = &bar;
}
What happens here is that bar gets destroyed when it goes out of scope, hence the pointer you put into the container, points to garbage. Presumably somewhere else in your code you are dereferencing those pointers, which is undefined behaviour (aka anything can happen).
Long story short: It is a common pattern among c++ beginners to overuse pointers. Most likely you should make container a container of objects rather than pointers and make use of automatic memory managment instead of trying to fight it.
Thanks to #user463035818 and #drescherjm for identifiying the actual problem.
So in the end I fixed it by simply moving the Action object creation up to the Arduino code (where it's essentially global) and passing references to those objects to the controller.
In code this translates to:
JFSF.cpp
void JFSF::addAction(JFSF_PRIV::AbstractAction *action){
_actions[_nextActionIndex++] = action;
}
Arduino code (ino)
// See code in original post
JFSF controller(&joystick, !DO_AUTO_SEND_STATE);
JFSF_PRIV::SwitchContinuousAction btnOne(&joystick, 10, 0);
JFSF_PRIV::SwitchContinuousAction btnTwo(&joystick, 9, 1);
void setup() {
joystick.begin(DO_AUTO_SEND_STATE);
// controller.addSwitchContinuous(10, 0); // Pin 10; btn index 0
// controller.addSwitchContinuous(9, 1); // Pin 9 ; btn index 1
controller.addAction(&btnOne);
controller.addAction(&btnTwo);
}
// loop() is unchanged

How can I distinguish my characters in a vector? SFML 2.4.1

I am using push_back to add identical characters and for some reason these characters all have the same stats all the time.
Battle.cpp:
void Battle::InitalizeUser()
{
user.t_Pokemon.clear();
user.t_Item.clear();
user.currentPokemon_U = 0;
user.t_Pokemon.push_back(&uF1);
user.t_Pokemon.push_back(&uF1);
user.t_Pokemon.push_back(&uW3);
user.t_Pokemon.push_back(&uW3);
user.t_Pokemon.push_back(&uG5);
user.t_Pokemon.push_back(&uG5);
user.t_Item.push_back(&uI1);
user.t_Item.push_back(&uI2);
for (unsigned int i = 0; i < user.t_Pokemon.size(); i++)
{
user.t_Pokemon.at(i)->poke_health = 100;
user.t_Pokemon.at(i)->poke_isFainted = false;
}
assert(user.t_Pokemon.size() == 6);
assert(user.t_Item.size() == 2);
}
So if uF1 health is reduced all uF1 characters will suffer the same reduction, but I don't want all the others uF1 to suffer the reduction, I want to be able to distinguish them and have only one specific character affected.
How can I do that?
Pokemon.cpp:
void Pokemon::attackNormal(Pokemon * opponentPokemon)
{
opponentPokemon->poke_health = opponentPokemon->poke_health - 20;
opponentPokemon->changeIfFainted();
assert(opponentPokemon->poke_health <= 100 && opponentPokemon->poke_health >= 0);
}
Battle.h:
class Battle
{
private:
static Trainer user;
static Trainer ash;
static IntRect user_Rect;
static IntRect ash_Rect;
// User's pokemon
static Fire uF1;
static Water uW3;
static Grass uG5;
static Item uI1;
static Item uI2;
}
uF1 : Pokemon.h
class Fire : public Pokemon
{
public:
Fire();
Fire(string name);
virtual ~Fire();
void specialAttack(Pokemon * opponentPokemon);
void changeWeather();
void Draw(RenderWindow &window);
};
The problem is that your vector contains copies of a pointer what is not equivalent to having different copies of an actual object.
It seems that you are passing same pointers several times in order to achieve object copy which is not a case.
You should first declare all your objects and then add their addresses to the vector.
Additional note: you don't have to create a variable for every object you use. You could also create an array of objects.

Coding State Machine in C++

I'm attempting to code a state machine based on a gumball machine. I have a interface class of a basic state, while I have specific states that use this interface. I have four states, no_quarter, has_quarter, sold, and sold_out states. I also have a gumball machine class that handles these states and depending on which state my machine is in, it will go that class and do the needed action. Here is my code that is having the problem, I'll post my functions also.
Gumball_Machine.h
class Gumball_Machine
{
private:
int gumball_count;
State *current_state;
No_Quarter_State *nqs;
Has_Quarter_State *hqs;
Sold_State *ss;
Sold_Out_State *sos;
public:
Gumball_Machine(int inventory)
{
gumball_count = inventory;
nqs = new No_Quarter_State(this);
hqs = new Has_Quarter_State(this);
ss = new Sold_State(this);
sos = new Sold_Out_State(this);
if (gumball_count == 0)
set_state(sos);
else
set_state(nqs);
}
void insert_quarter()
{
current_state->insert_quarter();
}
void eject_quarter()
{
current_state->eject_quarter();
}
void turn_crank()
{
current_state->turn_crank();
}
void dispense()
{
current_state->dispense();
}
void set_state(State *new_state)
{
current_state = new_state;
}
State *get_no_quarter_state()
{
return nqs;
}
State *get_has_quarter_state()
{
return hqs;
}
State *get_sold_state()
{
return ss;
}
State *get_sold_out_state()
{
return sos;
}
No_Quarter_State.h
#ifndef NO_QUARTER_STATE_H_INCLUDED
#define NO_QUARTER_STATE_H_INCLUDED
#include "State.h"
class No_Quarter_State: public State
{
public:
No_Quarter_State(Gumball_Machine *gbm);
void insert_quarter();
void eject_quarter();
void turn_crank();
void dispense();
};
#endif // NO_QUARTER_STATE_H_INCLUDED
No_Quarter_State.cpp
#include "No_Quarter_State.h"
#include "Gumball_Machine.h"
No_Quarter_State::No_Quarter_State(Gumball_Machine *machine)
{
machine = machine;
}
void No_Quarter_State::insert_quarter()
{
cout << "You inserted a quarter.\n";
machine->set_state(machine->get_has_quarter_state());
}
void No_Quarter_State::eject_quarter()
{
cout << "You must insert a quarter before you can eject one.\n";
}
void No_Quarter_State::turn_crank()
{
cout << "You must insert a quarter before you can crank the handle.\n";
}
void No_Quarter_State::dispense()
{
cout << "You need to pay first before you can get a gumball.\n";
}
The line I'm having an issue is in the No_Quarter_State.cpp
machine->set_state(machine->get_has_quarter_state());
This is giving me a run-time error. I've seen examples like this but I'm not completely sure if this is legal in C++. I'm attempting to switch the state of my gumball machine object.
The error I get is a generic not responding error: "test.ext has stopped working". I'm using CodeBlocks to code this.
In the constructor, the presumed member variable machine is hidden by the parameter.
No_Quarter_State::No_Quarter_State(Gumball_Machine *machine)
{
machine = machine;
}
You can fix this by using initializer list syntax instead:Thanks Sneftel and NathanOliver
No_Quarter_State::No_Quarter_State(Gumball_Machine *machine)
: machine(machine)
{
}
However, in regular method functions, you would have to use this-> if you named the method parameter the same as the member variable. A typical style used to avoid that issue is to prepend m_ or append _ to member names.

Why can't one clone a `Space` in Gecode before solving the original one?

I'm looking for a way to copy Space instances in Gecode and then analyze the difference between the spaces later.
However it goes already wrong after the first copy. When one copies the code in the book Modelling and Programming in Gecode, as shown here below, and simply modifies it such that a copy is made first (SendMoreMoney* smm = m->copy(true);), one gets a Segmentation fault, regardless whether the shared option is true or false.
#include <gecode/int.hh>
#include <gecode/search.hh>
using namespace Gecode;
class SendMoreMoney : public Space {
protected:
IntVarArray l;
public:
SendMoreMoney(void) : l(*this, 8, 0, 9) {
IntVar s(l[0]), e(l[1]), n(l[2]), d(l[3]),
m(l[4]), o(l[5]), r(l[6]), y(l[7]);
// no leading zeros
rel(*this, s, IRT_NQ, 0);
rel(*this, m, IRT_NQ, 0);
// all letters distinct
distinct(*this, l);
// linear equation
IntArgs c(4+4+5); IntVarArgs x(4+4+5);
c[0]=1000; c[1]=100; c[2]=10; c[3]=1;
x[0]=s; x[1]=e; x[2]=n; x[3]=d;
c[4]=1000; c[5]=100; c[6]=10; c[7]=1;
x[4]=m; x[5]=o; x[6]=r; x[7]=e;
c[8]=-10000; c[9]=-1000; c[10]=-100; c[11]=-10; c[12]=-1;
x[8]=m; x[9]=o; x[10]=n; x[11]=e; x[12]=y;
linear(*this, c, x, IRT_EQ, 0);
// post branching
branch(*this, l, INT_VAR_SIZE_MIN(), INT_VAL_MIN());
}
// search support
SendMoreMoney(bool share, SendMoreMoney& s) : Space(share, s) {
l.update(*this, share, s.l);
}
virtual SendMoreMoney* copy(bool share) {
return new SendMoreMoney(share,*this);
}
// print solution
void print(void) const {
std::cout << l << std::endl;
}
};
// main function
int main(int argc, char* argv[]) {
// create model and search engine
SendMoreMoney* m = new SendMoreMoney;
SendMoreMoney* mc = m->copy(true);
DFS<SendMoreMoney> e(m);
delete m;
// search and print all solutions
while (SendMoreMoney* s = e.next()) {
s->print(); delete s;
}
return 0;
}
How can one make a real copy?
You have to call status() on the Space first.
I found this exchange in the Gecode mailing list archives: https://www.gecode.org/users-archive/2006-March/000439.html
It would seem that internally, Gecode uses the copy function and constructor for its own internal purposes, so to make a "copy-by-value" copy of a space, you need to use the clone() function defined in the Space interface. However, as noted in #Anonymous answer, you need to call status() before calling clone or it will throw an exception of type SpaceNotStable
I augmented my space with the function below to automatically call status, make the clone, and return a pointer of my derived type:
struct Example : public Space {
...
Example * cast_clone() {
status();
return static_cast<Example *>(this->clone());
}
...
}
As a workaround, one can create a totally independent space and then use equality constraints
on the variable level to reduce the domains of these variables.
Example:
void cloneHalfValues(SendMoreMoney* origin) {
int n = l.size();
for(int i = 0x00; i < n/2; i++) {
if(origin->l[i].assigned()) {
rel(*this, l[i], IRT_EQ, origin->l[i].val());
}
}
}
The reason why one can't clone a Space is however still a mystery.

Issue with setting speed to DifferentialWheels in Webots C++

Small community here, but hopefully somebody sees this. I'm attempting to do a pure C++ implementation of a Webots simulation for an E-puck. The C++ documentation is sorely lacking, and I can't seem to find a resolution for this issue (the C implementation is stellar, but all the function calls were changed for C++).
Essentially, I'm just trying to get a simple application up and running...I want to make the E-puck move forward. I will post the entirety of my code below...all I'm doing is instantiating a Robot entity, printing out all the IR sensor values, and attempting to move it forward.
The issue is that it does not move. I'd think that there would be some call to link the DifferentialWheel object to the E-puck (similar to the camera = getCamera("camera") call).
If I comment out my call to setSpeed, the program works perfectly (doesn't move, but prints values). If I leave it in, the simulation freezes up after a single step, once it gets to that call. I'm not exactly sure what I'm doing wrong, to be honest.
// webots
#include <webots/Robot.hpp>
#include <webots/Camera.hpp>
#include <webots/DistanceSensor.hpp>
#include <webots/DifferentialWheels.hpp>
#include <webots/LED.hpp>
// standard
#include <iostream>
using namespace webots;
#define TIME_STEP 16
class MyRobot : public Robot
{
private:
Camera *camera;
DistanceSensor *distanceSensors[8];
LED *leds[8];
DifferentialWheels *diffWheels;
public:
MyRobot() : Robot()
{
// camera
camera = getCamera("camera");
// sensors
distanceSensors[0] = getDistanceSensor("ps0");
distanceSensors[1] = getDistanceSensor("ps1");
distanceSensors[2] = getDistanceSensor("ps2");
distanceSensors[3] = getDistanceSensor("ps3");
distanceSensors[4] = getDistanceSensor("ps4");
distanceSensors[5] = getDistanceSensor("ps5");
distanceSensors[6] = getDistanceSensor("ps6");
distanceSensors[7] = getDistanceSensor("ps7");
for (unsigned int i = 0; i < 8; ++i)
distanceSensors[i]->enable(TIME_STEP);
// leds
leds[0] = getLED("led0");
leds[1] = getLED("led1");
leds[2] = getLED("led2");
leds[3] = getLED("led3");
leds[4] = getLED("led4");
leds[5] = getLED("led5");
leds[6] = getLED("led6");
leds[7] = getLED("led7");
}
virtual ~MyRobot()
{
// cleanup
}
void run()
{
double speed[2] = {20.0, 0.0};
// main loop
while (step(TIME_STEP) != -1)
{
// read sensor values
for (unsigned int i = 0; i < 8; ++i)
std::cout << " [" << distanceSensors[i]->getValue() << "]";
std::cout << std::endl;
// process data
// send actuator commands
// this call kills the simulation
// diffWheels->setSpeed(1000, 1000);
}
}
};
int main(int argc, char* argv[])
{
MyRobot *robot = new MyRobot();
robot->run();
delete robot;
return 0;
}
Now, if this were the C implementation, I would call wb_differential_wheels_set_speed(1000, 1000); However, that call isn't available in the C++ header files.
The problem causing the freeze is due to the use of the uninitialized variable diffWheels.
DifferentialWheels (as well as Robot and Supervisor) doesn't need to be initialized.
You have to change the base class of your MyRobot class to DifferentialWheels
class MyRobot : public DifferentialWheels
and then simply call
setSpeed(1000, 1000)
and not
diffWheels->setSpeed(1000, 1000)
It doesn't seem as though you've initialized diffWheels, so I would imagine you're getting a segfault from dereferencing a garbage pointer. Try putting
diffWheels = new DifferentialWheels;
in the constructor of MyRobot.