Technicznie, jak pokazują inne odpowiedzi, istnieją sposoby ograniczenia go do podtypów określonego typu w czasie kompilacji. Jednak w większości przypadków wystarczy po prostu wykonać
template <typename T> T foo(T bar) {...}
bez konieczności określania powiązania.
W języku Java do generics potrzebne są ograniczenia, ponieważ klasa lub metoda generyczna jest kompilowana niezależnie od jakichkolwiek jej zastosowań. Ogólne klasy lub metody są kompilowane raz, w jedną wersję kodu bajtowego, jedną wersję, która jest w stanie obsłużyć dowolne argumenty, które wywołują wywołujący, które spełniają ograniczenia w deklaracji.
Kompilator musi używać funkcji check-type typu T
w treści metody, takich jak wywołania metod, dostępu do pól itp., Nie wiedząc, co to jest T
, więc należy podać granicę, aby kompilator mógł być spełniony na przykład wywołanie metody jest poprawne, ponieważ jest zdefiniowane dla wszystkich typów, które spełniają to ograniczenie. Na przykład, jeśli w treści metody użyto wyrażenia bar.baz()
, kompilator zezwoli na kompilację tylko wtedy, gdy typ MyClass
(a więc wszystkie jego podtypy) zapewnia metodę .baz()
; jeśli nie podano żadnych ograniczeń, kompilator narzekałby, że Object
(niejawna górna granica) nie ma metody .baz()
.
Szablony C++ są różne. Klasa lub funkcja szablonu jest "instancjonowana" (ponownie kompilowana) dla każdego innego argumentu, którego jest użyty. Tak więc w momencie kompilowania bryły funkcji dla konkretnej T
kompilator wie, czym jest T
i jest w stanie bezpośrednio sprawdzać zastosowania tego typu.
Więc jeśli miałeś wyrażenie bar.baz()
w ciele funkcji, byłoby dobrze. Jeśli użyłeś tej funkcji z T
, która jest typem, który rozszerza MyClass
, to skompiluje dobrze, ponieważ taki typ ma .baz()
.Jeśli użyjesz tej funkcji z typem, który nie ma .baz()
, to nie uda się skompilować przy takim użyciu. Jeśli przypadkowo użyjesz funkcji z typem, który nie rozszerza się na MyClass
, ale ma .baz()
, której typy parametrów i typ powrotu pasują do sposobu, w jaki go używasz, również się skompiluje; ale to niekoniecznie jest złe. Szablony C++ zwykle nie są używane z hierarchiami typów, ale raczej z wymaganiami dotyczącymi tego, jaki typ musi dostarczyć. Na przykład algorytm sortowania nie wymaga, aby jego kontener i/lub typ elementu rozszerzał określony typ, ale raczej, aby kontener zapewniał pewne cechy (np. Operator indeksu dostępu losowego), a typ elementu zapewnia określone funkcje (np. mniejszy niż operator).
Taka jest natura szablonów. – AndyG
Java i C++ generic wydają się być zupełnie inne. –
@AndyG Czym dokładnie jest szablon i jak mogę go użyć w tym scenariuszu? – ricky3350