Это пример одного из больших различий между C ++ и Java. Единственный инструмент абстракции, который есть в Java, - это полиморфизм времени выполнения (интерфейсы и абстрактные классы). В C ++ вы этим не ограничены. Вы можете создать псевдонимы для типов и позволить классам иметь другие связанные / вложенные типы. Во многих случаях это позволяет вам избежать полиморфизма во время выполнения. Универсальность во время компиляции имеет то преимущество, что она довольно быстрая (нет вызовов виртуальных функций, есть встроенные возможности). Кроме того, это облегчает управление в течение всей жизни, когда у вас нет сборщика мусора. Вы можете просто создавать объекты в стеке.
Вот (непроверенный) пример:
template<typename Iter>
typename std::iterator_traits<Iter>::value_type
sum(Iter begin, Iter end) {
typedef typename std::iterator_traits<Iter>::value_type vt;
vt accum = vt();
while (begin!=end) {
accum += *begin;
++begin;
}
return accum;
}
Здесь "Iter" - это просто имя. На самом деле это не накладывает никаких ограничений на тип. Если вы захотите создать экземпляр этого шаблона с типом, который не является итератором (по крайней мере, в структурном смысле), вы получите ошибку во время компиляции (типизированная утка во время компиляции). Итак, часть вашей работы - документирование того, какого типа вы ожидаете. Обычно это делается путем выбора некоторых описательных имен параметров шаблона (например, ForwardIterator) и комментариев.
Я должен также упомянуть, что множественные функции «sum» будут «созданы», если вы будете использовать этот шаблон функции с различными типами итераторов. Если вы не хотите такого дублирования кода и / или действительно нуждаетесь в полиморфизме во время выполнения, вы можете применить метод, называемый «стирание типа». Стирание типа для итераторов не является частью стандартной библиотеки. Кроме того, я никогда не чувствовал необходимости применять эту технику для итераторов. Но вы найдете использование стирания типов в других библиотеках, таких как boost :: any и boost :: function.
Есть несколько других приемов шаблонов, которые вы можете использовать, чтобы различать разные категории итераторов (см. «Диспетчеризация тегов») или ограничивать шаблон функции (см. «SFINAE»). Если вы заинтересованы в стирании типов, попробуйте поискать googling для c ++, стирание типов, итератор. Вы в основном создаете класс дескриптора, который управляет полиморфным объектом (через указатель). Этот полиморфный объект оборачивает некоторый другой объект, тип которого вы хотите «стереть» (скрыть).