Tecnicamente, come le altre risposte mostrano, ci sono modi per limitare a sottotipi di un certo tipo in fase di compilazione. Tuttavia, la maggior parte delle volte, devi semplicemente fare
template <typename T> T foo(T bar) {...}
senza specificare un limite.
In Java, i limiti sono necessari per i generici perché la classe generica o il metodo è compilato separatamente da qualsiasi utilizzo di esso. Classi o metodi generici vengono compilati una volta, in una singola versione nel bytecode, una singola versione in grado di gestire qualsiasi argomento che i chiamanti lanciano su di esso che soddisfano i limiti della sua dichiarazione.
Il compilatore deve digitare-controllo utilizza del tipo T
nel corpo del metodo, come chiamate di metodo, campo di accessi, ecc, senza sapere che cosa T
è, quindi è necessario fornire un tenuti in modo che il compilatore può essere soddisfatto per esempio una chiamata al metodo è valida perché è definita su tutti i tipi che soddisfano quel limite. Ad esempio, se nel corpo del metodo è presente l'espressione bar.baz()
, il compilatore ti consente di compilare solo se il tipo MyClass
(e quindi tutti i sottotipi di esso) fornisce il metodo .baz()
; se non avessi fornito limiti, il compilatore si lamenterebbe che lo Object
(il limite superiore implicito) non ha alcun metodo .baz()
.
I modelli C++ sono diversi. La classe o la funzione basata su modello viene "istanziata" (compilata di nuovo) per ogni argomento di tipo diverso per cui è usato. Quindi, al momento di compilare il corpo della funzione per un particolare T
, il compilatore sa cosa è T
ed è in grado di controllare manualmente gli usi di quel tipo.
Quindi se si avesse l'espressione bar.baz()
nel corpo della funzione, ciò andrebbe bene. Se si è utilizzata questa funzione con T
come tipo che estende MyClass
, verrà compilato correttamente, poiché tale tipo ha un .baz()
.Se usi questa funzione con un tipo che non ha un .baz()
, allora non riuscirà a compilare a quell'utilizzo di esso. Se utilizzi accidentalmente la funzione con un tipo che non si estende MyClass
ma ha un .baz()
i cui tipi di parametri e tipo di reso corrispondono al modo in cui lo stai utilizzando, verrà compilato anche; ma non è necessariamente una brutta cosa. I modelli C++ non vengono solitamente utilizzati con le gerarchie di tipi, ma piuttosto con i requisiti su ciò che il tipo deve fornire. Quindi, per esempio, un algoritmo di ordinamento non richiederà che il suo contenitore e/o tipo di elemento estendano un certo tipo, ma piuttosto che il contenitore fornisca alcune caratteristiche (ad esempio un operatore di accesso casuale) e il tipo di elemento fornisca alcune caratteristiche (es. un operatore minore di).
Questa è la natura dei modelli. – AndyG
Java e C++ generico sembrano essere molto diversi. –
@AndyG Che cos'è esattamente un modello e come utilizzarlo in questo scenario? – ricky3350