перегрузка функций vs шаблоны функций-C++
в книгах на C++, почему нас учат использовать
5 ответов
Шаблоны предоставляют преимущество, когда вы хотите выполнить одно и то же действие для типов, которые могут быть разными. Простой пример:
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(); }
вы можете достичь вышеуказанного, используя шаблоны и специализации шаблонов, но такие специализации должны представлять собой несколько исключений из общего случая.
Шаблоны не могут принимать различное количество аргументов. Перегрузки могут. Кроме того, шаблон указывает, что вы можете работать с любым типом данных, но бессмысленно представлять это, когда на самом деле подавляющее большинство шаблонов будет только специализациями (в вашей системе). Кроме того, перегрузки могут быть virtual
и специализации шаблонов не могут. Специализации также не могут отличаться по своим сигнатурам от базы.
template<typename T> void foo(T& t);
template<> void foo<std::string>(std::string* ptr); // Illegal
void foo(std::string* ptr); // Legal
это сильно ограничило бы какие виды перегрузку можно производить по сравнению с текущей системой.
вы обычно используете шаблоны, когда хотите выполнить один и тот же набор операций для разных типов данных.
вы обычно используете перегрузку функций, когда хотите выполнять различные операции с определенными наборами данных.
преимущество шаблонов в ситуации, когда вы хотите выполнить один и тот же набор операций над многими различными типами данных, заключается в том, что компилятор будет обрабатывать для вас во время компиляции любой возможный новый тип, который вы можете создать в будущем, который использует шаблонная функция. если вы хотите использовать перегрузку функций, вам придется создавать новую перегрузку функций каждый раз, когда вы создаете новый тип, который хотите передать конкретной функции.
просто дополнение к ответу juanchopanza:
с перегрузками функций вы также можете изменить количество аргументов, что может быть удобно.
простой пример, если у вас есть функция со следующим объявлением:
void foo(int i, int j);
но вы часто вызываете foo с первым аргументом 0, вы можете написать следующую функцию, которая экономит вам ввод текста.
void foo(int j) {
foo(0, j);
}
Шаблоны (обычно) требуют, чтобы вы использовали идентичные синтаксис для выполнения операций на всех (поддерживаемых) типах.
функция перегрузки используется (или должна использоваться) аналогично, но позволяет использовать разные синтаксис для выполнения операций различных типов. Это означает ,что (хотя вам и не нужно) вы можете представлять ценности по-разному. Одним из очевидных примеров было бы то, что называется atan
и atan2
в библиотеке C. С atan
, мы передаем отношение "подъем к "бегу", и мы возвращаем угол, который представляет это отношение. С atan2
мы передаем значения для подъема и запускаем отдельно (который вычисляет примерно тот же результат, но поскольку он дает немного больше входных данных, может также дать более полный результат).
хотя они реализованы как полностью отдельные функции в C, если бы они были написаны на C++ с самого начала, было бы вполне уместно использовать одно имя (например, atan
) перегружен как для одного, так и для двух параметров:
double atan(double); // equivalent to current atan
double atan(double, double); // equivalent to current atan2
Шаблоны (за исключением специализации, которая в значительной степени просто переопределяет то, что предоставляют сами шаблоны) не обеспечивают различий в синтаксисе вызова, как это.
перегрузка также более ограничена - вы предоставляете одну перегрузку для каждого конкретного типа, который хотите поддержать (хотя, если вы берете указатель или ссылку, они также могут поддерживать производные типы). С шаблонами, один шаблон может (по крайней мере потенциально) применяться к любой тип.