View Full Version : [C++]array di puntatori a funzione in una classe-help!
Buongiorno,
Vi scrivo per chiederVi consiglio, ecco in breve il mio problema:
necessito di realizzare una classe (Con interfaccia de implementazione separate) che consentano l'uso di un menu controllato da un vettore di puntatori a funzione
(Per chi conosce il libro "C++ fondamenti di programmazione" della apogeo, autori Deitel & Deitel, sto parlando dell'esercizio 8.28)
In breve, quello che mi serve è riuscire a far funzionare una cosa del genere, al quale certamente mancherà della roba:
//Classe.h
class Classe
{
public:
classe();
void menuPrincipale();
void funzione0(); // stampa "funzione0"
void funzione1(); // stampa "funzione1"
void funzione2(); // termina la sessione
private:
bool continua;
};
//Classe.cpp
#include <iostream>
using std::endl;
using std::cin;
using std::cout;
#include "Classe.h" /* ovviamente salverò header e implementazione nella
stessa directory */
Classe::Classe()
{
void (*vettore[3])() = {funzione0, funzione1, funzione2}; /* ecco, Il
problema sta qui: questa dovrebbe essere la dichiarazione di un
vettore di tre puntatori a funzioni, ma non riesco a capire DOVE va
dichiarato, ne COME!!! */
continua = true;
cout << "Speriamo funzioni! :( \n";
}
void Classe::menuPrincipale()
{
int scelta;
cout << "Inserire un numero tra zero ed uno, due per uscire: ";
cin >> scelta;
while(continua != false)
{
if((scelta >= 0) && (scelta < 3))
{
(*vettore[scelta])();
cout << "Inserire un numero tra zero ed uno, due per uscire: ";
cin >> scelta;
}
else
{
cout << scelta << " : opzione non valida\n"
<< "Inserire un numero tra zero ed uno, due per uscire: ";
cin >> scelta;
} // fine dell'if/else
} // fine del while
}
void Classe::funzione0()
{
cout << "Hai selezionato la prima funzione\n";
}
void Classe::funzione1()
{
cout << "hai selezionato la seconda funzione\n";
}
void Classe::funzione2()
{
continua = false;
}
//main che usa il tutto
#include "Classe.h"
int main()
{
classe miaClasse;
miaClasse.menuPrincipale;
system("PAUSE");
return 0;
}
Se per favore riusciste a dirmi come modificare il tutto in modo che il programma possa essere compilato e funzionare correttamente (Io uso DEV C++) e come dichiarare anche nel file di intestazione "Classe.h" la presenza del vettore di puntatori (Ci ho provato in varie maniere ma il compilatore mi dava delle diversità tra i dati Dichiarati e quelli effettivamente usati, o almeno questo è quello che ho capito *_*) Ve ne sarei molto grato. Ho provato anche ad inserire la dichiarazione del vettore all'interno del Main ma essendo il vettore di puntatori utilizzato all'interno della classe anche lì esce fuori il comprensibile errore di compilazione, mentre spostare tutto il corpo del while presente nella funzione "menuPrincipale()" all'interno del main farebbe perdere ogni significato alla classe stessa.
Spero possiate aiutarmi :) Certo della Vostra collaborazione Vi ringrazio anticipatamente, scusandomi per la mia scarsa preparazione in materia :(
Distinti saluti, a presto.
DanieleC88
16-10-2008, 19:15
Io direi di fare così:
// Questo va nell'header
typedef void (*f_callback)(); // così definisci il tipo "f_callback" come puntatore a funzione
class Classe
{
public:
Classe();
~Classe();
void funzione0();
void funzione1();
void funzione2();
private:
f_callback *aFunzioni;
};
Poi:
// Questo va nel sorgente
Classe::Classe()
{
aFunzioni = new f_callback[3];
if (!aFunzioni)
{
cerr << "Allocazione fallita" << endl;
}
aFunzioni[0] = &funzione0;
aFunzioni[1] = &funzione1;
aFunzioni[2] = &funzione2;
}
Classe::~Classe()
{
if (aFunzioni)
{
delete aFunzioni;
}
}
Così il codice che avrà bisogno di accedere alle varie funzioni potrà farlo accedendo all'array (che è un campo privato, quindi visibile solo dall'interno della classe).
P.S.: finisci il progetto o quello che stai studiando, e appena avrai tempo libero prova a dare un'occhiata a Code::Blocks invece che Dev-C++. È decisamente migliore. ;)
Vincenzo1968
16-10-2008, 19:18
Questa è la mia soluzione:
#include <iostream>
using std::endl;
using std::cin;
using std::cout;
class Classe
{
public:
Classe();
void menuPrincipale();
void funzione0(); // stampa "funzione0"
void funzione1(); // stampa "funzione1"
void funzione2(); // termina la sessione
private:
bool continua;
void (Classe::*vettore[3])();
};
Classe::Classe()
{
//void (*vettore[3])() = {funzione0, funzione1, funzione2};
vettore[0] = &Classe::funzione0;
vettore[1] = &Classe::funzione1;
vettore[2] = &Classe::funzione2;
continua = true;
cout << "Speriamo funzioni! :( \n";
}
void Classe::menuPrincipale()
{
int scelta;
cout << "Inserire un numero tra zero ed uno, due per uscire: ";
cin >> scelta;
while(continua != false)
{
if((scelta >= 0) && (scelta < 3))
{
(this->*vettore[scelta])();
cout << "Inserire un numero tra zero ed uno, due per uscire: ";
cin >> scelta;
}
else
{
cout << scelta << " : opzione non valida\n"
<< "Inserire un numero tra zero ed uno, due per uscire: ";
cin >> scelta;
} // fine dell'if/else
} // fine del while
}
void Classe::funzione0()
{
cout << "Hai selezionato la prima funzione\n";
}
void Classe::funzione1()
{
cout << "hai selezionato la seconda funzione\n";
}
void Classe::funzione2()
{
continua = false;
}
int main()
{
Classe miaClasse;
miaClasse.menuPrincipale();
system("PAUSE");
return 0;
}
||ElChE||88
16-10-2008, 19:19
Io direi di fare così:
aFunzioni = new f_callback[3];
if (!aFunzioni)
{
cerr << "Allocazione fallita" << endl;
}
Sbaglio o manca un (std::nothrow)?
DanieleC88
16-10-2008, 19:44
Sbaglio o manca un (std::nothrow)?
In effetti sì, manca. Sono ancora troppo abituato alla malloc() del C. :asd:
Questa è la mia soluzione:
FUNZIONA!!!
(vabè, con qualche piccolo inconveniente, mi tocca digitare due volte due per uscire, ma quelli son dettagli)
Non avevo la minima idea di Come dichiadare il vettore di puntatori, adesso ho le idee un po' più chiare, grazie :)
Ho scelto la tua soluzione perchè bene o male non fa ricorso ad istruzioni che non conosco (std::nothrow???) ma anche la soluzione col typedef era pensata bene. Io non ci sarei mai arrivato.
Vi ringrazio ancora tutti, a presto!
Ho parlato troppo presto :sofico:
Vedo che anche nella soluzone sopra c'è una istruzione che non conosco: "this->"... Come funziona? :confused:
DanieleC88
16-10-2008, 21:04
Ho scelto la tua soluzione perchè bene o male non fa ricorso ad istruzioni che non conosco (std::nothrow???)
Il nothrow lo si usa quando si chiama la new:
int *variabile = new (nothrow) int[100];
Serve solo a dire al compilatore di non lanciare eccezioni se l'allocazione della memoria fallisce (il comportamento di default del compilatore è di far lanciare eccezioni in tal caso, ma nel mio esempio ho voluto gestire a mano la condizione d'errore).
ma anche la soluzione col typedef era pensata bene. Io non ci sarei mai arrivato.
Si può fare anche senza, ma così è molto più leggibile e pratico (è solo "syntactic sugar").
ciao ;)
DanieleC88
16-10-2008, 21:07
Ho parlato troppo presto :sofico:
Vedo che anche nella soluzone sopra c'è una istruzione che non conosco: "this->"... Come funziona? :confused:
La parola chiave this non è altro che un puntatore all'istanza corrente di un oggetto della classe (all'interno di un oggetto, "punta a se stesso"). IMHO si poteva anche scrivere senza quel "this->". ;)
tomminno
16-10-2008, 21:11
Ho parlato troppo presto :sofico:
Vedo che anche nella soluzone sopra c'è una istruzione che non conosco: "this->"... Come funziona? :confused:
Scusa ma vuoi fare un array di puntatori a metodo (che non sono esattamente dei puntatori a funzione ma qualcosa di sintatticamente e logicamente più complesso) e non sai cosa significa "this->"?
Conosco l'operatore freccia dal C, ma il "this" è la prima volta che lo vedo :(
E quel programma, senza il this, non funziona, quindi significa che occorre inserirlo.
L'operatore puntatore a struttura accede ai membri di una struttura attraverso un puntatore alla stessa" ("C, corso completo di programmazione", edizioni apogeo. Autori: Deitel & Deitel, pg 352) quindi se ho ben capito "this" funziona da puntatore a quello che indica la freccia (l'operatore puntatore a struttura insomma). indipendentemente dal tipo di dato a cui punta, giusto? Nel caso sopra puntava ad un elemento di un vettore che a sua volta conteneva l'indirizzo di una funzione, che quindi viene eseguita.
Ho capito bene? Cercherò di fare qualche prova comunque :)
Bhe' il this e' una parola chiave del c++. E' un puntatore all'oggetto che invoca il metodo. Per comodita' molte volte viene omesso, ma e' implicito. Forse e' per questo che non l'hai visto. Scusa ma conosci qualcosa di programmazione ad oggetti?
Molto poco, lo confesso. Sto studiando il libro suddetto ("C++ fondamenti di programmazione") e anche se non devo diventare un ingegnere informatico (Ma bensì elettronico :) prima o poi!!! :cry: ) gradirei imprarle bene certe cose, almeno a livello concettuale, che tanto ormai molte applicazioni sono fatte tramite programmazione di DSP e simili, quindi presto o tardi me le ritroverò in un futuro professionale.
Ma quindi, tornando alla istruzione this, la si può usare solo con gli oggetti? Qual'è esattamente la sua sintassi? E perchè nell'esempio sopra se viene omesso il compilatore mi da errore? :help:
Bhe' dimmi cosa hai scritto di preciso... a naso credo di tratti un problema di precedenza di operatori.
Scusa mi ero dimenticato parte della domanda. Si', il this ha senso solo con la programmazione ad oggetti.
Nel programma suggeritomi dal Sig. VIncenzo1968 nella funzione "MenuPrincipale()" della classe c'è la seguente istruzione:
(this->*vettore[scelta])();
dove compare appunto detto operatore. Togliendolo il compilatore segnala un errore, segno questo che è necessario. Comincio a capire comunque: se avessi scritto semplicemente " vettore[scelta] " non avrebbe avuto senso perchè occorreva che Qualcosa facesse quello che stava scritto nella locazione puntata dall'elemento selezionato nel vettore, e questo "Qualcosa" è appunto l'operatore this... Continuo a cercare a giro chiarimenti al riguardo ma non sto trovando molto :muro:
Vincenzo1968
16-10-2008, 23:01
Nel programma suggeritomi dal Sig. VIncenzo1968 nella funzione "MenuPrincipale()" della classe c'è la seguente istruzione:
(this->*vettore[scelta])();
dove compare appunto detto operatore. Togliendolo il compilatore segnala un errore, segno questo che è necessario. Comincio a capire comunque: se avessi scritto semplicemente " vettore[scelta] " non avrebbe avuto senso perchè occorreva che Qualcosa facesse quello che stava scritto nella locazione puntata dall'elemento selezionato nel vettore, e questo "Qualcosa" è appunto l'operatore this... Continuo a cercare a giro chiarimenti al riguardo ma non sto trovando molto :muro:
Ciao Lombo,
grazie per il Sig. Vincenzo1968 :) ma dammi del tu, lo preferisco ;)
Compilando col visual studio senza l'operatore this, l'errore segnalato è questo:
C2171 -> A unary operator is used with an invalid operand type.
Su msdn viene fornito questo esempio:
// C2171_b.cpp
// compile with: /c
class A {
public:
A() { STF( &A::D ); }
void D() {}
void DTF() {
(*TF)(); // C2171
(this->*TF)(); // OK
}
void STF(void (A::*fnc)()) {
TF = fnc;
}
private:
void (A::*TF)();
};
Purtroppo, la documentazione non si dilunga(anzi, non dice proprio un bel niente) sul perché sia necessario utilizzare quella sintassi.
Prova a fare una ricerca su google inserendo il codice dell'errore(o il messaggio).
Ciao :)
DanieleC88
16-10-2008, 23:21
Purtroppo, la documentazione non si dilunga(anzi, non dice proprio un bel niente) sul perché sia necessario utilizzare quella sintassi.
In effetti così è una cosa abbastanza criptica. Non avevo mai incontrato quella sintassi, ma provo a dare la mia interpretazione... Il metodo che avevo usato io accettava una qualsiasi funzione di prototipo void (*)(), la tua dovrebbe accettare solo funzioni con quel prototipo ed appartenenti alla classe Classe. Visto che i metodi non sono statici, devono essere già istanziati, e c'è bisogno di dire a quale oggetto fare riferimento.
Se ho detto qualche boiata, perdonatemi, non sono una cima già di mio, poi sono pure stanco ed ecco fatto. :D
ciao ;)
Sono riuscito ad inserire il codice suggeritomi nell'esercizio che mi interessava, ed ho anche capito come usarlo (Posso quindi replicarlo in altri esempi diversi, con piu funzioni ad esempio) e dal punto di vista funzionale basta questo :) quello che non ho capito è come Funziona questa istruzione, e come mai è necessaria... Ma ripeto: non devo diventare un ingegnere informatico :stordita: mi basta sapere come usare detta istruzione per creare classi simili a quella in esame in maniera bovina, per il resto pazienza :oink:
Grazie di Cuore a tutti, siete stati gentilissimi. Buonanotte.
Ti ripeto: per favore posta il codice e magari il messaggio di errore del compilatore, se no si rischia di far confusione.
Per cominciare il this NON e' un operatore, ma e' una parola chiave.
Poi prova a dar un'occhiata a questo link (http://www.bo.cnr.it/corsi-di-informatica/corsoCstandard/Lezioni/21Puntfunz.html)
Per la cronaca credo che l'utilizzo del this sia per motivi sintattici o implementativi: se tu avessi scritto vettore[scelta](), in teoria avrebbe funzionato se non fossimo stati in un contesto di classi.
Ti ripeto: per favore posta il codice e magari il messaggio di errore del compilatore, se no si rischia di far confusione.
Per cominciare il this NON e' un operatore, ma e' una parola chiave.
Poi prova a dar un'occhiata a questo link (http://www.bo.cnr.it/corsi-di-informatica/corsoCstandard/Lezioni/21Puntfunz.html)
Per la cronaca credo che l'utilizzo del this sia per motivi sintattici o implementativi: se tu avessi scritto vettore[scelta](), in teoria avrebbe funzionato se non fossimo stati in un contesto di classi.
Credo tu abbia ragione, perchè in un esempio fatto dal libro ma non implementato in classi (Il codice era tutto nel main) non c'era bisogno di simili intrecci.
"La Parola chiave this" si, scusatemi. :fagiano: Conosco la differenza, è che sono meno di un neofita in questo campo e mi confondo... Grazie di nuovo a tutti :)
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.