C++编程基础: 15. 模板template
2025-04-17 10:36:43
本系列文章是配合我发布的《C++编程基础》系列视频教程的知识点总结和补充。这一节我们来讲讲模板template。
模板
作为泛型编程的基础,模板可以避开给出某个特定的数据类型而只给出类或函数的基本框架,当它在程序中被调用时才根据实际参数推导出具体的参数类型。
函数模版
声明一个函数模板的格式如下:
template <class 参数名> 函数声明;
template <typename 参数名> 函数声明;
以上二者的区别仅限于选用了不同的关键字class/typename,它们实际作用并无不同。
下面代码定义了一个返回最大值的函数模板:
template<typename T>T maxValue(const T& a, const T& b){
return a>b?a:b;
}
主程序中调用这个函数模板时的格式如下:
int a = 3, b=9;
std::cout<<"Max Value(Integer):"<<maxValue(a,b)<<std::endl;
也可以在函数名后用尖括号给出具体的参数类型,如:
int a = 3, b=9;
std::cout<<"Max Value(Integer):"<<maxValue<int>(a,b)<<std::endl;
类型参数
一般来说,用class或typename声明的参数代表类型,所以称之为类型参数
例如下面代码中的T就是一个类型参数:
template<typename T>
非类型参数
模板的参数不止可以是代表类型的参数,还可以是普通值,这一类称之为非类型参数。
例如,下面代码中声明了整数N作为参数:
template<int N>
类模板
和函数模板格式类似,声明一个函数模板的格式如下:
template <class 参数名> 类的定义;
template <typename 参数名> 类的定义;
下面的代码中,我定义了一个类模板MyList,它可以接收不同数据类型和长度的数组,并且提供了打印该数组值的方法printMyList():
template<typename T, int N>class MyList{
private: T myList[N]={};
public: MyList(T iniList[N]){
for(int i=0;i<N;i++){
[i] = iniList[i];
myList}
}
int getSize(){
return N;
}
void printMyList(){
for(int i=0;i<N;i++){
std::cout<<"myList["<<i<<"]="<<myList[i]<<std::endl;
}
}
};
在主程序中的调用,我首先声明了数组,再利用类的构造函数将这个数组传递给了类的对象,在类对象创建的过程中,这个数组的所有值会赋给类对象里私有数组成员myList,调用该类对象的公有方法printMyList()就可以打印数组myList中的值了:
char myCharList[5]={'a','c','l','e','n'};
<char, 5> myCharlist(myCharList);
MyList.printMyList();
myCharlistint myIntegerList[6]={5,2,6,7,8,3};
<int, 6> myIntlist(myIntegerList);
MyList.printMyList(); myIntlist
输出结果:
myList[0]=a
myList[1]=c
myList[2]=l
myList[3]=e
myList[4]=n
myList[0]=5
myList[1]=2
myList[2]=6
myList[3]=7
myList[4]=8
myList[5]=3
思考
在函数中的参数传递,传递的是该参数的拷贝,还是它的引用?如何让参数传递时减少浪费系统资源,提高程序运行速度,必要时确保传递的参数不被更改?