[Connaissances de base C ++] Programmation générique - Modèle

Programmation générique

Pensez d'abord à une question: comment mettre en œuvre une fonction d'échange universelle?

Beaucoup de gens ici peuvent penser à la surcharge de fonctions. Oui, la surcharge de fonctions peut permettre l'échange de différents types de données, mais elle présente également de gros défauts:

  1. Les fonctions surchargées ne sont que de types différents et le taux de réutilisation du code est relativement faible. Tant que de nouveaux types apparaissent, les fonctions correspondantes doivent être ajoutées.
  2. La maintenabilité du code est relativement faible et une erreur peut entraîner une erreur de toutes les surcharges

Pouvez-vous donner un modèle au compilateur et laisser le compilateur utiliser le modèle pour générer du code selon différents types?

Le concept de
programmation générique sera imprimé ici Programmation générique: Ecrire du code générique qui n'a rien à voir avec les types est un moyen de réutiliser le code. Les modèles sont la base de la programmation générique.

Modèle de fonction

concept:

Le modèle de fonction représente une famille de fonctions. Le modèle de fonction n'a rien à voir avec le type. Il est paramétré lorsqu'il est utilisé et une version de type spécifique de la fonction est générée en fonction du type du paramètre réel.

Format du modèle de fonction

template <nom de type T1, nom de type T2,…, nom de type Tn>
valeur de retour type nom de fonction (liste de paramètres) {}

template<typename T>
void Swap( T& left, T& right) {
    
    
 T temp = left;
 left = right;
 right = temp; }
//注意:typename是用来定义模板参数的关键字
//也可以使用class(切记:不能使用struct)

Dans la phase de compilation du compilateur, pour l'utilisation des fonctions de modèle, le compilateur doit déduire et générer le type de fonction correspondant pour l'appel en fonction du type du paramètre réel passé.
Par exemple: lors de l'utilisation d'un modèle de fonction avec le type double, le compilateur détermine T comme type double en déduisant le type du paramètre réel, puis génère un code qui traite du type double, et il en va de même pour le caractère taper.

Instanciation de modèles de fonctions

  1. Instanciation implicite: laissez le compilateur déduire le type réel du paramètre de modèle en fonction du paramètre réel
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; 
 }
  1. Instanciation explicite: spécifiez le type réel du paramètre de modèle dans le <> après le nom de la fonction
int main(void) 
{
    
    
 	int a = 10;
 	double b = 20.0;
 
 	// 显式实例化
 	Add<int>(a, b);
 	return 0; 
 }

Si les types ne correspondent pas, le compilateur essaiera d'effectuer une conversion de type implicite. Si la conversion échoue, le compilateur signalera une erreur.

Principe de mise en correspondance des paramètres du modèle de fonction

  1. Une fonction non-modèle peut exister en même temps qu'un modèle de fonction avec le même nom, et le modèle de fonction peut également être instancié en tant que cette fonction non-modèle
  2. Pour une fonction non-modèle et un modèle de fonction avec le même nom, si les autres conditions sont les mêmes, la fonction non-modèle sera appelée en premier et une instance ne sera pas générée à partir du modèle. Si le modèle peut produire une fonction avec une meilleure correspondance, le modèle sera sélectionné
  3. Les fonctions de modèle ne permettent pas la conversion de type automatique, mais les fonctions ordinaires peuvent effectuer une conversion de type automatique

Modèle de classe

Format de définition du modèle de classe

template<class T1, class T2, ..., class Tn>
class 类模板名
{
    
    
 // 类内成员定义
};

Exemple:

// 动态顺序表
// 注意: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; }

Instanciation du modèle de classe

L'instanciation du modèle de classe est différente de l'instanciation du modèle de fonction. L'instanciation du modèle de classe doit suivre le nom du modèle de classe avec <>, puis placer le type instancié dans <>. Le nom du modèle de classe n'est pas la classe réelle, mais le instancié Le résultat est la classe réelle.

// Vector类名,Vector<int>才是类型
Vector<int> s1;
Vector<double> s2;

Je suppose que tu aimes

Origine blog.csdn.net/weixin_43962381/article/details/114990116
conseillé
Classement