View Full Version : [C++] capire di che tipo è una classe
Damage92
29-08-2010, 19:28
Salve!
Sto usando il C++. Ho una lista di elementi eterogenei, tutti derivati dalla stessa classe (che è astratta). Devo eseguire un metodo di tutti gli elementi della lista usando un ciclo con un puntatore di tipo della classe base (se c'è un altro modo benvenga!), ma va eseguito solo su quelli di un certo tipo.
Però non so come riconoscere di che tipo è ogni elemento della lista...
Se può essere utile il metodo da eseguire è ereditato come virtuale dalla classe base.
Grazie!
http://msdn.microsoft.com/en-us/library/b2ay8610%28vs.71%29.aspx
http://msdn.microsoft.com/en-us/library/b2ay8610%28vs.71%29.aspx
Usare la RTTI dentro un ciclo su un array con parecchi elementi. Mi sembra proprio una buona idea :D
A parte la RTTI che la eviterei per motivi "idelogici" oltre che prestazionali, puoi sempre mettere il check del tipo corretto dentro il metodo virtuale, che non fa nulla se non è del tipo giusto.
Altrimenti puoi mettere nella classe base una stringa col tipo che viene riempita dalle classi figlie, e viene usata per il check.
Altrimenti... ce ne sono di modi :D
Di solito definendo meglio il problema puoi capire come evitare il riconoscimento della classe...
per esempio, perchè dato un array di classi base devi distinguerle a seconda della classe figlia?
Idealmente le classi figlie le tratti come la classe base senza saperne niente, quindi è già poco elegante dover distinguere.
banryu79
29-08-2010, 22:18
Visitor design pattern?
Se è questo il caso, a questa pagina (http://sourcemaking.com/design_patterns/visitor) trovi la spiegazione, e in calce link a vari esempi, tra cui alcuni in C++.
Damage92
30-08-2010, 09:54
Grazie a tutti per le risposte!
Sono ancora agli inizi, dunque non ho ben capito come funziona la RTTI... in pratica l'operatore typeid è in grado di determinare il tipo della classe?
Il visitor design pattern sembra interessante, ma penso mi ci vorrebbero ore per capirlo! Però, da quello che dice l'articolo di wikipedia, sembra una lettura utile :D
@Tommo
In effetti avevo pensato a queste due soluzioni, ma immaginavo che ci potesse essere già*uno strumento del linguaggio per fare ciò. Per ora ho implementato il metodo virtuale.
Per rispondere alla domanda, innanzitutto non è un array, ma una lista (un link vale mille parole: http://it.wikipedia.org/wiki/Struttura_dati#Lista).
Il programma è un lettore di feed rss... nella lista ci sono i feed, le cartelle, e altri elementi (cerca, segnalibri), e in futuro potrei aggiungerne altri...
Quando devo aggiornare tutti i feed, il metodo "aggiorna" deve essere chiamato solo sui feed, di certo non sulle cartelle :D
In effetti dubito che il modo in cui ho strutturato i dati in memoria sia... il migliore, ma non ho trovato un altro modo :fagiano:
A questo punto avrei una curiosità, cosa ti ha spinto a creare una superclasse per classi che a primo impatto non mi sembra abbiano nulla in comune?
Kralizek
30-08-2010, 13:54
A questo punto avrei una curiosità, cosa ti ha spinto a creare una superclasse per classi che a primo impatto non mi sembra abbiano nulla in comune?
ad occhio direi che vede una cartella ed un feed rss entrambi come un contenitore di "articoli"
Ok, ma il segnalibro a questo punto cosa avrebbe in comune con questi "contenitori"?
ad occhio direi che vede una cartella ed un feed rss entrambi come un contenitore di "articoli"
In ogni caso non vedo perché non avrebbe potuto mantenere una lista di cartelle ed una lista di feed separate...
Come in molti altri casi il problema è da affrontare altrove. Un collection così etorogenea non ha senso di esistere.
In ogni caso non vedo perché non avrebbe potuto mantenere una lista di cartelle ed una lista di feed separate...
Come in molti altri casi il problema è da affrontare altrove. Un collection così etorogenea non ha senso di esistere.
che è proprio quello che intendevo io...
IMHO la riflessività diventa utile solo quando si usano tipi generici, nelle normali gerarchie polimorfiche se serve è solo un problema di design :read:
Damage92
30-08-2010, 15:42
Hanno diverse cose in comune.
Sto utilizzando le gtkmm, e tutti gli elementi di questa lista vengono visualizzati in un albero (gtk::treeview). Per cui hanno in comune una stringa, un'icona, una variabile che identifica la linea nell'albero, e tre metodi relativi alla gui.
Le informazioni di ogni elemento sono scritte anche in un file xml, per cui hanno in comune una variabile (un tipo di libxml2) che mi permette di puntare velocemente ai dati scritti su disco.
Forse il vero errore che ho fatto è la scelta del tipo di struttura dati :fagiano:
Ho creato delle liste (ogni cartella punta ad un'altra lista) che rispecchia in memoria la gerarchia che gli elementi hanno nella gui.
Ho provato a cercare un modo per memorizzare gli elementi e poi, separatamente, descrivere la loro posizione nell'albero, ma non mi è venuto nulla in mente :(
Beh, perchè il metodo aggiorna deve essere chiamato sui feeds ma non sulle cartelle?
Mi sembra fattibilissimo fare un metodo aggiorna delle cartelle che non fa nulla :D
Sennò io farei così:
creerei una classe Updater, e una classe Listener (o Observer che dir si voglia) Updater::Listener.
Updater mantiene una lista di classi Listener, su cui chiama update quando l'applicazione gli viene richiesto tramite un metodo apposito.
Quindi, la tua classe principale possiede un Updater (o più di una, vedi se serve) in cui a loro volta vengono registrati i feeds e tutto quello che eredita Updater::Listener.
In questo modo tra l'altro separi la gestione della GUI e dell'albero dalla gestione degli updates, che sono due cose diverse...
Approvo l'observer. E' sicuramente il modo più semplice per operare su una architettura già "formata".
Un feed si registra sull'observer al momento della creazione e si deregistra al momento della distruzione.
tomminno
30-08-2010, 16:16
Hanno diverse cose in comune.
Sto utilizzando le gtkmm, e tutti gli elementi di questa lista vengono visualizzati in un albero (gtk::treeview). Per cui hanno in comune una stringa, un'icona, una variabile che identifica la linea nell'albero, e tre metodi relativi alla gui.
Le informazioni di ogni elemento sono scritte anche in un file xml, per cui hanno in comune una variabile (un tipo di libxml2) che mi permette di puntare velocemente ai dati scritti su disco.
Secondo me le hai infarcite troppo queste classi.
Sono classi che gestiscono sia la GUI che i dati. Insomma il solito calderone mono-tier ;)
Damage92
30-08-2010, 16:21
creerei una classe Updater, e una classe Listener (o Observer che dir si voglia) Updater::Listener.
Updater mantiene una lista di classi Listener, su cui chiama update quando l'applicazione gli viene richiesto tramite un metodo apposito.
In pratica una lista dei soli feed... in effetti è la soluzione più semplice :D
Ora ho implementato l'idea del metodo virtuale, anche perché mi sono reso conto che "aggiorna" su una cartella potrebbe significare "aggiorna tutti i feed contenuti nella cartella" :D
Ma quando si usano i doppi due punti (come Update::Listener) significa che Listener deriva da Updater? E perché usare una classe Listener, e non direttamente la classe Feed?
grazie a tutti :)
No, per avere una classe
Updater::Listener* qualcosa = new Updater::Listener()
devi scrivere una cosa tipo
class Updater
{
class Listener
{
...
};
...
};
Che non è una classe derivata ma "nested", cioè una dentro l'altra.
In realtà potevi fare anche una classe a parte, ma a me piace farlo così :D
Comunque il pattern Observer è si una lista dei soli feed, nel tuo caso, ma è anche molto di più (http://en.wikipedia.org/wiki/Observer_pattern).
Per esempio potresti renderti conto che vuoi altri oggetti aggiornabili oltre ai feeds, e funzionerebbe uguale. Oppure potresti gestire liste che si aggiornano in momenti diversi. eccetera...
Damage92
31-08-2010, 10:53
Che non è una classe derivata ma "nested", cioè una dentro l'altra.
In realtà potevi fare anche una classe a parte, ma a me piace farlo così :D
Comunque il pattern Observer è si una lista dei soli feed, nel tuo caso, ma è anche molto di più (http://en.wikipedia.org/wiki/Observer_pattern).
Per esempio potresti renderti conto che vuoi altri oggetti aggiornabili oltre ai feeds, e funzionerebbe uguale. Oppure potresti gestire liste che si aggiornano in momenti diversi. eccetera...
Questa della classe nested non la sapevo proprio! :D
Anche i Design Pattern e gli Anti-Pattern non li conoscevo!
Grazie mille! :)
vBulletin® v3.6.4, Copyright ©2000-2026, Jelsoft Enterprises Ltd.