Artigo Diretório
Programação genérica
Primeiro pense em uma questão: como implementar uma função de troca universal?
Muitas pessoas aqui podem pensar em sobrecarga de função. Sim, a sobrecarga de função pode realizar a troca de diferentes tipos de dados, mas também tem grandes falhas:
- Funções sobrecarregadas são diferentes apenas em tipos, e a taxa de reutilização de código é relativamente baixa. Enquanto novos tipos aparecem, as funções correspondentes precisam ser adicionadas
- A capacidade de manutenção do código é relativamente baixa e um erro pode fazer com que todas as sobrecargas dêem errado
Você pode fornecer um modelo ao compilador e permitir que ele use o modelo para gerar código de acordo com diferentes tipos?
O conceito de
programação genérica será impresso aqui : Programação genérica: Escrever código genérico que não tem nada a ver com tipos é um meio de reutilização de código. Os modelos são a base da programação genérica.
Template de função
conceito:
O template de função representa uma família de funções. O template de função não tem nenhuma relação com o tipo. Ele é parametrizado quando usado, e uma versão de tipo específico da função é gerada de acordo com o tipo do parâmetro atual.
Formato de modelo de função
template <nome do tipo T1,
nome do tipo T2,…, nome do tipo Tn> nome da função do tipo de valor de retorno (lista de parâmetros) {}
template<typename T>
void Swap( T& left, T& right) {
T temp = left;
left = right;
right = temp; }
//注意:typename是用来定义模板参数的关键字
//也可以使用class(切记:不能使用struct)
No estágio de compilação do compilador, para o uso de funções de modelo, o compilador precisa deduzir e gerar o tipo de função correspondente para chamada com base no tipo do parâmetro real passado.
Por exemplo: ao usar um modelo de função com o tipo duplo, o compilador determina T como o tipo duplo deduzindo o tipo do parâmetro real e, em seguida, gera um código que trata do tipo duplo, e o mesmo é verdadeiro para o caractere tipo.
Instanciação de modelos de função
- Instanciação implícita: deixe o compilador deduzir o tipo real do parâmetro do modelo com base no parâmetro real
template<class T> T Add(const T& left, const T& right)
{
return left + right;
}
int main()
{
int a1 = 10, a2 = 20;
double d1 = 10.0, d2 = 20.0;
Add(a1, a2);
Add(d1, d2);
/*
该语句不能通过编译,因为在编译期间,当编译器看到该实例化时,需要推演其实参类型
通过实参a1将T推演为int,通过实参d1将T推演为double类型,但模板参数列表中只有一个T,
编译器无法确定此处到底该将T确定为int 或者 double类型而报错
注意:在模板中,编译器一般不会进行类型转换操作,因为一旦转化出问题,编译器就需要背黑锅
Add(a1, d1);
*/
// 此时有两种处理方式:1. 用户自己来强制转化 2. 使用显式实例化
Add(a, (int)d);
return 0;
}
- Instanciação explícita: especifique o tipo real do parâmetro do modelo no <> após o nome da função
int main(void)
{
int a = 10;
double b = 20.0;
// 显式实例化
Add<int>(a, b);
return 0;
}
Se os tipos não corresponderem, o compilador tentará realizar a conversão implícita de tipo.Se a conversão falhar, o compilador relatará um erro.
Princípio de correspondência de parâmetros do modelo de função
- Uma função não modelo pode existir ao mesmo tempo que um modelo de função com o mesmo nome, e o modelo de função também pode ser instanciado como esta função não modelo
- Para uma função não modelo e um modelo de função com o mesmo nome, se outras condições forem iguais, a função não modelo será chamada primeiro e uma instância não será gerada a partir do modelo. Se o modelo pode produzir uma função com uma correspondência melhor, o modelo será selecionado
- As funções de modelo não permitem a conversão automática de tipo, mas as funções comuns podem realizar a conversão automática de tipo
Modelo de classe
Formato de definição do modelo de classe
template<class T1, class T2, ..., class Tn>
class 类模板名
{
// 类内成员定义
};
Exemplo:
// 动态顺序表
// 注意:Vector不是具体的类,是编译器根据被实例化的类型生成具体类的模具
template<class T>
class Vector
{
public :
Vector(size_t capacity = 10)
: _pData(new T[capacity])
, _size(0)
, _capacity(capacity)
{
}
// 使用析构函数演示:在类中声明,在类外定义。
~Vector();
void PushBack(const T& data);
void PopBack();
// ...
size_t Size() {
return _size;}
T& operator[](size_t pos)
{
assert(pos < _size);
return _pData[pos];
}
private:
T* _pData;
size_t _size;
size_t _capacity;
};
// 注意:类模板中函数放在类外进行定义时,需要加模板参数列表
template <class T>
Vector<T>::~Vector()
{
if(_pData)
delete[] _pData;
_size = _capacity = 0; }
Instanciação do modelo de classe
A instanciação do modelo de classe é diferente da instanciação do modelo de função. A instanciação do modelo de classe precisa seguir o nome do modelo de classe com <> e, em seguida, colocar o tipo instanciado em <>. O nome do modelo de classe não é a classe real, mas o instanciado O resultado é a classe real.
// Vector类名,Vector<int>才是类型
Vector<int> s1;
Vector<double> s2;