English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Подробное объяснение шаблонов функций C++

Шаблоны в C++ можно разделить на две основные категории: функции шаблонов и шаблонные классы. Эта статья сначала рассказывает о функциях шаблонов, а затем будет рассмотрена шаблонные классы.

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

Пример кода:

#include <iostream>
// объявление шаблонного класса
template<typename T>
void Swap(T& a,T& b);
int main()
{
  int i = 10;
  int j = 20;
  std::cout << "i=" << i << "," << "j=" << j;
  Swap(i,j); // генерация void Swap(int &,int&);
  std::cout << "i=" << i << "," << "j=" << j;
  double x = 11.5;
  double y = 19.5;
  std::cout<<"x=" << x << "," << "y=" <<y;
  Swap(x,y);// 编译器生成 void Swap(double &,double&);
  std::cout<<"x=" << x << "," << "y=" <<y;
  return 0;
}
// 模板类的定义
template<typename T>
void Swap(T& a,T& b)
{
  T temp;
  temp = a;
  a = b;
  b = temp;
}

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

Перегруженный шаблон:

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

#include <iostream>
// объявление шаблонного класса
template<typename T>
void Swap(T& a,T& b);
const int iCount = 5;
template<typename T>
void Swap(T* a,T*b,int n);
int main()
{
  int i = 10;
  int j = 20;
  std::cout << "i=" << i << "," << "j=" << j;
  Swap(i,j); // генерация void Swap(int &,int&)
  std::cout << "i=" << i << "," << "j=" << j;
  double x = 11.5;
  double y = 19.5;
  std::cout<<"x=" << x << "," << "y=" <<y;
  Swap(x,y);// 编译器生成 void Swap(double &,double&);
  std::cout<<"x=" << x << "," << "y=" <<y;
  int d[iCount] = {0,1,2,3,4};
  int e[iCount] = {5,6,7,8,9};
  Swap(d,e,iCount);// 匹配新的模板,进行数组的交换
  return 0;
}
// 模板类的定义
template<typename T>
void Swap(T& a,T& b)
{
  T temp;
  temp = a;
  a = b;
  b = temp;
}
template<typename T>
void Swap(T* a,T*b,int n)
{
  for (int i=0;i<iCount;++i)
  {
    T temp;
    temp = a[i];
    a[i] = b[i];
    b[i] = temp;
  }
}

如上代码新增了一个模板,用于交换两个数组中的元素,原来的模板特征标为(T&,T&),新模板的特征标为(T[],T[]),int)。注意,在后一个模板中,最后一个参数的类型为具体类型(int),而不是通用类型,并非所有的模板参数都必须是模板参数类型。

显示具体化:

对于给定的函数名,可以有非模板函数,模板函数和显示具体化模板函数以及它们的重载版本。

显示具体化的原型和定义应该以template<>打头,并通过名称来指出类型。

具体化将覆盖常规模板,而非模板函数将覆盖具体化和常规模板。

下面是用于交换Job结构的非模板函数,模板函数和具体化的原型。

void Swap(job &,job&);// 非模板函数
template <typename T>
void Swap(T&,T&);// 模板函数
template <> void Swap<job>(job&,job&);// 显示具体化函数,其中Swap后的job参数可去掉,则函数签名为template <> void Swap(job&,job&);

Предыдущие remarks指出,如果有多个原型,编译器在选择原型时,非模板将优先于显式具体化和模板版本,而显式具体化将优先于使用模板生成的版本。

如下面的调用:

double u,v;
Swap(u,v); // Использование общего шаблона
job a, b;
swap (a, b)//использование версии с конкретизацией.

Инсталляция и конкретизация:

    Чтобы лучше понять шаблоны, необходимо понять термины инсталляция и конкретизация. Запомните, что включение самого шаблона функции в код не создает определение функции, это всего лишь план для создания определения функции. Когда компилятор создает определение для конкретного типа с использованием шаблона, получаемый результат — это экземпляр шаблона (инсталляция). Например: вызов функции Swap(i, j) заставляет компилятор создать экземпляр Swap(), который использует тип int. Шаблон не является определением функции, но экземпляр шаблона с использованием int — это определение функции. Этот способ инсталляции называется неявной инсталляцией, потому что компилятор знает, что нужно определить, благодаря переданным параметрам типа int при вызове Swap().

    Теперь компилятор может также разрешать инсталляцию, что означает, что可以直接 приказать компилятору генерировать определенный экземпляр, например Swap<int> . Синтаксис: указать выбранный тип — использовать символы <> для указания типа, и добавить ключевое слово template перед声明ми:

template void Swap<int>(int, int);//инсталляция

Компилятор, реализующий эту функциональность, создает экземпляр шаблона Swap() типа int после просмотра вышеуказанного объявления.

В отличие от инсталляции, конкретизация использует одну из следующих эквивалентных деклараций:

template <> void Swap<int>(int, int);
template <> void Swap(int, int);

Разница заключается в том, что смысл этих объявлений — не использовать шаблон Swap() для генерации определений функций, а вместо этого использовать независимые, специализированные определения функций, отображаемые как функции типа int.

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

Вabove所述是小编给大家介绍的C++模版函数详解,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言。

Вам может понравиться