目录
1.关于模版的介绍
2.函数模版
2.1函数模板概念
2.2函数模板格式
2.3 函数模板的原理
2.4 函数模板的实例化
2.5模板参数的匹配原则
3.类模版
3.1类模板的定义格式
3.2 类模板的实例化
1.关于模版的介绍
- C++中的模板是一种通用编程工具,它允许程序员编写具有通用性的函数或类,可以适用于不同类型的数据。模板使用泛型编程的概念,即代码可以处理多种不同的数据类型,而不只是特定的类型。
- 在C++中,有两种类型的模板:函数模板和类模板。
- --->函数模板是一种通用的函数定义,可以用于处理不同类型的参数。函数模板使用一对尖括号 "<>" 包围一个或多个类型参数,这些类型参数在函数定义中可以用作函数参数或返回类型的占位符。在调用函数模板时,编译器会根据实际参数的类型来推导出模板参数的具体类型。
- --->类模板是一种通用的类定义,可以用于创建具有相同结构但可能使用不同类型的成员的类。类模板的定义使用一对尖括号 "<>" 包围一个或多个类型参数,这些类型参数在类定义中可以用作类的成员变量、成员函数的参数或返回类型的占位符。在实例化类模板时,需要提供实际类型的参数。
- 使用模板可以提供代码的重用性和灵活性,因为它使得编写可以用于处理不同类型数据的通用代码成为可能。模板还可以提供更好的类型检查,并在编译时进行错误检查。
2.函数模版
2.1函数模板概念
2.2函数模板格式
template<typename T>//template<class T>
void Swap(T& a, T& b)
{
T tmp = a;
a = b;
b = tmp;
}
int main()
{
int a = 1, b = 0; double c = 3.1415925, d = 4.2526036;
Swap(a, b); Swap(c, d);
cout << a << b << c << d << endl;
return 0;
}
2.3 函数模板的原理
template<typename T>//template<class T>
void Swap(T& a, T& b)
{
T tmp = a;
a = b;
b = tmp;
}
int main()
{
int a = 1, b = 0;
Swap(a, b);
double c = 3.1415925, d = 4.2526036;
Swap(c, d);
char e = 'a', f = 'b';
Swap(e, f);
return 0;
}
2.4 函数模板的实例化
template<typename T1,typename T2>//template<class T>
void Swap(T1& a, T2& b)
{
T tmp = a;
a = b;
b = tmp;
}
int main()
{
int a = 1, b = 0;
double c = 3.1415925, d = 4.2526036;
Swap(a, b);
Swap(c, d);
Swap(a, d);
return 0;
}
这段代码可以成功运行吗?当然可以,因为我们用typename创建了两个模版参数T1和T2,传参时会发生隐式实例化,即便是a与d参数类型不同,也可以分别实例化,那如果将参数减少为一个呢?
// 专门处理int的加法函数
int Add(int left, int right)
{
return left + right;
}
// 通用加法函数
template<class T>
T Add(T left, T right)
{
return left + right;
}
void Test()
{
Add(1, 2); // 与非模板函数匹配,编译器不需要特化
Add<int>(1, 2); // 调用编译器特化的Add版本
}
- 将a强制类型转换为double或将d强制类型转换为int;
- 使用显式实例化
template<typename V>//template<class T>
void Swap(const V& a,const V& b)
{
V tmp = a;
a = b;
b = tmp;
}
int main()
{
int a = 1, b = 0;
double c = 3.1415925, d = 4.2526036;
Swap<double>(a, d);
return 0;
}
注意:这里只是演示显式实例化,交换函数在传参时会产生临时变量,具有常性,因此必须用const类型进行接收,不然权限就被放大了,但const修饰之后不可以更改值,因此还请读者注意!
2.5模板参数的匹配原则
// 专门处理int的加法函数
int Add(int left, int right)
{
return left + right;
}
// 通用加法函数
template<class T>
T Add(T left, T right)
{
return left + right;
}
void Test()
{
Add(1, 2); // 与非模板函数匹配,编译器不需要特化
Add<int>(1, 2); // 调用编译器特化的Add版本
}
// 专门处理int的加法函数
int Add(int left, int right)
{
return left + right;
}
template<class T1, class T2>
T1 Add(T1 left, T2 right)
{
return left + right;
}
void Test()
{
Add(1, 2); // 与非函数模板类型完全匹配,不需要函数模板实例化
Add(1, 2.0); // 模板函数可以生成更加匹配的版本,编译器根据实参生成更加匹配的Add函
数
}
3.类模版
3.1类模板的定义格式
形式:
template<class T1, class T2, ..., class Tn>
class 类模板名
{
// 类内成员定义
};
演示:
template<class T>
class A
{
public:
A(int year = 2025, int month = 1, int day = 19);
~A()
{}
private:
T* arr;
int _year;
int _month;
int _day;
};
template<class T>//作用域就是一个函数或者就是一个类,提取出来就要加上模板
A<T>::A(int year, int month , int day)//A是类名 A<T>是类型 要区分开来
{
cout << year << "-" << month << "-" << day << endl;
this->_year = year;
this->_month = month;
this->_day = day;
}
注意:
- 缺省参数只能在声明时候标注,在定义的时候标注会引发冲突;
- 一般在类中模版参数类型为class,而普通函数模版参数类型为typename;
- 类中函数在类外定义时,需要加上template...因为模版的作用域是一个类或者是一个函数,每当重新定义新的类或者函数,都需要重新加上模版
- 类外函数声明在用模版参数时不再是简单的类名::函数名,而需要在类名后加上<模版参数>,这是语法规定!
3.2 类模板的实例化
类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。
template<class T>
class A
{
public:
A(int year = 2025, int month = 1, int day = 19);
~A()
{}
private:
T* arr;
int _year;
int _month;
int _day;
};
template<class T>//作用域就是一个函数或者就是一个类,提取出来就要加上模板
A<T>::A(int year, int month , int day)//A是类名 A<T>是类型 要区分开来
{
cout << year << "-" << month << "-" << day << endl;
this->_year = year;
this->_month = month;
this->_day = day;
}
int main()
{
A<int> a1;
A<double> a2;
return 0;
}
在main函数中实例化一个类时,使用<>,中间填入模版类型即可~
补充:
-
模板的实参在任何时候都可以省略,模板实参省略意思为隐式实例化,一般情况下都使用隐式实例化,不需指定模板类型参数,让编译器进行推导,但有些情况下编译器推导时可能会有歧义,比如:模板参数只有一个类型T,但是用两个不同类型隐式实例化。
-
类模板与模板类所指的是同一概念,类模板是一个类家族,模板类是通过类模板实例化的具体类
-
类模板的参数可以是虚拟类型的,也可以是具体类型,C++中类模板的参数即为模板参数列表中内容,有两种方式:类型参数和非类型参数,类型参数:即类型参数化,将来实例化为具体的实际类型,有点像函数的形参,形参可以接受不同值的实参;非类型参数:在定义时给定了具体的类型,用该类型定义的为常量。
-
类模板中的成员函数全是模板函数,定义时都必须通过完整的模板语法进行定义。 因为所有类模板的成员函数,放在类外定义时,需要在函数名前加类名,而类名实际为ClassName<T>,所以定义时还需加模板参数列表。
- - - - - - ————————————本文结束———————————— - - - - - -