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

Spiegazione dettagliata delle funzioni di template C++

I template in C++ possono essere suddivisi in due grandi categorie: template di funzione, template di classe. Questo articolo si concentra sui template di funzione, e in seguito introdurrà i template di classe.

Una funzione template è una descrizione di funzione universale, ossia utilizza tipi universali per definire, i quali possono essere sostituiti con tipi specifici.

Esempio di codice:

#include <iostream>
//dichiarazione della classe template
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);//genera 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); // il compilatore genera void Swap(double &,double&);
  std::cout<<"x=" << x << "," << "y=" <<y;
  return 0;
}
// definizione della classe modello
template<typename T>
void Swap(T& a,T& b)
{
  T temp;
  temp = a;
  a = b;
  b = temp;
}

L'esempio sopra è uno degli esempi più semplici di template di funzione, il compilatore genererà la funzione corrispondente in base al tipo utilizzato.

Sovraccarico del template:

Quando è necessario utilizzare lo stesso algoritmo per diversi tipi, è possibile utilizzare i template, come mostrato nel codice sopra. Tuttavia, non tutti i tipi utilizzano lo stesso algoritmo. Per soddisfare questa esigenza, è possibile sovraccaricare la definizione del template come si fa con la definizione delle funzioni normali. Come per il sovraccarico delle funzioni normali, la tabella delle caratteristiche del sovraccarico deve essere diversa. Ecco un esempio di codice:

#include <iostream>
//dichiarazione della classe template
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);//genera 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); // il compilatore genera 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); // abbinamento del nuovo modello per lo scambio dell'array
  return 0;
}
// definizione della classe modello
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;
  }
}

Come nel codice sopra, è stata aggiunta una modello per scambiare gli elementi di due array, la caratteristica del modello originale è (T&,T&), la caratteristica del nuovo modello è (T[],T[]), int). Attenzione, nel secondo modello, il tipo dell'ultimo parametro è un tipo specifico (int), non un tipo generico, non tutti i parametri del modello devono essere tipi modello.

Specificazione esplicita:

Per un nome di funzione dato, possono esserci funzioni non modello, funzioni modello e funzioni modello specifiche esplicitamente definite e le loro versioni sovraccaricate.

La prototipazione esplicita e la definizione devono iniziare con template<> e indicare il tipo tramite il nome.

La specificizzazione copre il modello normale, mentre la funzione non modello copre la specificizzazione e il modello normale.

Di seguito è riportata la funzione non modello utilizzata per scambiare la struttura Job, il prototipo del modello e la specificizzazione.

void Swap(job &,job&); // funzione non modello
template <typename T>
void Swap(T&,T&); // funzione modello
template <> void Swap<job>(job&,job&); // funzione di specificizzazione esplicita, dove il parametro job dopo Swap può essere omesso, il nome della firma della funzione diventa template <> void Swap(job&,job&);

Come precedentemente menzionato, se ci sono più prototipi, il compilatore preferisce il non modello rispetto alla specificizzazione esplicita e alla versione del modello, mentre la specificizzazione esplicita preferisce la versione generata dal modello.

Come nella chiamata seguente:

double u,v;
Swap(u,v); // utilizzando un modello generico
job a, b;
swap(a, b)//使用显示具体化版本。

实例化和具体化:

    为了进一步了解模板,必须理解术语实例化和具体化。记住,在代码中包含函数模板本身并不会生成函数的定义,它只是一个用于生成函数定义的方案。编译器使用模板为特定类型生成定义时,得到的是模板实例(instantiation)。例如:函数调用Swap(i, j),使编译器生成一个Swap()的一个实例,该实例使用int类型。模板并非函数定义,但使用int的模板实例是函数定义。这种实例化方式被称为隐式实例化,因为编译器之所以知道需要定义,是由于程序调用Swap()时提供了int参数。

    现在编译器还可以允许显示实例化,这意味着可以直接命令编译器生成特定的实例,如Swap<int>。其句法是,声明所选的种类-用<>符号指示类型,并在声明前加上关键字template:

template void Swap<int>(int, int);//显示实例化

实现了这种特性的编译器在看到上述声明后,将使用Swap()模板生成一个int类型的实例。

与显示实例化不同的是,显示具体化使用下面两个等价声明的之一:

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

区别在于,这些声明的意思是“不要使用Swap()模板来生成函数定义,而应该使用独立的、专门的函数定义显示为int类型生成函数定义。

注意:尝试在一个编程单元中使用同一种类型的显示具体化与显示实例化将出错。

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

Ti potrebbe interessare