MagoAntò (Normal User)
Rookie
Messaggi: 42
Iscritto: 07/02/2009
|
Ciao a tutti!
Sto realizzando un programma in C++ per l'implementazione di un vocabolario mediante alberi Red Black. Nella traccia viene espressamente richiesto di fare uso dell'ereditarietà.
Ho strutturato il programma in questo modo:
Codice sorgente - presumibilmente C# |
class nodo_BST { protected: string chiave; nodo_BST *sx; nodo_BST *dx; nodo_BST *padre; public: nodo_BST() // Costruttore { chiave = ""; sx = NULL; dx = NULL; padre = NULL; } ~nodo_BST() // Distruttore { } string get_chiave() { return chiave; } void set_chiave(string c) { chiave = c; } nodo_BST* get_sx() { return sx; } void set_sx(nodo_BST *sinistra) { sx = sinistra; } nodo_BST* get_dx() { return dx; } void set_dx(nodo_BST *destra) { dx = destra; } nodo_BST* get_padre() { return padre; } void set_padre(nodo_BST *p) { padre = p; } }; class nodo_RB : public nodo_BST { private: colore c; public: nodo_RB():nodo_BST() // invoco il costruttore della superclasse { c = nero; } ~nodo_RB() { } colore get_color () { return c; } void set_color (colore colore_in) { c = colore_in; } };
|
Come potete vedere, la classe nodo_RB è una sottoclasse di nodo_BST. Il problema è il seguente: mettiamo caso che, per esempio, dopo aver creato un oggetto della classe nodo_RB, debba necessariamente invocare il metodo get_sx per conoscere il figlio sinistro del nodo corrente. Il compilatore mi da errore, dicendo che il metodo della superclasse restituisce un nodo_BST.
Come risolvere il problema?
Ho letto che può essere utilizzato il downcasting (magari quello dinamico che controlla pure se il tipo "castato" è effettivamente diventato quello richiesto) ma mi chiedevo se fosse possibile prendere un'altra strada.
Grazie in anticipo per le risposte!
|
|
lumo (Member)
Expert
Messaggi: 449
Iscritto: 18/04/2010
|
Postato originariamente da MagoAntò:
Ciao a tutti!
Sto realizzando un programma in C++ per l'implementazione di un vocabolario mediante alberi Red Black. Nella traccia viene espressamente richiesto di fare uso dell'ereditarietà.
Ho strutturato il programma in questo modo:
Codice sorgente - presumibilmente C# |
class nodo_BST { protected: string chiave; nodo_BST *sx; nodo_BST *dx; nodo_BST *padre; public: nodo_BST() // Costruttore { chiave = ""; sx = NULL; dx = NULL; padre = NULL; } ~nodo_BST() // Distruttore { } string get_chiave() { return chiave; } void set_chiave(string c) { chiave = c; } nodo_BST* get_sx() { return sx; } void set_sx(nodo_BST *sinistra) { sx = sinistra; } nodo_BST* get_dx() { return dx; } void set_dx(nodo_BST *destra) { dx = destra; } nodo_BST* get_padre() { return padre; } void set_padre(nodo_BST *p) { padre = p; } }; class nodo_RB : public nodo_BST { private: colore c; public: nodo_RB():nodo_BST() // invoco il costruttore della superclasse { c = nero; } ~nodo_RB() { } colore get_color () { return c; } void set_color (colore colore_in) { c = colore_in; } };
|
Come potete vedere, la classe nodo_RB è una sottoclasse di nodo_BST. Il problema è il seguente: mettiamo caso che, per esempio, dopo aver creato un oggetto della classe nodo_RB, debba necessariamente invocare il metodo get_sx per conoscere il figlio sinistro del nodo corrente. Il compilatore mi da errore, dicendo che il metodo della superclasse restituisce un nodo_BST.
Come risolvere il problema?
Ho letto che può essere utilizzato il downcasting (magari quello dinamico che controlla pure se il tipo "castato" è effettivamente diventato quello richiesto) ma mi chiedevo se fosse possibile prendere un'altra strada.
Grazie in anticipo per le risposte! |
|
|
MagoAntò (Normal User)
Rookie
Messaggi: 42
Iscritto: 07/02/2009
|
Grazie per la risposta.
Sto provando un'altra strada: in pratica, definire all'interno della classe nodo_RB dei metodi che rimandino alla classe padre. Qualche esempio...
Codice sorgente - presumibilmente C/C++ |
nodo_BST* nodo_BST::ricerca_termine (nodo_BST *root, string key)
{
corpo del metodo...
}
|
...diventa...
Codice sorgente - presumibilmente C/C++ |
nodo_RB* nodo_RB::ricerca_termine(nodo_RB* root, string key)
{
return (nodo_RB*) nodo_BST::ricerca_termine(root, key);
}
|
Ho solo un dubbio sui metodi void, come questo:
Codice sorgente - presumibilmente C/C++ |
void inserisci_nodo(nodo_RB **root, string key);
|
che diventa
Codice sorgente - presumibilmente C/C++ |
void nodo_RB :: inserisci_nodo(nodo_RB **root, string key)
{
nodo_BST :: inserisci_nodo(root, key);
}
|
Il compilatore continua a riportarmi questo messaggio: 'inserisci_nodo' : cannot convert parameter 1 from 'class nodo_RB ** ' to 'class nodo_BST ** ' Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
Come fare? Ultima modifica effettuata da MagoAntò il 24/04/2012 alle 20:23 |
|
lumo (Member)
Expert
Messaggi: 449
Iscritto: 18/04/2010
|
L'altra strada sarebbe appunto al seconda opzione che ho elencato, e cioè i covariant return types.
Però questi non li puoi applicare agli argomenti come hai cercato di fare; ma non è un problema infatti puoi fare:
Codice sorgente - presumibilmente C/C++ |
nodo_RB* nodo_RB::ricerca_termine(nodo_BST* root, string key)
{
return (nodo_RB*) nodo_BST::ricerca_termine(root, key);
}
|
Quandi usi il metodo e fai un cast da nodo_RB* a nodo_BST* il cast è sempre valido.
Sta solo attento che non venga passato un nodo_BST*, altrimenti avresti qualche inconsistenza. Ma se dai una buona struttura al progetto non dovrebbe succedere.
Al massimo se ti pare di aver fatto un errore usa dynamic_cast<nodo_RB*>( root );
Se root non fosse un nodo_RB* allora il puntatore ottenuto sarebbe nullo(Beware: richiedere RTTI).
|
|
MagoAntò (Normal User)
Rookie
Messaggi: 42
Iscritto: 07/02/2009
|
Non potendo usare i covariant return type per gli argomenti, ho cambiato la firma del metodo in questo modo:
Codice sorgente - presumibilmente Plain Text |
nodo_BST* inserisci_nodo(string key)
|
...che viene invocato da...
Codice sorgente - presumibilmente C/C++ |
nodo_RB* inserisci_nodo(string key)
{
return (nodo_RB*) nodo_BST::inserisci_nodo(key);
}
|
Il nodo RB viene allocato dinamicamente grazie ad una funzione apposita che viene invocata nel corpo di inserisci_nodo. A questo punto, però, mi chiedo: è formalmente corretto che un metodo della superclasse chiami una funzione (non un metodo, attenzione) che alloca dinamicamente un oggetto della sottoclasse? Ultima modifica effettuata da MagoAntò il 26/04/2012 alle 19:51 |
|