View Full Version : [C++] matrice punt a funzioni e dintorni ...
trallallero
08-01-2008, 11:29
Non riesco a copiare una matrice di puntatori a funzione in un'altra matrice.
Quì il codice, in un modulo ho:
typedef int LLLtgStates;
typedef void (*Buttons)(LLLtgStates [4][4]);
Buttons LtgButt[4][4] =
{
{ Button_0_0, Button_0_1, Button_0_2, Button_0_3 },
{ Button_1_0, Button_1_1, Button_1_2, Button_1_3 },
{ Button_2_0, Button_2_1, Button_2_2, Button_2_3 },
{ Button_3_0, Button_3_1, Button_3_2, Button_3_3 }
};
Nell'altro voglio copiarmi il contenuto della matrice LtgButt in m_Buttons che è un membro di una classe, dichiarato come segue:
Buttons m_Buttons[4][4];
ho provato con una memcpy:
memcpy( reinterpret_cast<void*>(m_Buttons),
reinterpret_cast<void*>(LtgButt),
sizeof(LtgButt) );
ma vedo che non va, il puntatore di m_Buttons[0][0] è <> da LtgButt[0][0]
allora ho provato con un for:
for (int y = 0; y < 4; ++y)
for (int x = 0; x < 4; ++x)
m_Buttons[y][x] = LtgButt[y][x];
ma mi da un errore:
pointer to a function used in arithmetic
dove sbaglio ? :help:
grazie
trallallero
08-01-2008, 11:33
ma che scemo!!! :stordita:
appena inviata la domanda ho visto che nel modulo ho dichiarato
extern Buttons LtgButt;
anzichè
extern Buttons LtgButt[4][4];
vabbè, si può chiudere, grazie lo stesso :)
trallallero
08-01-2008, 11:40
a questo punto ne approfitto per una domandina:
avendo questi 2 tipi:
typedef int LLDeviceId;
typedef void (*Buttons)(LLLtgStates [4][4]);
quindi 2 matrici di quei tipi:
Buttons m_Buttons[4][4]; //!< a matrix of pointers to functions
LLDeviceId m_DevIds [4][4]; //!< a mtrix of device ids
posso fare una map dei 2 ?
quindi, in soldoni, si possono fare mappe di matrici ?
Cioè intendi: si possono fare mappe a 2 dimensioni ? In tal caso la risposta è sì...
trallallero
08-01-2008, 15:19
Cioè intendi: si possono fare mappe a 2 dimensioni ? In tal caso la risposta è sì...
non lo so neanche io, son completamente fuso! mi stan facendo fare una cosa allucinante! una logica di 30 pagine dove ci son 5 pannelli, ogni pannello 20 interruttori, ogni interruttore dipende dagli altri interruttori (anche di altri pannelli) e accende o spegne canali di comunicazione tra l'autista del carro armato o l'operatore o l'istruttore e vatte la pesca...
Poi ci sono le cuffie, i microfoni, i volumi, i led rossi, verdi, bianchi, switch BCD coded, frequenze Mh Kh e altro.
E devo fare sia il design che scrivere il codice. Entro Febbraio!
Ho fatto l'oggetto elemento, dentro l'oggetto device, dentro l'oggetto pannello e dentro l'oggetto unità.
Adesso nel pannello sto gestendo le devices (pulsanti) che son fisse, quindi ogni pulsante ha una funzione ed un ID.
Non ho più usato punt a funzione (stile C) ma a funzione di una classe.
Adesso vorrei collegare ogni ID al relativo puntatore, così quando mi arriva un msg con un certo ID, chiamo il relativo puntatore a membro senza doverlo cercare.
Potrei fare una matrice di IDs ma vorrei usare lo stesso sistema che ho usato nell altre classi (elemento, device etc) quindi mappe.
Non so se son stato chiaro ma son veramente fuso.
I puntatore a funzione ti sono serviti per associare una funzionalità ad un ID ?
Perché non usi un command pattern ?
Se non altro ti eviti di lavorare con i puntatori a funzione...
trallallero
09-01-2008, 07:48
Perché non usi un command pattern ?
Se non altro ti eviti di lavorare con i puntatori a funzione...
command pattern ?
dimmi dimmi
e scusa ma ieri alle 4 e mezza me ne sono andato a casa, troppo fuso (e a casa non ho internet)
Prima di tutto, visto che ora programmi ad oggetti ti consiglio di studiarti i design pattern ;) Quando sarai riuscito ad implementarne qualcuno vedrai che ti aiuteranno molto.
Immaginiamo che tu abbia una class Button che gestisce lo stato del bottone (la semplifico, servirebbe magari anche il testo visualizzato, l'eventuale icona e così via):
class Button
{
Command *command;
public:
Button(Command *command) { this->command = command };
void pressed() { command->execute()};
~Button() { delete command; };
};
Questo è il command pattern applicato:
class Command
{
public:
virtual void execute() = 0; //questa funzione virtuale pura rende la classe astratta
};
//ora deriviamo i vari comandi
class CopyCommand: public Command
{
System *mySystem;
public:
CopyCommand(System *mySystem) { this->mySystem = mySystem; };
virtual void execute() { mySystem->doACopy(); };
};
class PasteCommand: public Command
{
SecondSystem *otherSystem;
public:
CopyCommand(SecondSystem *otherSystem) { this->otherSystem = otherSystem; };
virtual void execute() { otherSystem->pasteIn(); };
};
//quando andrai a creare i bottoni
Button myButton1(new CopyCommand(mySystem));
Button myButton2(new PasteCommand(otherSystem));
System e SecondSystem non c'entrano niente, li ho usato solo per far vedere come è possibile sfruttare i comandi per inizializzarli con "parametri" diversi.
Il codice da eseguire con un dato comando va messo dentro ad execute.
Ora...questa è un'associazione statica dei bottoni al comando...ma si può anche fare un'associazione dinamica. Sei i comandi sono senza stato possiamo andarci a creare un pool di comandi da assegnare dinamicamente ai bottoni:
class Button
{
Command *command;
public:
Button(Command *command) { setCommand(command); };
void pressed() { command->execute()};
void setCommand(Command *command) { this->command = command; };
};
//mappa statica dei comandi, da deallocare alla fine dell'esecuzione
map<CommandType, Command *> commandMap;
commandMap[CommandType::Paste] = new PasteCommand(otherSystem);
commandMap[CommandType::Copy] = new CopyCommand(mySystem);
...
//inizializzazione dei bottoni
Button myButton1(commandMap[CommandType::Paste]);
Button myButton2(commandMap[CommandType::Copy]);
...
//quando vorrai cambiare la funzionalità di un bottone a runtime
myButton2.setCommand(commandMap[CommandType::Paste]);
trallallero
09-01-2008, 16:36
ho letto al volo anche perchè a quest'ora son sempre fuso, ma sembra figo.
In realtà io non ho pulsanti veri, ma gestisco solo la logica dei pulsanti.
Hardware <-> interfaccia <-> Logica -> comunicazione
Io sono la Logica, quindi ricevo un input che è la pressione dei pulsanti, volumi etc e setto degli stati, rispondo al mittente con un output (accendi il led, alza il volume etc) e imposto una matrice di comunicazione (tizio parla con altro tizio, device accende registrazione).
Però quello che mi hai scritto può andare bene (e anche se non dovesse me lo salvo per la prossima) perchè non ho i pulsanti ma una funzione per ognuno di essi, quindi è come se li avessi.
Grazie mille caro, ne sai sempre una più del diavolo :eek:
domani rileggo e studio con calma, se ho dubbi ... tienti pronto :D
PS: era da un pò che non lo facevo ma devo dire che "disegnare" e programmare ad oggetti è una figata!
Ah ok...quindi i bottoni non li devi premere te, ma a te arriva un id ed in base a quell'id cambi lo stato dei pulsanti visualizzati.
Ad esempio, potresti filtrare i comandi per id, ma anche modificare dinamicamente il comportamento di risposta ad un certo id, ad esempio a seguito dell'arrivo di un dato id.
Ovviamente CommandType è un enum.
class CommandFilter
{
typedef Map<CommandType, Command *>::iterator CommandsIt;
typedef Map<int, Command *>::iterator FilterIt;
Map<int, Command *> filterMap;
Map<CommandType, Command *> commandMap:
public:
CommandFilter();
void filter(int id, CommandType type);
void applyCommand(int id);
void applyCommand(CommandType type);
~CommandFilter();
};
CommandFilter::CommandFilter()
{
commandMap[CommandType::Fisrt] = new FirstCommand(this);
commandMap[CommandType::Second] = new SecondCommand();
commandMap[CommandType::Third] = new ThirdCommand();
....
}
void CommandFilter::filter(int id, CommandType type)
{
CommandsIt it = commandMap.find(type);
if(it == map::end)
throw new CommandNotLoadedException(type);
filterMap[id] = it->second;
}
void CommandFilter::applyCommand(int id)
{
FilterIt it = filterMap.find(id);
if(it == map::end)
throw new FilterNotLoadedException(id);
it->second->execute();
}
void CommandFilter::applyCommand(CommandType type)
{
CommandsIt it = commandMap.find(type);
if(it == map::end)
throw new CommandNotLoadedException(type);
it->second->execute();
}
//inizializzazione del filtro
CommandFilter filter;
filter.changeFilter(0, CommandType::First);
filter.changeFilter(1, CommandType::Second);
filter.changeFilter(5, CommandType::Third);
filter.changeFilter(7, CommandType::Other);
//ad esempio un comando che va a cambiare la reazione del filtro ad un dato ID
class FirstCommand: public Command
{
CommandFilter *commandFilter;
public:
CopyCommand(CommandFilter *commandFilter) { this->commandFilter = commandFilter; };
virtual void execute()
{
commandFilter->changeFilter(5, CommandType::Second);
}
};
//oppure un comand che va ad eseguire altri comandi
class SecondCommand: public Command
{
CommandFilter *commandFilter;
public:
CopyCommand(CommandFilter *commandFilter) { this->commandFilter = commandFilter; };
virtual void execute()
{
commandFilter->applyCommand(CommandType::Third);
commandFilter->applyCommand(CommandType::Other);
}
};
//ovviamente per filtrare un dato evento basta inserire:
filter.applyCommand(id);
trallallero
10-01-2008, 08:26
azz! questo 3d me lo salvo e lo chiudo in cassaforte :D
come si vede che hai lavorato parecchio ad oggetti ... anche io sto usando typedefs, enums e mappe ovunque ma alla fine si vede che non ho questa dimestichezza in relazionare gli oggetti come te.
Il problema adesso sarebbe modificare ciò che ho già fatto e applicare il tuo sistema, ma non c'è tempo. Comunque per Febbraio (che poi in realtà è Marzo) dobbiamo presentare un prototipo funzionante, dopo avremo tempo per perfezionare il tutto. E, anche se non ho molta esperienza in object oriented modeling, se c'è una cosa in cui vado forte è lo scrivere codice facilmente mantenibile e modificabile quindi, ripeto, mi tengo questi consigli da parte per il futuro. E grazie :)
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.