I would like to send back data to class that create this object.
It's game related.
The enemy objects have a threaded function and move on their own in the scene.
It generates lots of errors if you include the header file from the class that creates to the objects into the object itself ... to pass pointers.
Enemy Class:
Class Enemy
{
private:
void (*iChange)(DWORD &);
}:
Enemy::Enemy(void (*iChangeHandler)(DWORD &) ) : iChange(0)
{
this->iChange = iChangeHandler;
}
void Enemy::Draw(D3DGraphics& gfx)
{
this->iChange(this->dwThreadID); // send a message back to the class that created me
gfx.PutPixel(this->my_position_x + 0,this->my_position_y,this->red,this->blue,this->green);
this->grafix->DrawCircle(this->my_position_x + 0,this->my_position_y, this->radius, this->red,this->blue,this->green);
(sprintf)( this->enemy_buffer, "X: %d, Y: %d", this->my_position_x , this->my_position_y);
this->grafix->DrawString( this->enemy_buffer, this->my_position_x , this->my_position_y, &fixedSys, D3DCOLOR_XRGB(255, 0, 0) );
}
Game Class:
struct enemies_array_ARRAY {
std::string name;
DWORD ID;
Enemy* enemy;
} enemies_array[25];
void Game::EnemyEvent(DWORD &thread_id)
{
enemies_array[0]...... // i want to acces this struct array
}
Game::Game(HWND hWnd)
{
enemies_array[0].name = "john Doe";
enemies_array[0].ID = NULL;
enemies_array[0].enemy = new Enemy(&Game::EnemyEvent);
// error: C2664:
// another attemp
enemies_array[0].name = "john Doe";
enemies_array[0].ID = NULL;
enemies_array[0].enemy = new Enemy(Game::EnemyEvent);
// error C3867:
}
If I understand correctly, you want to call a function on the Game object. This means you need to pass a pointer to the Game object in order to correctly call a non static member function pointer(iChange) on it.
Make the changes shown below and you should be able to do what you want
enemies_array[0].enemy = new Enemy(this,&Game::EnemyEvent);
typedef void (Game::*ChangeFunc)(DWORD &)
Class Enemy
{
private:
ChangeFunc iChange;
Game *pGame;
}:
Enemy(Game *pCreatorGame, ChangeFunc iChangeHandler )
{
iChange = iChangeHandler;
pGame = pCreatorGame;
}
void Enemy::Draw(D3DGraphics& gfx)
{
(pGame->*iChange)(this->dwThreadID);
Related
I have an application with several Forms. Two of them are quite similar, they have features in the form of VCL objects (labels, images, etc...) in common, which I named the same.
I want to have a function in a specific class which can accept one of these two Form as a parameter in order to modify the parameters that they have in common. The solution I came around does not seem to work.
As my application is quite big and complicated, I replicated the problem using a small example.
First, below is an example of my MainForm :
And an example of one subForm (they are all arranged in a similar way)
I have an additionnal class which is used to fill in the Edits on the subForms. The code for this class is the following:
#pragma hdrstop
#include "master_class.h"
#include "sub_Form2.h"
#include "sub_Form3.h"
#include "sub_Form4.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
Master::Master(void)
{
}
Master::~Master(void)
{
}
void Master::WriteToForm(TForm* Form)
{
TForm2* curForm = static_cast<TForm2*>(Form);
TForm3* self = dynamic_cast<TForm3*>(Form);
TForm2* self2 = dynamic_cast<TForm2*>(Form);
if (self != NULL && self2 == NULL) {
TForm3* curForm = static_cast<TForm3*>(Form);
}
else if (self == NULL && self2 != NULL) {
TForm2* curForm = static_cast<TForm2*>(Form);
}
curForm -> Edit1 -> Text = "blablabla_1";
curForm -> Edit2 -> Text = "blablabla_2";
}
And in the MainForm, the code for the "Fill Form2" button is the following:
Master1 -> WriteToForm(Form2);
where Master1 is just an object of the Master class.
This works very well for Form2 :
But for Form3, which is filled up using Master1 -> WriteToForm(Form3), here is what I get, which the same pb than in my real application:
So what should go to the Edit, is misplaced. I think the main pb comes from the fact that I did not create every label, edit, etc... on the same order. I did that on purpose to mimic my real application. To verify this, I created a 3rd subForm, where this time the VCL objects were created in the same order as my first subForm, and this works:
So I would suspect that this comes from the initial cast
TForm2* curForm = static_cast<TForm2*>(Form);
When I pass Form3 as an argument, Form3 is somewhat casted into the "shape" of Form2, which is not defined in the same order. Maybe this could be corrected by modifying directly the DFM file, but it is not a realistic approach for my main app.
I do this initial cast otherwise I get a compilation error saying that curForm is not known at the first line
curForm -> Edit1 -> Text = "blablabla_1";
So, is there a better way to pass the Form as an argument to the WriteToForm function?
Just because two types are similar does not mean they are related. Your code does not work because your two Form classes are not related to each other in any way. You can't just cast one to the other arbitrarily.
To solve this, you have several options:
code for both Form classes separately, eg:
void Master::WriteToForm(TForm* Form)
{
TForm2* curForm2 = dynamic_cast<TForm2*>(Form);
TForm3* curForm3 = dynamic_cast<TForm3*>(Form);
if (curForm2)
{
curForm2->Edit1->Text = _D("blablabla_1");
curForm2->Edit2->Text = _D("blablabla_2");
}
else if (curForm3)
{
curForm3->Edit1->Text = _D("blablabla_1");
curForm3->Edit2->Text = _D("blablabla_2");
}
}
Or:
void WriteToForm(TForm2* Form);
void WriteToForm(TForm3* Form);
...
void Master::WriteToForm(TForm2* Form)
{
Form->Edit1->Text = _D("blablabla_1");
Form->Edit2->Text = _D("blablabla_2");
}
void Master::WriteToForm(TForm3* Form)
{
Form->Edit1->Text = _D("blablabla_1");
Form->Edit2->Text = _D("blablabla_2");
}
Make your function use a template (however, be aware of this: Why can templates only be implemented in the header file?):
template<typename T>
void WriteToForm(T* Form);
...
void Master::WriteToForm<T>(T* Form)
{
Form->Edit1->Text = _D("blablabla_1");
Form->Edit2->Text = _D("blablabla_2");
}
make the two Form classes derive from a common base class or interface, eg:
class TBaseForm : public TForm
{
public:
inline __fastcall TBaseForm(TComponent *Owner) : TForm(Owner) {}
virtual void SetEdit1(const String &Text) = 0;
virtual void SetEdit2(const String &Text) = 0;
};
...
class TForm2 : public TBaseForm
{
...
public:
__fastcall TForm2(TComponent *Owner);
...
void SetEdit1(const String &NewText);
void SetEdit2(const String &NewText);
};
__fastcall TForm2::TForm2(TComponent *Owner)
: TBaseForm(Owner)
{
...
}
void TForm2::SetEdit1(const String &NewText)
{
Edit1->Text = NewText;
}
void TForm2::SetEdit2(const String &NewText)
{
Edit2->Text = NewText;
}
...
repeat for TForm3...
...
void Master::WriteToForm(TBaseForm* Form)
{
Form->SetEdit1(_D("blablabla_1"));
Form->SetEdit2(_D("blablabla_2"));
}
Or:
__interface INTERFACE_UUID("{E900785E-0151-480F-A33A-1F1452A431D2}")
IMyIntf : public IInterface
{
public:
virtual void SetEdit1(const String &Text) = 0;
virtual void SetEdit2(const String &Text) = 0;
};
...
class TForm2 : public TForm, public IMyIntf
{
...
public:
__fastcall TForm2(TComponent *Owner);
...
void SetEdit1(const String &NewText);
void SetEdit2(const String &NewText);
};
__fastcall TForm2::TForm2(TComponent *Owner)
: TForm(Owner)
{
...
}
void TForm2::SetEdit1(const String &NewText)
{
Edit1->Text = NewText;
}
void TForm2::SetEdit2(const String &NewText)
{
Edit2->Text = NewText;
}
...
repeat for TForm3...
...
void Master::WriteToForm(IMyIntf* Intf)
{
Intf->SetEdit1(_D("blablabla_1"));
Intf->SetEdit2(_D("blablabla_2"));
}
use RTTI to access the fields, eg:
#include <System.Rtti.hpp>
void Master::WriteToForm(TForm* Form)
{
TRttiContext Ctx;
TRttiType *FormType = Ctx.GetType(Form->ClassType());
TRttiField *Field = FormType->GetField(_D("Edit1"));
if (Field)
{
TValue value = Field->GetValue(Form);
if( (!value.Empty) && (value.IsObject()) )
{
TObject *Obj = value.AsObject();
// Either:
static_cast<TEdit*>(Obj)->Text = _D("blablabla_1");
// Or:
TRttiProperty *Prop = Ctx.GetType(Obj->ClassType())->GetProperty(_D("Text"));
if (Prop) Prop->SetValue(Obj, String(_D("blablabla_1")));
}
}
Field = FormType->GetField(_D("Edit2"));
if (Field)
{
TValue value = Field->GetValue(Form);
if( (!value.Empty) && (value.IsObject()) )
{
TObject *Obj = value.AsObject();
// Either:
static_cast<TEdit*>(Obj)->Text = _D("blablabla_2");
// Or:
TRttiProperty *Prop = Ctx.GetType(Obj->ClassType())->GetProperty(_D("Text"));
if (Prop) Prop->SetValue(Obj, String(_D("blablabla_2")));
}
}
}
I'm trying to use a factory pattern to create different types of "State" objects. The objects are returned with a pointer (State*) but shortly after the objects are created, the values they point to disappear (go to NULL or reset to boolean "true").
The code directly below is where it goes awry, but below that is a complete code sample that compiles and runs. Additionally, I've posted pictures of the debugger values before and after the usleep() command.
I feel like it may have something to do with scope and the garbage collector, but I'm not a C++ expert by any stretch of the imagination. I would have thought my pointer would have kept my referenced object alive.
// relevant code
void execute(){
// Calling the constructor directly as an example
State directState = State("temp", false, false, false);
// Using factory pattern to create a state. Just creating the "default" state as an example
State * factoryState = StateFactory::getDefaultState();
// factoryState -> name is "Reading" in the debugger, but when I try to print it out, it's gone
// Grab the names for easy reference
const char * dName = directState.name;
const char * fName = factoryState -> name;
usleep(1000000 / 100);
// factoryState -> name .... it's vanished?
usleep(1000000 / 100);
// TODO we would run the factoryState -> execute() function here
}
// Complete code example
#include <iostream>
#include <zconf.h>
// Main generic "State" class
class State {
public:
const char * name;
bool isReadable;
bool isExecuting;
bool isFinished;
State(const char name[], bool isReadable, bool isExecuting, bool isFinished){
this -> name = name;
this -> isReadable = isReadable;
this -> isExecuting = isExecuting;
this -> isFinished = isFinished;
}
};
// An inherited class. There will be lots of these eventually
class StateReading: public State { ;
public:
StateReading():State((const char *)"Reading", true, false, false) {}
};
// Factory method that will create lots of the different states
// note that it will be returning a pointer to a "State" object
class StateFactory {
public:
static State* getDefaultState(){
StateReading defaultState = StateReading();
State* state = &defaultState;
return state;
}
};
// Runs the various "States" in a template pattern
class StateExecutor {
public:
State * state;
StateExecutor(){
StateReading stateReading = StateReading();
state = &stateReading;
}
void execute(){
// Calling the constructor directly as an example
State directState = State("temp", false, false, false);
// Using factory pattern to create a state. Just creating the "default" state as an example
State * factoryState = StateFactory::getDefaultState();
// factoryState -> name is "Reading" in the debugger, but when I try to print it out, it's gone
// Grab the names for easy reference
const char * dName = directState.name;
const char * fName = factoryState -> name;
usleep(1000000 / 100);
// factoryState -> name .... it's disappeard?
usleep(1000000 / 100);
// TODO we would run the factoryState -> execute() function here
}
};
// The actual
void loop(StateExecutor stateExecutor) {
// Run the "execute" function of whatever the current state is
// The stateExecutor actually runs the state
stateExecutor.execute();
// Slow the loop down a little. Just for effect
usleep(1000000 / 100);
}
// Simple program to recreate an event loop
int main() {
try {
StateExecutor stateExecutor = StateExecutor();
int count = 0;
do {
loop(stateExecutor);
count++;
// Arbitrarily break out of the loop after 100 events.
} while(count < 100);
} catch (std::exception& e){
std::cout << e.what() << '\n';
}
}
Here are the values directly after the factory created them. All looks good.
Gah! I called usleep() and the factoryState's name field is gone and the bools have reverted to true (cout does this as well). Black magic!
Here:
static State* getDefaultState(){
StateReading defaultState = StateReading();
State* state = &defaultState;
return state;
}
You return a pointer to defaultState. This state however is destroyed when the function returns. Using this pointer later is undefined behavior. You can declare defaultState as static, though i would rather make it a static member.
I would like to implement a workaround to use a non-static class as a call-back function. I am working with Eclipse Paho MQTT code. The following type is implemented and used as callback:
typedef void MQTTAsync_onSuccess(void* context, MQTTAsync_successData* response);
MQTTAsync_onSuccess* onSuccess;
onSuccess = myStaticCallback;
void myStaticCallback (void* context, MQTTAsync_successData* response)
{
//...callback actions...
}
I want to wrap this C API (without modifying the existing MQTT C API) and implement non-static / non-centralized callback function that belongs to an object/class.
typedef void MQTTAsync_onSuccess(void* context, MQTTAsync_successData* response);
class myMQTTClass
{
private:
void myCallback (void* context, MQTTAsync_successData* response);
MQTTAsync_onSuccess* onSuccess;
public:
void foo (void)
{
this->onSuccess = this->myCallback;
}
}
As you might guess, the code above causes the error:
cannot convert myCallback from type 'void (myMQTTClass::) (void*, MQTTAsync_successData*)' to type 'void (*)(void*, MQTTAsync_successData*)'.
Any guidance as to how to address this issue or any workaround is greately appreciated. I would be willing to provide any possible missing information. Thanks in advance.
EDIT: Actual code with some omissions
namespace rover
{
typedef struct
{
char * clientID;
char * topic;
char * payload;
int qos; // 1
long int timeout; // Such as 10000L usec
} RoverMQTT_Configure_t;
class RoverPahoMQTT
{
public:
RoverPahoMQTT (char * host_name, int port, RoverMQTT_Configure_t MQTT_Configure);
private:
/**
* #brief Host name used for connecting to the Eclipse Paho MQTT server
*/
char * HOST_NAME;
/**
* #brief Port used for connecting to the Eclipse Paho MQTT server
*/
int PORT;
RoverMQTT_Configure_t rover_MQTT_configure;
/* Internal attributes */
MQTTAsync client;
/**
* #brief Connect options
*/
MQTTAsync_connectOptions conn_opts;
/**
* #brief Disconnect options
*/
MQTTAsync_disconnectOptions disc_opts;
//...
static void onPublisherConnect (void* context, MQTTAsync_successData* response);
void onPublisherConnect_ (MQTTAsync_successData* response);
//...
}
}
int rover::RoverPahoMQTT::publish (void)
{
this->flushFlags ();
this->conn_opts = MQTTAsync_connectOptions_initializer;
this->client = new MQTTAsync;
int rc;
char my_addr[20];
this->constructAddress (my_addr);
printf ("address: %s", my_addr);
MQTTAsync_create ( &(this->client),
my_addr,
this->rover_MQTT_configure.clientID,
MQTTCLIENT_PERSISTENCE_NONE,
NULL);
MQTTAsync_setCallbacks(this->client, NULL, onConnectionLost, NULL, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
conn_opts.onSuccess = rover::RoverPahoMQTT::onPublisherConnect;
conn_opts.onFailure = onConnectFailure;
conn_opts.context = this->client;
if ((rc = MQTTAsync_connect(this->client, &(this->conn_opts))) != MQTTASYNC_SUCCESS)
{
printf("Failed to start connect, return code %d\n", rc);
return rc;
}
/*printf("Waiting for publication of %s\n"
"on topic %s for client with ClientID: %s\n",
PAYLOAD, TOPIC, CLIENTID);*/
while (!mqtt_finished)
usleep(this->rover_MQTT_configure.timeout);
MQTTAsync_destroy(&client);
return rc;
}
void rover::RoverPahoMQTT::onPublisherConnect_(MQTTAsync_successData* response)
{
MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
int rc;
printf("Successful connection\n");
opts.onSuccess = onPublisherSend;
opts.context = client;
pubmsg.payload = &default_MQTT_configure.payload;
pubmsg.payloadlen = strlen(default_MQTT_configure.payload);
pubmsg.qos = default_MQTT_configure.qos;
pubmsg.retained = 0;
deliveredtoken = 0;
if ((rc = MQTTAsync_sendMessage(client, default_MQTT_configure.topic, &pubmsg, &opts)) != MQTTASYNC_SUCCESS)
{
printf("Failed to start sendMessage, return code %d\n", rc);
exit(EXIT_FAILURE);
}
}
void rover::RoverPahoMQTT::onPublisherConnect (void* context, MQTTAsync_successData* response)
{
rover::RoverPahoMQTT* m = (rover::RoverPahoMQTT*) context;
m->onPublisherConnect_(response);
//((rover::RoverPahoMQTT*)context)->onPublisherConnect_(response);
// ^^^HERE IS THE SEGMENTATION FAULT
}
As clearly stated here, the callback has to be
registered with the client library by passing it as an argument in
MQTTAsync_responseOptions
and the context argument is a
pointer to the context value originally passed to
MQTTAsync_responseOptions, which contains any application-specific
context.
I suggest a common interface for your classes, which provides a static method that matches the callback prototype:
class myMQTTClass
{
public:
static void callback(void* context, MQTTAsync_successData* response)
{
myMQTTClass * m = (myMQTTClass*)context;
m->myCallback(response);
}
protected:
virtual void myCallback(MQTTAsync_successData* response) = 0;
};
You can now implement different behaviours in subclasses:
class myMQTTClassImpl : public myMQTTClass
{
protected:
void myCallback(MQTTAsync_successData *response)
{
std::cout << "success!!!" << std::endl;
}
};
Let's see how to use it:
int main()
{
myMQTTClass * m = new myMQTTClassImpl();
MQTTAsync_responseOptions options;
options.onSuccess = myMQTTClass::callback;
options.context = m;
}
Edit (refers to actual code posted):
In your publish method, this is right:
conn_opts.onSuccess = rover::RoverPahoMQTT::onPublisherConnect;
this is wrong:
conn_opts.context = this->client;
it should be:
conn_opts.context = this;
If you can use the context parameter to point to the object you want the callback to fire on you could simply make the callback function static and forward to an instance function. If the context parameter is needed for other data then I would use libffi to generate a closure and associate the object pointer with the closure's saved arguments.
There is no correct way to pass an actual instance function to that callback and be sure that it will work (even if you made the instance function be something like void MyCallback(MQTTAsync_successData*) and then forcibly cast that to the callback type you aren't guaranteed that the calling convention would match.
For the first (where you can use the context arg to point to 'this'):
class MyCallback
{
static void CallbackFunc(void * ptr, MQTTAsync_successData* data)
{
((MyCallback*)ptr)->RealCallback(data);
}
void RealCallback(MQTTAsync_successData*)
{}
};
You would then assign &MyCallback::CallbackFunc to the function pointer.
libffi is quite a bit more complicated.
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)
Hey hey I'm a c++ newb here... i would appriciate someone pointing out an apparent misunderstanding i have about pointers and vectors (may be something else). I'm trying to create a switch element that handles several sub states
class MotionSwitch: public StateSwitch, public IMotion
{
public:
MotionSwitch(){ initialize(); };
~MotionSwitch(){};
//Make Motion States
MotionState restState; //Initialized In _states at 0
MotionState motionState;//" " 1
MotionState spinState;//" " 2
std::vector<MotionState*> _states;
};
class MotionState: public State, public IMotion
{
...
String msg = "Hello Is Motion";
...
};
The _states vector is initialized like this...
void MotionSwitch::initialize()
{
//Add States In Order Of ENUM (Because It Matters!)
_states.push_back(&restState);
_states.push_back(&motionState);
_states.push_back(&spinState);
}
The in following application code only one of the following will print
MotionState *currentState = widget._motionSwitch._states.at(0);
widget._com.log( "State Message...");
widget._com.log( currentState -> msg); //Won't Print
widget._com.log( widget._motionSwitch.restState.msg ); //This WILL Print
I would appreciate any help i can get here from you code gods!