2011-08-31 8 views
25

Mi sono guardato intorno per questo, e la risposta comune a questo sembra essere sulla falsariga di "non sono correlati, e non si può sostituire l'altro". Ma dì che sei in un'intervista e ti viene chiesto "Quando useresti un modello invece dell'ereditarietà e viceversa?"Quando utilizzare template rispetto all'ereditarietà

+15

In che modo questa "non è una domanda reale"? Le dita del grilletto da vicino mi irritano. –

+2

Se senti questa domanda in un'intervista, è il momento di salutarti, dato che stanno solo perdendo tempo; e tu ora fai lo stesso con il nostro. –

+1

È una domanda di intervista stupida. Nella migliore delle ipotesi, è il modo sbagliato. Non dovresti chiedere "quando usi lo strumento X". Dovresti chiedere, "ecco il problema J. Come lo risolvi?" e la risposta potrebbe essere "strumento X". – tenfour

risposta

3

utilizzare un modello in una base (o composizione) quando si desidera mantenere la sicurezza del tipo o si desidera evitare la spedizione virtuale.

+2

In effetti, sospetto che evitare l'invio virtuale tramite [CRTP] (http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern) sia ciò che l'intervistatore stava cercando. – ildjarn

13

La "risposta comune" è errata. In "Effective C++," afferma Scott Meyers in Articolo 41:

Articolo 41: Capire le interfacce implicite e compilare in tempo polimorfismo.

Meyers prosegue per riassumere:

  • entrambe le classi e le interfacce modelli di supporto e polimorfismo.
  • Per le classi, le interfacce sono esplicite e centrate sulla funzione delle firme. Il polimorfismo si verifica in fase di runtime tramite funzioni virtuali.
  • Per i parametri del modello, le interfacce sono implicite e basate su espressioni valide. Il polimorfismo si verifica durante la compilazione tramite il modello di istanziazione e la risoluzione di sovraccarico delle funzioni.
+0

Fa anche l'errore? : P –

+1

Heh heh. Non sono riuscito a trovare una fonte per tagliare e incollare ... – Gnawme

+0

Consiglio a tutti di leggere quel capitolo, sarà chiaro che cosa è necessario utilizzare dall'introduzione :) – Hame

1

modelli sono appropriate al momento di definire un'interfaccia che funziona su più tipi di oggetti non correlati. I modelli hanno perfettamente senso per le classi di contenitori in cui è necessario generalizzare gli oggetti nel contenitore, mantenendo tuttavia le informazioni sul tipo.

In caso di ereditarietà, tutti i parametri devono essere del tipo di parametro definito o estenderli. Quindi, quando i metodi operano su oggetti che hanno una relazione gerarchica diretta, l'ereditarietà è la scelta migliore.

Quando ereditarietà è erroneamente applicata, allora richiede la creazione di gerarchie di classi eccessivamente complesse, di oggetti estranei. La complessità del codice aumenterà per un piccolo guadagno. Se questo è il caso, quindi utilizzare i modelli.

42

Il modo in cui lo vedo è che i modelli e l'ereditarietà sono concetti letteralmente ortogonali: l'ereditarietà è "verticale" e scende, dall'astratto al sempre più concreto. Una forma, un triange, un triangolo equilatero.

I modelli invece sono "orizzontali" e definiscono le istanze di codice parallele che non si conoscono l'una dall'altra. L'ordinamento degli interi è formalmente lo stesso dell'ordinamento dei doppi e delle stringhe di ordinamento, ma queste sono tre funzioni completamente diverse. Tutti "sembrano" gli stessi da lontano, ma non hanno niente a che fare l'uno con l'altro.

L'ereditarietà fornisce l'astrazione runtime. I modelli sono gli strumenti di generazione codice.

Poiché i concetti sono ortogonali, possono essere usati insieme per lavorare verso un obiettivo comune.Il mio esempio preferito di questo è la cancellazione del tipo , in cui il contenitore di cancellazione del tipo contiene un puntatore di base virtuale a una classe di implementazione, ma esistono arbitrariamente molte implementazioni concrete generate da una classe derivata dal modello. La generazione del codice del modello serve a riempire una gerarchia di ereditarietà. Magia.

+1

Mi piace questa spiegazione. È un po 'più in inglese rispetto agli altri. – Brent212

+1

Hmm, non sono un esperto in materia ed è per questo che ho trovato questa risposta, ma mentre la descrivi, mi sembra che i template risolvano la mancanza di C++ per un complesso sistema di ereditarietà come i mixin (un problema, ad esempio , risolto elegantemente da Go). Se gli interi, i doppi e gli archi non hanno nulla in comune ma devono essere ordinati, tutti e tre dovrebbero estendere in qualche modo un tratto "ordinabile". – pistacchio

+1

@pistacchio: non definirei una "soluzione" l'ereditarietà complessa. I modelli offrono una sorta di ordinabilità in un modo molto più carino, dal momento che il sortee non ha bisogno di sapere che è stato ordinato. L'ereditarietà complessa di solito risulta quando si lavora con una mentalità forzata che tutto deve essere una gerarchia di ereditarietà, che di fatto è raramente appropriata. L'approccio di Go è semplice, ma più restrittivo e meno efficiente. È appropriato per la lingua piccola che Go vuole essere. –

0

Il modello descrive un algoritmo come decidere il risultato di un confronto tra i due oggetti di una classe o di ordinarli. Il tipo (classe) di oggetti da operare varia ma l'operazione o la logica o il passo ecc. Sono logicamente gli stessi.

L'ereditarietà, d'altra parte, viene utilizzata dalla classe figlio solo per estendere o rendere più specifica la funzionalità dei genitori. Speranza che abbia senso

Problemi correlati