2013-10-01 10 views
5

Sto provando a creare un algoritmo generico. Finora ho raggiunto questo gerarchia di classi utilizzando e puntatori, come nell'esempio qui sotto:Polimorfismo C++ statico piuttosto che dinamico

struct Base{ 
    virtual double fn(double x){return 0;} 
}; 

class Derived : public Base{ 
    double A; 
public: 
    Derived(double a) : A(a) {} 
    double fn(double x) { return A*x;} 
}; 

//Some other implementations 

class algo{ 
    double T; 
    std::unique_ptr<Base> b_ptr; 
public: 
    algo(double t, std::unique_ptr<Base>& _ptr); //move constructor... 
    //Some constructors 
    double method(double x){ return T*b_ptr->fn(x);} 

}; 

Questo set up viene quindi implementato come segue:

int main(){ 
    std::unique_ptr<Derived> ptr(new Derived(5.4)); 
    algo(3.2,ptr); 
    method(2.4); 

    return 0; 
} 

Questo è un esempio molto semplice, naturalmente , ma serve per la mia domanda. Da quello che ho capito, l'uso di classi derivate in questo modo significa che il metodo viene scelto in fase di esecuzione piuttosto che in fase di compilazione. Dal momento che non ho bisogno di alcun comportamento dinamico dal mio algoritmo - tutto è determinato al momento della compilazione - questa è una perdita inutile di efficienza. C'è un modo per fare quanto sopra al momento della compilazione, cioè il polimorfismo statico?

Da quello che ho capito, è possibile ottenere solo il polimorfismo statico utilizzando i modelli. Tuttavia, non sono stato in grado di trovare modelli di attrezzo con tipi non primitivi. Come nell'esempio sopra, ho bisogno di classi derivate con costruttori non predefiniti, il che non sembra possibile ... Qualcuno potrebbe offrire qualche soluzione su come ciò potrebbe essere fatto?

+0

tua osservazione circa inutili il comportamento dinamico è astuto: dovresti avere una gerarchia di classe polimorfa solo se * devi * rimandare la decisione di quale tipo effettivo hai bisogno di runtime. Buoni esempi sono l'analisi di messaggi da un protocollo di rete o la gestione di eventi in un ciclo di eventi. Altrimenti, se effettivamente * conosci * di quale tipo hai bisogno, il polimorfismo con funzione virtuale non è lo strumento giusto. –

+0

'È possibile ottenere solo il polimorfismo statico usando i modelli 'Il polimorfismo consiste nel chiamare la funzione corretta di base sul tipo di oggetto corrente. Quindi mi piacerebbe dire che il sovraccarico di funzione è anche polimorfismo statico. – ZijingWu

risposta

3

classe base e derivato sembrano rappresentare una funzione solo avere una sola funzione membro, così abbiamo potuto probabilmente fare a meno il polimorfismo completamente e passare una funzione in algo:

#include <iostream> 
#include <utility> 

template <class Function> 
class algo 
{ 
    double t; 
    Function fn; 

public: 
    algo(double t, const Function& fn) 
     : t{t}, fn{fn} 
    { } 
    double method(double x){ return t * fn(x);} 

}; 

template <class Function> 
algo<Function> make_algo(double t, Function&& fn) 
{ 
    return algo<Function>(t, std::forward<Function>(fn)); 
} 

int main() 
{ 
    const double someValue = 123; 
    const double anotherValue = 987; 

    auto algo = make_algo(anotherValue, [someValue](double otherValue) { 
     return someValue * otherValue; 
    }); 

    std::cout << std::fixed << algo.method(321) << std::endl; 
} 
+0

Si può generalizzare ulteriormente e fare il doppio anche su un parametro template. – goji

+0

Questa è una risposta molto interessante, grazie mille! L'esempio della classe di una funzione era semplice. Di solito, la classe derivata ha più funzioni e le funzioni possono essere piuttosto complesse. Il metodo di passaggio delle funzioni sarebbe troppo illeggibile! Si potrebbero definire le funzioni in anticipo e poi passarle? Ho appena scoperto il wrapper std :: function, è simile al metodo sopra o utilizza il polimorfismo dinamico? – Plamen

+0

L'uso di 'std :: function' invece di passare la funzione come modello probabilmente produrrebbe un codice più lento. L'altra alternativa è usare le classi di politica, questo potrebbe essere più il percorso che speravi con il binding statico dei metodi dell'algoritmo. – goji

Problemi correlati