一.概述
二.函数模板
1.概述
(1)介绍
C++的函数模板在一定程度上类似于Java的泛型,可以类比学习
编译次数:函数模板会编译两次,一次是对函数模板本身的编译,一次是在调用函数模板时,会将T
的类型具体化,然后再编译一次
**函数模板的目标:**函数模板是为了实现泛型,可以减轻编程的工作量,增强函数的重用性
**参数类型的来源:**在调用函数模板时
- 如果没有显示的指定函数模板的类型,编译器会根据传入的参数自动推导类型,并对模板中类型的代号进行替换
- 如果显示制定了函数模板的类型,那编译器就会直接以指定的类型替换函数模板中的类型
(2)注意事项
-
函数模板和普通函数都识别时,编译器默认会优先选择普通函数
因为可以减少编译的次数
-
函数模板和普通函数都识别时,可以通过显示指定使用函数模板,使编译器选择函数模板
在函数名后附加
<>
,可以指定使用函数模板。例如:Test<>(1,2)
-
函数模板自动类型推导时,不能对函数的参数进行自动类型转换
-
当显示指定模板类型时,是可以进行自动类型转换的,即小类型to大类型
Test
(10,'b');//里面的b字符会被替换成ASCII码-98
-
2.格式
(1)参数
下面的
T
是类型占位符,可以任意取的,且该数据类型只在函数模板内有效
-
template
:函数模板的定义-
typename T
用于告知编译器T
是一个数据类型
-
-
T parameter1, T parameter2
:函数的参数列表- 用函数模板定义的
T
作为参数的数据类型
- 用函数模板定义的
(2)格式:
template
才是真正的函数模板,也只有他才能代表函数模板返回值类型 函数名
template //可以声明一个类型,也可以声明多个类型
返回值类型 函数名(T parameter1, V parameter2) {
// 函数实现
}
(3)示例
下面交换元素信息的函数模板,不论传入什么类型都可以调用
#include
using namespace std;
/*函数模板*/
//template声明的类型只在函数模板内有效
template void exchange(T data1,T data2){
T temp = data1;
data1 = data2;
data2 = temp;
cout << "data1:" << data1 << " data2: " << data2 << endl;
}
int main(){
/*调用函数模板*/
//编译器自动类型推导
exchange(10,20);
exchange('a','b');
//显示指定模板的数据类型
exchange(30,40);
}
/*
data1:20 data2: 10
data1:b data2: a
data1:40 data2: 30
*/
3.函数模板重载
① 概述
重载的规则和普通函数重载一致,让函数参数、个数、顺序不同即可
② 示例
template
void exchange(T data){
cout << data << endl;
}
/*重载函数模板*/
template
void exchange(T data1,T data2){
T temp = data1;
data1 = data2;
data2 = temp;
cout << "data1:" << data1 << " data2: " << data2 << endl;
}
4.局限性
(1)概述
当函数模板推出的类型是数组或则是其它自定义类型时,可能会运算符不识别,此时,可以采取运算符重载和具体化函数模板的形式进行解决
(2)运算符重载
① 概述
根据编辑器的提示,重写不识别的运算符即可
对不识别的运算符进行重载,使其能够正常运行即可
② 示例
#include
using namespace std;
class Data{
public:
int data;
public:
Data(){
this->data = 0;
}
Data(int x){
this ->data =x;
}
};
/*函数模板*/
//template声明的类型只在函数模板内有效
template
void exchange(T data1,T data2){
T temp = data1;
data1 = data2;
data2 = temp;
cout << "data1:" << data1 << " data2: " << data2 << endl;
}
/*重写报异常的<<运算符*/
ostream & operator<<(ostream & out,Data obj){
out << obj.data;
return out;
}
int main(){
Data data1(1);
Data data2(2);
exchange(data1,data2);
}
(3)具体化函数模板
① 概述
概述: 就是具体指明函数模板中的泛型是什么数据类型
② 格式
格式:
具体化函数模板的时候,template后的<>
不用指定内容
template<> 数据类型 函数名<具体化的类型>(数据类型 对象名){
}
例子:
template<>
void exchange(Data data1,Data data2){
Data temp = data1;
data1 = data2;
data2 = temp;
cout << "data1:" << data1.data << " data2: " << data2.data << endl;
}
③ 示例
#include
using namespace std;
class Data{
public:
int data;
public:
Data(){
this->data = 0;
}
Data(int x){
this ->data =x;
}
};
/*函数模板*/
//template声明的类型只在函数模板内有效
template
void exchange(T data1,T data2){
T temp = data1;
data1 = data2;
data2 = temp;
cout << "data1:" << data1 << " data2: " << data2 << endl;
}
/*具体化函数模板*/
template<>
void exchange(Data data1,Data data2){
Data temp = data1;
data1 = data2;
data2 = temp;
cout << "data1:" << data1.data << " data2: " << data2.data << endl;
}
int main(){
Data data1(1);
Data data2(2);
exchange(data1,data2);
}
三.类模板
1.概述
简述: 类模板是一种特殊类型的类,它允许程序员编写一个通用的类定义,这个类可以与多种不同的数据类型一起工作。通过使用模板,我们可以编写一个代码,它可以在多种数据类型上工作,而无需为每种数据类型重写代码
注意事项:
- 使用类模板必须显式的指定类模板的数据类型
2.格式
使用
template
关键字声明的类型用于定义类内的成员
(1)简述
类模板的声明使用template
关键字,后面跟着尖括号中的模板参数列表。模板参数列表可以包含一个或多个类型参数。
(2)格式
类模板的是
template
这一个整体,无论是声明友元还是类外实现类模板内函数,都要以其作为函数名class MyClass
定义:
template
class MyClass {
public:
T value;
MyClass(T val) : value(val) {}
void printValue() {
std::cout << "Value: " << value << std::endl;
}
};
使用类模板创建对象:
创建类模板对象时,要在
<>
显式制定类型
MyClass ob(value);
(3)示例
定义了一个名为Data的类模板,并使用类模板创建了对象0b1,并调用了类模板的showData方法
#include
using namespace std;
template
class Data{
public:
T1 a;
T2 b;
public:
Data(){}
Data(T1 a,T2 b){
this -> a = a;
this -> b = b;
}
void showData(){
cout << a << " " << b < ob1(10,20);
ob1.showDat