Sì, questo è definitivamente possibile.
Ma ci sono due sfide da affrontare nel tuo progetto:
-
Close()
è una funzione membro. Quindi se il pulsante deve chiamare questa funzione membro, deve sapere su quale oggetto chiamarlo.
-
Se il pulsante successivo deve intervenire sulla chiamata, devi renderlo visibile in qualche modo nella tua architettura (o è un elemento della GUI che esegue l'azione quando è troncato, o dovrebbe essere accessibile pragrammaticamente all'interno del tuo codice.
Risponderò con C ++. Per il secondo argomento, nell'interesse della demo, presumo che il pulsante sia un membro pubblico di Game_Events.
Alternativa 1: approccio di base che elabora il puntatore della funzione
Se non hai bisogno di chiamare una funzione membro, cioè se Close()
potrebbe essere static
, il tuo codice potrebbe funzionare quasi come è, con alcune correzioni sintattiche minori:
class Button
{
private:
void (*f_m)();
public:
Button(void (*f)()) : f_m(f) {}
~Button(){}
void operator() () { f_m(); } // make button a callable (i.e. button() )
};
Demo online
Tuttavia, l'uso è limitato, perché CLose dovrebbe essere statico, quindi non potrebbe utilizzare alcun valore di vval dell'oggetto dipendente dall'evento. Che pessima
Alternativa 2: avvicinare l'astrazione della funzione da chiamare
Quindi rendiamolo un po 'più generale. Invece di usare un puntatore a funzione o un puntatore a funzione membro (che ci obbligherebbe a determinare la classe della funzione), potremmo usare la libreria funzionale di C ++, che permette di definire una funzione astratta ab:
#include <functional>
...
class Button
{
private:
function<void()> f_m;
public:
Button(function<void()> f) : f_m(f) {}
~Button(){}
void operator() () { f_m(); }
};
Quindi potresti creare un pulsante, con una flessibilità totale per la funzione che fornirai. Qui userò una funzione lambda:
class Game_Events
{
public:
Button* button;
Game_Events()
{
button = new Button([this]()->void{this->Close(); });
}
~Game_Events(){}
void Close(){ cout<<"Boum"<<endl;} //I need to pass this function for call it on the other side
};
Il requisito è che l'oggetto esista ancora quando il pulsante viene attivato.
demo online
Alternativa 3: schema di progettazione del comando
Questo è il mio approccio preferito: implementa il schema di comando .
Il principio generale è leggermente cambiato rispetto al tuo approccio originale, ma è più facile da gestire e molto potente:
- Avresti una classe
Command
astratta con una sola funzione membro virtuale: Execute()
.
- Il costruttore di pulsanti verrà creato con un puntatore a un oggetto
Command
astratto (anziché un puntatore a funzione).
- Quando il tuo pulsante è attivo, chiama solo
Execute()
per l'oggetto Command
.
- Avresti una classe
CloseGameEvent
che eredita da Command
. Il suo costruttore tiene traccia del Game_Event
e il suo overriden Execute()
chiamerebbe la funzione Close()
per esso.
- Quando costruisci il tuo oggetto pulsante, devi quindi passarlo al
CloseGameEvent
pertinente.