PDA

Visualizza la versione completa : [c++]Controller e std::function o memfun


giuseppe500
19-10-2012, 20:34
ciao.
Detto bevemente sto implementando un sistema per inserire oggetti grafici su un area opengl.
Il sistema grafico funziona ed è in opengl(ho gestito i vari oggetti buffer,texture,color ecc..).
Per adesso volevo poter inserire la linea e il punto per semplicità , e sto cercando di trovare un meccanismo solido per , in futuro aggiungere le CEntity che mi pare.

Un punto o una linea sono CEntity e ogni CEntity ha un suo controller(tipo MVC) che non è nient altro che una serie di funzioni che vanno a modificare le caratteristiche grafiche del punto o della linea.
Questo controller è alla fine una semplice classe con dei metodi ma puo essere diverso a seconda dell' entità.
ad es:


class CControllerLine
{
public:
CControllerLine();
Move(int x, int y){...implementazione};
SetColor(int color){...implementazione};
Scale(float toX, float toY){...implementazione}
Rotate(float angle){...implementazione}

};
class CControllerPoint
{
public:
CControllerLine();
Move(int x, int y){...implementazione};
SetColor(int color){...implementazione};
Scale(float toX, float toY){...implementazione}
//Rotate(float angle){ATTENZIONE Inutile su un punto non è compatibile non la trovo e //agisco di conseguenza disabilitando il menu del context menu}

};


