Перегрузка функций с помощью шаблонов функций - С++ - программирование
Подтвердить что ты не робот

Перегрузка функций с помощью шаблонов функций - С++

В книгах на С++ почему мы учили использовать функцию перегрузки, когда у нас есть шаблоны в С++?

Не было бы лучше показать эффективное (и правильное) использование шаблонов? В отличие от того, где перегрузка функций преподается в большинстве книг на С++?

Или есть ли веские причины использовать один вместо другого?

4b9b3361

Ответ 1

Шаблоны предоставляют преимущество, если вы хотите выполнить одно и то же действие для типов, которые могут быть разными. Простой пример:

template <typename T>
T foo(const T& a, const T& b) { return a + b; }

Вы можете использовать перегрузку, если хотите применить различные операции в зависимости от типа:

struct Foo{ void foo() const {} };

void foo(int i) { std::cout << "i = " << i << "\n"; }
void foo(const Foo& f) { f.foo(); }

Вы могли бы достичь вышеуказанного, используя шаблоны и специализированные шаблоны, но такие специализации должны представлять собой несколько исключений для общего случая.

Ответ 2

Шаблоны не могут принимать различное количество аргументов. Перегрузки могут. Кроме того, шаблон указывает, что вы можете работать с любым типом данных, но это бессмысленно представлять это, когда на самом деле огромное, огромное большинство шаблонов будут только специализациями (в вашей системе). Кроме того, перегрузки могут быть virtual, а специализации шаблонов не могут. Кроме того, специализации не различаются по своим подписям от базы.

template<typename T> void foo(T& t);
template<> void foo<std::string>(std::string* ptr); // Illegal
void foo(std::string* ptr); // Legal

Это серьезно ограничило бы то, какую перегрузку вы могли бы производить по сравнению с текущей системой.

Ответ 3

Обычно вы используете шаблоны, когда хотите выполнять один и тот же набор операций для разных типов данных.

Обычно вы используете перегрузку функций, когда хотите выполнять разные операции над определенными наборами данных.

преимущество шаблонов в ситуации, когда вы хотите сделать один и тот же набор операций для разных типов данных, заключается в том, что компилятор будет обрабатывать для вас во время компиляции любой возможный новый тип, который вы можете создать в будущем, который использует шаблонная функция. если бы вы использовали перегрузку функций, вам приходилось создавать новую функцию перегрузки каждый раз, когда вы создавали новый тип, который вы хотели передать конкретной функции.

Ответ 4

Шаблоны (обычно) требуют, чтобы вы использовали идентичный синтаксис для выполнения операций для всех (поддерживаемых) типов.

Перегрузка функций (или должна использоваться) аналогично, но позволяет использовать различный синтаксис для выполнения операций для разных типов. То есть (хотя вам и не нужно) вы можете представлять значения по-разному. Одним из очевидных примеров будет то, что называется atan и atan2 в библиотеке C. С atan мы передаем отношение "подъем к" прогону ", и мы возвращаем угол, который представляет соотношение. С atan2 мы передаем значения для подъема и запуска отдельно (что вычисляет примерно такой же результат, но поскольку он дал немного больше входных данных, может также получить более полный результат).

Хотя они реализованы как полностью отдельные функции в C, если они были написаны на С++ с самого начала, было бы вполне целесообразно использовать одно имя (например, atan), перегруженное как для одного, так и для двух параметров:

double atan(double);           // equivalent to current atan
double atan(double, double);   // equivalent to current atan2

Шаблоны (за исключением специализации, которая в значительной степени просто переопределяет, какие сами шаблоны предоставляют) не предусматривает различий в синтаксисе вызова, как это.

Перегрузка также более ограничена - вы предоставляете одну перегрузку для каждого определенного типа, который хотите поддерживать (хотя, если вы берете указатель или ссылку, они также могут поддерживать производные типы). С шаблонами один шаблон может (по крайней мере потенциально) применяться к любому типу.

Ответ 5

Просто добавление к juanchopanza ответ:

С перегрузкой функции вы также можете изменять количество аргументов, что может быть удобно.

Простой пример, если у вас есть функция со следующим объявлением:

void foo(int i, int j);

Но вы часто вызываете foo с первым аргументом 0, вы можете написать следующую функцию, которая сохранит вам некоторую типизацию.

void foo(int j) {
  foo(0, j);
}