C ++: Differenza tra NVI e Template Method Pattern?
-
28-09-2019 - |
Domanda
Qual è la differenza tra NVI ( non virtuale ) e dei modelli Template Method il?
sembrano molto simili e ho letto sia che sono fondamentalmente la stessa e che sono sottilmente diverso con Template di essere in qualche modo più generale.
Soluzione
NVI è un idioma, Template Method è un modello. NVI è un'implementazione del pattern Template Method utilizzando distribuzione dinamica in C ++; è anche possibile creare metodi template in C ++ utilizzando il modello metaprogrammazione per eliminare l'invio dinamica.
Un modello è più generale di un idioma, e le lingue può utilizzare diversi linguaggi per implementare il modello.
Altri suggerimenti
Come è stato detto, NVI è un idioma programmazione, relativi a una categoria di lingue. E 'stato promosso da Herb Sutter, tra gli altri, perché aiuta a far rispettare i contratti:
- invarianti di classe
- contratti di funzione (asserzioni oltre i parametri passati e il valore di ritorno generato)
- operazioni ripetitive (come la registrazione)
- controllo sulle eccezioni generate (pessima idea però;))
Tuttavia, l'implementazione può effettivamente differire considerevolmente, per esempio un altro esempio di realizzazione NVI è combinarlo con Pimpl:
class FooImpl;
class Foo
{
public:
enum type { Type1, Type2 };
Foo(type t, int i, int j);
int GetResult() const;
private:
FooImpl* mImpl;
};
E per l'attuazione:
struct FooImpl
{
virtual ~FooImpl();
virtual int GetResult() const;
};
class FooType1: public FooImpl
{
public:
FooType1(int i, int j);
virtual int GetResult() const;
private:
/// ...
};
Ho sempre trovato che trasmetteva il punto migliore. Avete capito?
Il punto principale è che virtual
è un dettaglio di implementazione. Ed esponendo i dettagli di implementazione nell'interfaccia è una cattiva idea, perché si potrebbe desiderare di cambiare loro.
Inoltre dettagli di implementazione tendono a confusione con compatibilità binaria. Per esempio aggiungendo un nuovo metodo virtual
in una classe può cambiare il layout della tabella virtuale (comune tecnica attuazione) e quindi botch la compatibilità binaria. Su gcc è necessario fare in modo che si aggiunge scorso (tra il virtuale), se si desidera conservare la compatibilità.
Utilizzando la combinazione NVI + Pimpl sopra, non v'è alcun virtual
a tutti (nemmeno privato) nella classe esposta. Il layout di memoria è in avanti e indietro compatibile. Abbiamo ottenere la compatibilità binaria.
Qui, usiamo diversi modelli in una sola volta:
- Template Method
- Strategia (dal momento che siamo in grado di scambiare il puntatore a volontà)
- di fabbrica (per decidere quale implementazione otteniamo)