Alla fine volevo gestire il tutto con i function object std::function o std::memfun, non riesco bene a capire la differenza tra i due.
Io vorrei settare un functional corrente(compatibile dopo il bind dei parametri con tutti i possibili modificatori: colore,scala,posizione ecc...) e fare il bind come mi è stato insegnato in questo forum da shodan in modo che se il tipo di ritorno è void, e lo sarà, posso dichiarare un function generico dove si inseriranno a seconda delle scelte (tramite pulsanti e altri widget) delle std::function diverse contenute direttamente nel widget ereditato con una proprietà Function.
Quando scelgo un azione premendo il button "Azione" mi basterà fare il bind sulla classe(il controller)contenuto nella CEntity(trovero' il puntatore ad essa con un sistema di picking in opengl) e all' interno del controller gestirò le modifiche alla CEntity e alla sua rappresentazione grafica a seconda di quello che faccio nella ui.
Mi serirebbe un unica cosa: è possibile sapere se su un dato controller esiste un metodo(una funzione membro) o meno?
mi servirebbe davvero tanto, potrei personalizzzare ad es un context menu o in generale l'interfaccia "polimorficamente" con le azioni possibili abilitate e quelle non possibili disabilitate a seconda se esiste la funzione di modifica o meno.
Ed eviterei casini.
I controller e tutte le altre classi di cui non ho parlato sono policy(passo il tipo di controller come parametro template).
ciao.
grazie.

shodan
19-10-2012, 21:32
Originariamente inviato da giuseppe500
Mi serirebbe un unica cosa: è possibile sapere se su un dato controller esiste un metodo(una funzione membro) o meno?

Se i tuoi controller fossero template: si, usando SFINAE e un paio di barbatrucchi.
Non essendo template la risposta è: dipende.
Visto che usi solo VC++ puoi adoperare una keyword proprietaria del compilatore.
http://msdn.microsoft.com/en-us/library/x7wy9xh3%28VS.80%29.aspx
Leggi bene come e quando si usa.
N.B. Non esiste un "else", quindi occhio a non conforderti.

giuseppe500
20-10-2012, 00:00
ho letto, shodan e mi piace poco perchè non è portabile, ma è possibile utilizzarla grazie.
Cosa intendi per


Se i tuoi controller fossero template


i miei controller sono template , assemblo le classi con le policy e il controller è uno di queste policy cosi:
per es per un entity Line ho


template<class Controller, Class Model, class View>
class CLine
{
......
}

ho scritto:


I controller e tutte le altre classi di cui non ho parlato sono policy(passo il tipo di controller come parametro template).


ma non ho capito probabilmente cosa intendi.

comunque grazie.

Who am I
20-10-2012, 00:11
Ho già fatto una cosa del genere con OpenGL.
Tutto il problema sta nell' aggirare il fatto che in C++ il binding è statico, per cui usi un puntatore a funzione che nel costruttore della classe da cui derivano tutti i tuoi widget, fai puntare a una funzione che poi richiama il metodo della classe principale che gestisce l' azione.
Ogni sottoclasse nel costruttore cambia il valore di questo puntatore a funzione in modo da farlo puntare alla sua funzione.Funzione che richiama il metodo della classe, per cui è come se avessi un metodo dinamico come in Java.
Per sapere quali classi hanno un dato metodo ti affidi alla classi astratte, che sono la versione meno evoluta delle interfacce di Java per il C++.
Tutte le classi che ereditano da quella classe devono avere quel metodo, poi indipendentemente dalla lunghezza della gerarchia, ogni classe decide se fare o meno overriding di quel metodo.Potrebbe anche non farlo ed eseguire quello della sottoclasse.

shodan
20-10-2012, 00:18
Mi riferivo alle classi: CControllerLine e CControllerPoint, che non sono template (o almeno non le hai presentate come tali) e che dal tuo commento sono quelle di cui vorresti controllare l'esistenza della funzione.
Tuttavia dato che diventano un parametro di un template, forse qualcosa si può fare.

giuseppe500
20-10-2012, 13:19
Originariamente inviato da Who am I
Per sapere quali classi hanno un dato metodo ti affidi alla classi astratte, che sono la versione meno evoluta delle interfacce di Java per il C++.
Tutte le classi che ereditano da quella classe devono avere quel metodo, poi indipendentemente dalla lunghezza della gerarchia, ogni classe decide se fare o meno overriding di quel metodo.Potrebbe anche non farlo ed eseguire quello della sottoclasse.

il fatto è che per sapere se una classe ha quel metodo devo sapere che interfaccia implementa(o classe astratta)sbaglio Who am I ? e questo in java si puo fare con la keyword instanceof(penso)
in c++ questo non si puo fare, forse si potrebbe usare il dynamic_cast ma non penso sia una cosa completamente ad oggetti chiedersi se la classe implementa un interfaccia e agire di conseguenza.
deve essere l'oggetto che agisce in seguito alla chiamata di un metodo in modo differente o meno.
E' per questo che mi sto chiedendo se la mia domanda non sia in realtà una "cattiva domanda" cioè fuori dall astrazione degli oggetti.
non so .
O percaso intendevi dire di ereditare i controller da una classe astratta base e implementare solo le funzioni che voglio che facciano qualcosa?
questa potrebbe essere una soluzione, prezzo un interfaccia base che potrebbe essere grandissima e che comunque non conosco a priori se una classe ha o meno quel metodo , il metodo semplicemente puo fare qualcosa o meno.
è cosi' quello che intendevi?


Tuttavia dato che diventano un parametro di un template, forse qualcosa si può fare.
shodan mi puoi dare un aiuto o dirmi se è una cattiva domanda cosi la pianto di cercare?
comunque grazie a tutti e due, intanto ci penso un po su.


ciao.

shodan
20-10-2012, 13:33
Originariamente inviato da giuseppe500
mi puoi dare un aiuto o dirmi se è una cattiva domanda cosi la pianto di cercare?
comunque grazie a tutti e due, intanto ci penso un po su.

Non è una cattiva domanda, anzi. Il fatto è che la soluzione non è proprio così immediata e ci sto ancora lavorando per renderla più elastica possibile.

giuseppe500
20-10-2012, 14:30
Magari,spero, possa servire anche a qualcun altro sul forum.
ciao.

Who am I
21-10-2012, 01:15
Originariamente inviato da giuseppe500
il fatto è che per sapere se una classe ha quel metodo devo sapere che interfaccia implementa(o classe astratta)sbaglio Who am I ? e questo in java si puo fare con la keyword instanceof(penso)
in c++ questo non si puo fare, forse si potrebbe usare il dynamic_cast ma non penso sia una cosa completamente ad oggetti chiedersi se la classe implementa un interfaccia e agire di conseguenza.
deve essere l'oggetto che agisce in seguito alla chiamata di un metodo in modo differente o meno.
E' per questo che mi sto chiedendo se la mia domanda non sia in realtà una "cattiva domanda" cioè fuori dall astrazione degli oggetti.
non so .
O percaso intendevi dire di ereditare i controller da una classe astratta base e implementare solo le funzioni che voglio che facciano qualcosa?
questa potrebbe essere una soluzione, prezzo un interfaccia base che potrebbe essere grandissima e che comunque non conosco a priori se una classe ha o meno quel metodo , il metodo semplicemente puo fare qualcosa o meno.
è cosi' quello che intendevi?



Te la cavi passando un oggetto del tipo della classe base, che è astratta.
Così sei sicuro che tutti gli oggetti rispondono a quel metodo, e lo fanno in maniera dinamica.Non ti servirà usare il dynamic cast, e soprattutto, se vuoi ereditare da una classe che eredita dalla classe base astratta, ti basta che nel costruttore assegni il puntatore a funzione alla funzione giusta, che richiama quel metodo, ed è fatta.
In pratica in C++ la chiamata dinamica dei metodo come in Java si può simulare.
D' altronde secondo il mio concetto di OOP non ha senso chiamare i metodi staticamente.
Ogni oggetto dovrebbe rispondere a seconda del tipo che è, indipendentemente dal tipo del riferimento che si usa per l' accesso all' oggetto.

giuseppe500
21-10-2012, 12:12
grazie Who am I, adesso ho capito cosa intendi , secondo me è un buon metodo .
ciao.

Loading