Domanda

Supponiamo che io abbia una classe Base e diverse classi Derivate . Esiste un modo per trasmettere un oggetto a una delle classi derivate senza la necessità di scrivere qualcosa del genere:


string typename = typeid(*object).name();
if(typename == "Derived1") {
   Derived1 *d1 = static_cast< Derived1*>(object);
}
else if(typename == "Derived2") {
   Derived2 *d2 = static_cast < Derived2*>(object);
}
...
else {
  ...
}
È stato utile?

Soluzione

Non farlo.

Leggi sul polimorfismo. Quasi ogni "cast dinamico" la situazione è un esempio di polimorfismo che fatica ad essere implementato.

Qualunque decisione tu abbia preso nel cast dinamico è già stata presa. Delega semplicemente il lavoro reale alle sottoclassi.

Hai tralasciato la parte più importante del tuo esempio. L'utile lavoro polimorfico.

string typename = typeid(*object).name();
if(typename == "Derived1") {
   Derived1 *d1 = static_cast< Derived1*>(object);
   d1->doSomethingUseful();
}
else if(typename == "Derived2") {
   Derived2 *d2 = static_cast < Derived2*>(object);
   d2->doSomethingUseful();
}
...
else {
  ...
}

Se ogni sottoclasse implementa doSomethingUseful, tutto ciò è molto più semplice. E polimorfico.

object->doSomethingUseful();

Altri suggerimenti

Puoi usare dynamic_cast e testare NULL, ma invece fortemente prenderei in considerazione la possibilità di refactoring del codice

Se hai bisogno di una gestione specifica per una sottoclasse, Metodo modello potrebbe essere utile, ma senza saperlo quello che stai cercando di realizzare, è solo una vaga ipotesi.

Derived1* d1 = dynamic_cast< Derived1* >(object);
if (d1 == NULL)
{
    Derived2* d2 = dynamic_cast< Derived2* >(object);
    //etc
}

Ho i seguenti metodi sul mio tipo di smartpointer, simulando C # 'is' e 'as':

template< class Y > bool is() const throw()
    {return !null() && dynamic_cast< Y* >(ptr) != NULL;}
template< class Y > Y* as() const throw()
    {return null() ? NULL : dynamic_cast< Y* >(ptr);}

Puoi farlo usando dynamic_cast , ad esempio:

if ( Derived1* d1 = dynamic_cast<Derived1*>(object) ) {
    // object points to a Derived1
    d1->foo();
}
else if ( Derived2* d2 = dynamic_cast<Derived2*>(object) ) {
    // object points to a Derived2
    d2->bar();
}
else {
    // etc.
}

Ma come altri hanno già detto, codice come questo può indicare una cattiva progettazione e dovresti generalmente usare funzioni virtuali per implementare il comportamento polimorfico.

di solito, questo è un segno di un cattivo design. Perché hai bisogno di fare questo? Potrebbe essere possibile riprogettare in modo che non sia necessario.

Cosa stai cercando di realizzare, esattamente? Nella mia esperienza, cose come questa sono un segno di cattivo design. Rivaluta la tua gerarchia di classi, perché l'obiettivo della progettazione orientata agli oggetti è rendere inutili cose del genere.

Il tuo esempio non effettuerà il port, perché il formato esatto di name () non è specificato. Puoi provare una successione di dynamic_cast s. Dynamic_cast restituisce un puntatore null se si esegue il cast nel tipo errato. Tuttavia, se stai facendo un interruttore di tipo come questo, c'è qualcosa di sbagliato nel tuo design.

Penso che dynamic_cast sia la strada da percorrere, ma non penso in particolare che questo sia un cattivo design per tutte le possibili condizioni perché l'oggetto da lanciare potrebbe essere qualcosa fornito da un modulo di terze parti. Supponiamo che l'oggetto sia stato creato da un plug-in di cui l'autore dell'applicazione non è a conoscenza. E quel particolare plug-in può creare un oggetto di tipo Derived1 (essendo la vecchia versione) o un oggetto di tipo Derived2 (essendo la nuova versione). Forse l'interfaccia del plug-in non è stata progettata per eseguire operazioni specifiche della versione, ma crea semplicemente l'oggetto, quindi l'applicazione deve eseguire questo tipo di controllo per garantire il cast / esecuzione corretti. Dopodiché, possiamo tranquillamente chiamare object.doSomethingUsefulThatDoesNotExistInDerived1 ();

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top