2009-02-25 17 views
7

The CRTP è suggerito in questa domanda sul polimorfismo dinamico. Tuttavia, questo modello è presumibilmente utile solo per il polimorfismo statico. Il design che sto guardando sembra essere ostacolato in senso orario dalle chiamate alle funzioni virtuali, come hinted at here. Un aumento di velocità di persino 2,5 volte sarebbe fantastico.Esistono alternative al polimorfismo in C++?

Le classi in questione sono semplici e possono essere codificate completamente in linea, tuttavia non è noto fino al runtime quali classi verranno utilizzate. Inoltre, possono essere incatenati, in qualsiasi ordine, accumulando prestazioni ingiuriate.

Qualsiasi suggerimento (incluso il modo in cui il CRTP può essere utilizzato in questo caso) benvenuto.

Modifica: Googling presenta una menzione di modelli di funzione. Questi sembrano promettenti.

risposta

3

Sono d'accordo con m-sharp che non si intende evitare il polimorfismo di runtime.

Se il valore di ottimizzazione su eleganza, provare a sostituire diciamo

void invoke_trivial_on_all(const std::vector<Base*>& v) 
{ 
    for (int i=0;i<v.size();i++) 
    v[i]->trivial_virtual_method(); 
} 

con qualcosa di simile

void invoke_trivial_on_all(const std::vector<Base*>& v) 
{ 
    for (int i=0;i<v.size();i++) 
    { 
    if (v[i]->tag==FooTag) 
     static_cast<Foo*>(v[i])->Foo::trivial_virtual_method(); 
    else if (v[i]->tag==BarTag) 
     static_cast<Bar*>(v[i])->Bar::trivial_virtual_method(); 
    else... 
    } 
} 

Non è abbastanza, non certo OOP (più un ritorno a quello che si potrebbe fare in buon vecchio 'C') ma se i metodi virtuali sono abbastanza banali dovresti ottenere una funzione senza chiamate (soggetto a opzioni di ottimizzazione del compilatore &).Una variante che utilizza dynamic_cast o typeid potrebbe essere leggermente più elegante/sicura, ma attenzione che tali funzioni hanno il proprio overhead, che è probabilmente paragonabile ad una chiamata virtuale.

Nei casi in cui è probabile che si verifichi un miglioramento rispetto a quanto sopra, se alcuni metodi delle classi non sono operativi, e non è stato possibile richiamarli o se le funzioni contengono codice invariante del ciclo comune e l'ottimizzatore riesce a sollevare fuori dal giro.

+1

Credo che le if-statement in un template potrebbero rendere questo pasticcio un po 'più pulito. Sembra comunque promettente. – casualcoder

+0

Si prega di utilizzare static_cast <> anziché reinterpret_cast <>, quest'ultima darà risultati errati in taluni casi (su una tipica implementazione, un esempio sarebbe se Foo o Bar comprende più classi base e la base non è prima tra loro). –

+0

Buon punto, grazie; risposta aggiornata. – timday

18

Il polimorfismo significa letteralmente forme multiple (poli) (morph). Nei linguaggi tipizzati staticamente (come C++) ci sono tre tipi di polimorfismo.

  1. Polimorfismo ad hoc: questo è meglio visto in C++ come sovraccarico di funzioni e metodi. Lo stesso nome di funzione si associa a diversi metodi basati sulla corrispondenza del tempo di compilazione dei parametri della chiamata alla funzione o alla firma del metodo.
  2. Polimorfismo parametrico: in C++ questo è template e tutte le cose divertenti che puoi fare con esso come CRTP, specializzazione, specializzazione parziale, meta-programmazione ecc. Ancora questo tipo di polimorfismo in cui lo stesso nome di modello può fare cose diverse basate sui parametri del modello è un polimorfismo di compilazione.
  3. Sottotipo Polymorphism: Finalmente questo è ciò che pensiamo quando sentiamo la parola polimorfismo in C++. È qui che le classi derivate sovrascrivono le funzioni virtuali per specializzare il comportamento. Lo stesso tipo di puntatore a una classe base può avere un comportamento diverso in base al tipo derivato concreto a cui punta. Questo è il modo per ottenere il polimorfismo di esecuzione in C++.

Se non è noto fino al runtime quali classi verranno utilizzate, è necessario utilizzare il Polymorphism per sottotipo che coinvolgerà chiamate di funzioni virtuali.

Le chiamate al metodo virtuale hanno un overhead di prestazioni molto ridotto rispetto alle chiamate con collegamenti statici. Ti esorto a dare un'occhiata alle risposte a questo SO question.

-1

Puoi seguire il percorso Ole C e utilizzare i sindacati. Anche se anche questo può essere disordinato.

+1

ho letto questo tre volte separate come 'cipolle' e poteva solo immaginare ciò che il vostro flusso di lavoro 'disordinato' coinvolto. –

Problemi correlati