I'm not very experienced in cpp (used to work in python).
I have the following problem:
1) I have a main class A (a window) and the methods m_A1 and m_A2
2) I have a little class B (a dialog) with a callback m_B1
3) the class B is instantiated and destroyed inside of m_A1
4) from the callback m_B1 I need to call m_A2
I tried to give to B reference to the instance of A (with 'this') but this solution that worked in python here doesn't.
I tried to declare the class B inside of A to have the methods of A accessible inside of B but I can't understand how to write the code of the methods of B, writing for example the class constructor of B would be
A::B::A::B() but gives syntax errors.
Here's some code:
class Centrino
{
public:
Centrino();
virtual ~Centrino();
Gtk::Window *mp_window;
protected:
...
bool on_window_key_press(GdkEventKey *event);
void io_process_incoming_command(char *in_str_complete);
...
};
class DebugDialog : public Gtk::Dialog
{
public:
DebugDialog(const char *title, Gtk::Window& parent, bool modal);
virtual ~DebugDialog() {};
protected:
void on_button_send_clicked();
...
};
void Centrino::io_process_incoming_command(char *in_str_complete)
{
...
}
bool Centrino::on_window_key_press(GdkEventKey *event_key)
{
if(event_key->state & GDK_CONTROL_MASK)
{
if((event_key->keyval == GDK_KEY_d) || (event_key->keyval == GDK_KEY_D))
{
DebugDialog dialog("Debug Dialog", *mp_window, true);
int response = dialog.run();
}
}
...
}
void DebugDialog::on_button_send_clicked()
{
Glib::ustring entry_content = m_entry.get_text();
io_process_incoming_command(entry_content.c_str());
}
Centrino is the class that I called A, DebugDialog is the class that I called B.
From DebugDialog:: on_button_send_clicked() I need to call Centrino:: io_process_incoming_command().
The scope of the class DebugDialog instance is inside of Centrino:: on_window_key_press().
Can anybody point me to an example? Thanks in advance.
Add a Centrino reference in DebugDialog attributes and provide it in DebugDialog contructor. Declare Centrino::io_process_incoming_command() method public and invoke it from DebugDialog::on_button_send_clicked() method:
class Centrino
{
public:
Centrino();
virtual ~Centrino();
Gtk::Window *mp_window;
void io_process_incoming_command(char *in_str_complete);
protected:
...
bool on_window_key_press(GdkEventKey *event);
...
};
bool Centrino::on_window_key_press(GdkEventKey *event_key)
{
if(event_key->state & GDK_CONTROL_MASK)
{
if((event_key->keyval == GDK_KEY_d) || (event_key->keyval == GDK_KEY_D))
{
DebugDialog dialog("Debug Dialog", *mp_window, true, *this);
int response = dialog.run();
}
}
...
}
class DebugDialog : public Gtk::Dialog
{
public:
DebugDialog(const char *title, Gtk::Window& parent, bool modal, Centrino ¢rino);
virtual ~DebugDialog() {};
protected:
void on_button_send_clicked();
...
Centrino ¢rino_;
};
DebugDialog::DebugDialog(const char *title, Gtk::Window& parent, bool modal, Centrino ¢rino) :
....
centrino_(centrino)
{
...
}
void DebugDialog::on_button_send_clicked()
{
Glib::ustring entry_content = m_entry.get_text();
centrino_.io_process_incoming_command(entry_content.c_str());
}
The scope of DebugDialog is global, and as written, DebugDialog has
no knowledge of the context in which it was created. You need to pass
and save this information explicitly:
class DebugDialog : public Gtk::Dialog
{
Centrino* myOwner;
public:
DebugDialog( Centrino* owner, const char *title, Gtk::Window& parent, bool modal );
virtual ~DebugDialog() {};
protected:
void on_button_send_clicked();
...
};
DebugDialog::DebugDialog( Centrino* owner... )
: myOwner( owner )
, ...
void Centrino::io_process_incoming_command(char *in_str_complete)
{
...
}
bool Centrino::on_window_key_press(GdkEventKey *event_key)
{
if(event_key->state & GDK_CONTROL_MASK)
{
if((event_key->keyval == GDK_KEY_d) || (event_key->keyval == GDK_KEY_D))
{
DebugDialog dialog(this, "Debug Dialog", *mp_window, true);
int response = dialog.run();
}
}
...
}
void DebugDialog::on_button_send_clicked()
{
Glib::ustring entry_content = m_entry.get_text();
myOwner->io_process_incoming_command(entry_content.c_str());
}
Related
I have a parent class Window
class Window
{
public:
Window(int x, int y);
virtual void Display();
virtual ~Window();
}
and a base class Console
class Console : public Window
{
public:
Console(int x, int y);
virtual void Display();
virtual ~Console();
}
I store the results in a manager class with the following signature:
class WindowManager
{
public:
WindowManager() {};
void AddWindow(int x, int y)
{
m_Windows.emplace(nle::WindowType::RenderWindow, std::make_unique<nle::Window>(x,y))
}
void AddConsole(int x, int y)
{
m_Windows.emplace(nle::WindowType::ConsoleWindow, std::make_unique<nle::Console>(x,y));
}
nle::Window* GetRenderWindow()
{
return m_Windows[nle::WindowType::RenderWindow].get();
}
nle::Window* GetConsoleWindow()
{
return m_Windows[nle::WindowType::ConsoleWindow].get();
}
private:
std::unordered_map<WindowType, std::unique_ptr<nle::Window>> m_Windows;
};
When calling the Get___Window functions the base class is always called, I tried returning a reference to the windows instead of a pointer but the base class is still called, I've seen references of others doing a for ranged loop to directly access the container:
for(const window& : m_Windows)
{
window->Display();
}
This would work, but i would like to avoid using direct access to my manager.
An example of this code is:
static WindowManager m_WindowManager; // static purely for simplicity to avoid using a class for SO
int main()
{
InitResources();
while(1)
{
DisplayWindow();
}
return 1;
}
void InitResources()
{
m_WindowManager.AddConsoleWindow(1080, 720);
}
void DisplayWindow()
{
m_WindowManager.GetConsoleWindow()->Display(); // Base class is called
}
I have a problem with the following piece of code that can't even compile.
The problem is on the line
class2_ = new Class2(myFunction);
In fact, I don't now how to reference myFunction, I have also tried class2_ = new Class2(&Class3::myFunction); but the compiler still complains :(
2 constraints:
The function myFunction can't be declared as static
This code will be used in a Arduino base project, I can't use boost::bind
Could you please help me ?
Thanks.
class Class2 {
typedef void(*MyFunction) (int what);
MyFunction fn_;
public:
Class2(MyFunction fn) : fn_(fn) {}
void invoke(int val) {
fn_(val);
}
};
class Class3 {
Class2* class2_;
public:
Class3() {
class2_ = new Class2(myFunction);
class2_->invoke(12);
}
void myFunction(int what) {
// Do some work
}
};
void test2() {
Class3 instance3;
}
How about using an interface for that:
class ClassWithFunction {
public:
virtual void myFunction(int what) = 0;
}
class Class2 {
ClassWithFunction* fn_;
public:
Class2(MyFunction* fn) : fn_(fn) {}
void invoke(int val) {
fn_->myFunction(val);
}
};
class Class3 : ClassWithFunction {
Class2* class2_;
public:
Class3() {
class2_ = new Class2(this);
class2_->invoke(12);
}
void myFunction(int what) {
// Do some work
}
};
You need to use pointer to member function.
class Class3;
class Class2 {
typedef void(Class3::*MyFunction) (int);
MyFunction fn_;
public:
Class2(MyFunction fn) : fn_(fn) {}
void invoke(Class3 *p, int val) {
(p->*fn_)(val);
}
};
class Class3 {
Class2* class2_;
public:
Class3() {
class2_ = new Class2(&Class3::myFunction);
class2_->invoke(this, 12);
}
void myFunction(int what) {
// Do some work
}
};
If you want that Class2 accepts any callable object with signature void(int), then class template, function wrapper, lambda expression etc. will help.
The programm below is about polymorphism. It just changes the status of a door between open and closed. My problem is that i can't switch the status in my class "Open" to closed since the class "Close" is below my class "Open".
How can i forward declare the class "Close" that it will work properly? (since a normal forward declaration like 'class Close;' doesnt seem to work)
class Status;
class Door {
private:
Status* currentStatus;
public:
void setStatus(Status*);
void opendoor();
void closedoor();
};
class Status {
public:
virtual void opendoor(Door* s)=0;
virtual void closedoor(Door* s) = 0;
};
class Open : public Status {
public:
void opendoor(Door* s) {
return;
}
void closedoor(Door* s){
s->setStatus( new Close() ); //Error here
return;
}
};
class Close : public Status {
public:
void opendoor(Door* s) {
s->setStatus( new Open() );
return;
}
void closedoor(Door* s){
return;
}
};
void Door::opendoor() {
currentStatus->opendoor(this);
return;
}
void Door::closedoor(){
currentStatus->closedoor(this);
return;
}
void Door::setStatus(Status* x) {
delete currentStatus;
currentStatus = x;
return;
}
The easiest would be to separate the class from the implementation: first declare all the classes. Then only the implementation of the member functions.
class Status;
class Door {
...
};
class Status {
...
};
class Open : public Status {
public:
void opendoor(Door* s) override;
void closedoor(Door* s) override;
};
class Close : public Status {
public:
void opendoor(Door* s) override;
void closedoor(Door* s) override;
};
...
void Open::closedoor(Door* s){
s->setStatus( new Close() ); //no more error here
return;
}
Define the member function that needs the full definition of Close after the full implementation of Close. For example,
void Open::closedoor(Door* s)
should be defined outside your class, after class Close. That's because in the line
s->setStatus( new Close() )
the compiler needs to know the full definition of Close, as it tries to constructs an object of type Close.
I have a class hierarchy like:
class A {
list<A*> children;
public:
void update() {
do_something();
update_current();
for(auto child : children)
children->update();
}
protected:
virtual void update_current() {};
};
class B : public A {
protected:
void update_current() override {
do_something_important();
};
};
class C1 : public B {
protected:
void update_current() override {
B::update_current();
do_something_very_important();
};
};
class C2 : public B {
protected:
void update_current() override {
B::update_current();
do_something_very_important_2();
};
};
int main() {
A* a = new A();
//fill a's childred list somehow
while(come_condition) {
//some code
a.update();
//something else
}
return 0;
}
The question is: how can I remove duplicate B::update_current(); calls from derived classes without changing program's behaviour? Is it possible or are there no solutions except calling base class functions manually? Thank you.
You could make B's children override a different function:
class B : public A {
protected:
void update_current() override final {
do_something_important();
do_something_important_later();
};
virtual void do_something_important_later() = 0;
};
With:
class C2 : public B {
protected:
void do_something_important_later() override {
do_something_very_important_2();
};
};
There is a nice state machine tutorial called UML Tutorial: Finite State Machines by Robert C. Martin. But I can't compile the sample code it provides. I got *FsmTest.cpp(46) : error C2664: 'SetState' : cannot convert parameter 1 from 'class UnlockedState *' to 'class TurnstileState '
Please, help. Thanks.
class Turnstile
{
public:
virtual void Lock();
virtual void Unlock();
virtual void Thankyou();
virtual void Alarm();
};
class TurnstileFSM;
class LockedState;
class UnlockedState;
class TurnstileState
{
public:
virtual void Coin(TurnstileFSM*) = 0;
virtual void Pass(TurnstileFSM*) = 0;
protected:
static LockedState lockedState;
static UnlockedState unlockedState;
};
class TurnstileFSM : public Turnstile
{
public:
void SetState(TurnstileState* s) {itsState = s;}
void Coin() {itsState->Coin(this);}
void Pass() {itsState->Pass(this);}
private:
TurnstileState *itsState;
};
class LockedState : public TurnstileState
{
public:
virtual void Coin(TurnstileFSM* t)
{
t->SetState(&unlockedState);
t->Unlock();
}
virtual void Pass(TurnstileFSM* t)
{
t->Alarm();
}
};
class UnlockedState : public TurnstileState
{
public:
virtual void Coin(TurnstileFSM* t)
{
t->Thankyou();
}
virtual void Pass(TurnstileFSM* t)
{
t->SetState(&lockedState);
t->Lock();
}
};
LockedState TurnstileState::lockedState;
UnlockedState TurnstileState::unlockedState;
The problem is that when you try to call SetState() inside of LockedState::Coin(), the class UnlockedState is an incomplete type: it has been declared but not defined. In order to fix it, you'll need to move the definition of of Coin() to after that of UnlockedState:
class LockedState : public TurnstileState
{
public:
virtual void Coin(TurnstileFSM* t);
...
};
class UnlockedState : public TurnstileState
{
...
};
void LockedState::Coin(TurnstileFSM* t)
{
...
}
Most likely this is because it does not know UnlockedState is a subclass of TurnstileState yet. Remove the function from inside the class to the end of the file:
class TurnstileFSM {
void SetState(TurnstileState* s);
};
void TurnstileFSM::SetState(TurnstileState* s) {itsState = s;}
In the example, the generated code should include the tscontext.h, and the TurnStyle class is derived from the context, which should be declared in *tscontext.h" as class TurnStyleContext.
In my case the generated code looks like this:
#include "tscontext.h" // the header file name for the context class"
// Forward Declarations
class TurnStyle;
//----------------------------------------------
// TurnStyleState: The base state class
//----------------------------------------------
class TurnStyleState
{
public:
virtual const char* StateName() const = 0;
virtual void Coin( TurnStyle& );
virtual void Pass( TurnStyle& );
};
//----------------------------------------------
// State: Unlocked
//----------------------------------------------
class TurnStyleUnlockedState : public TurnStyleState
{
public:
virtual const char* StateName() const
{ return "Unlocked"; }
virtual void Pass( TurnStyle& );
virtual void Coin( TurnStyle& );
};
//----------------------------------------------
// State: Locked
//----------------------------------------------
class TurnStyleLockedState : public TurnStyleState
{
public:
virtual const char* StateName() const
{ return "Locked"; }
virtual void Coin( TurnStyle& );
virtual void Pass( TurnStyle& );
};
//----------------------------------------------
// TurnStyle: The Finite State Machine class
//----------------------------------------------
class TurnStyle: public TurnStyleContext
{
public:
// Static State variables
static TurnStyleUnlockedState Unlocked;
static TurnStyleLockedState Locked;
TurnStyle(); // default Constructor
// Event functions
virtual void Coin() { itsState->Coin( *this ); }
virtual void Pass() { itsState->Pass( *this ); }
// State Accessor functions
void SetState( TurnStyleState& theState ) { itsState = &theState; }
TurnStyleState& GetState() const { return *itsState; }
const char* GetCurrentStateName() const { return itsState->StateName(); }
const char* GetVersion() const;
private:
TurnStyleState* itsState;
};
with the state machine defined this way:
Context TurnStyleContext // the name of the context class
FSMName TurnStyle // the name of the FSM to create
Initial Locked // the name of the initial state
// for C++ output
pragma Header tscontext.h" // the header file name for the context class, note the necessary "
{
Locked
{
Coin Unlocked Unlock
Pass Locked Alarm
}
Unlocked <BeforeUnlocked >AfterUnlocked
{
Coin Unlocked Thankyou
Pass Locked Lock
}
}
The context implements FSMError, Thankyou, Lock, Alarm, Unlock, BeforeUnlocked, AfterUnlocked