👑1. 泛型编程
void Swap(int& a, int& b)
{
int tmp = a;
a = b;
b = tmp;
}
void Swap(double& a, double& b)
{
double tmp = a;
a = b;
b = tmp;
}
void Swap(char& a, char& b)
{
char tmp = a;
a = b;
b = tmp;
}
上面这段代码,是一个交换函数的重载,这虽然可以处理不同的类型,但是每个类型都要我们写对应的重载函数,而且复用率不是很高。
祖师爷可能也感觉这样不好用,设计了模板这个概念,就类似于印刷术,有一个模子在这里,想怎么印刷就怎么印刷。
泛型编程是一种编程范式,编写与特定类型无关的算法和数据结构,使其可以适用于多种数据类型,而无需为每种类型编写特定的代码。
在C++中,主要就通过模板来实现。
👒2. 模板
📿2.1 函数模板
函数模板是一种用于生成通用函数的模板。它允许在函数定义中使用类型参数,以便函数可以适用于多种数据类型。函数模板的语法如下:
template<typename T>
void func(T x)
{
//...
//
//...
}
这里的
template
也可以用class
来代替
typename
是定义函数模板的关键字
🎶2.11 类型推理
函数模板类似一张图纸,它本身并不是函数,是编译器会根据函数调用时候传递的参数类型进行推导,找到最匹配的模板参数类型。
template<typename T>
T Max(T a, T b)
{
return a > b ? a : b;
}
int main()
{
cout << Max(1, 3) << endl;
cout << Max(2.2, 1.3) << endl;
cout << Max('a', 'b') << endl;
return 0;
}
这段代码就会根据参数的不同类型,推导适合这些参数的模板参数。
🎶2.12 函数模板实例化
这些都是调用的同一个函数吗?
在推导完毕之后,会生成对应的函数实例,这叫做函数模板的实例化。它将根据模板描述中的模板参数类型,将函数模板中的代码替换为具体类型,并生成一个实际的函数定义。
所以可以看出这些调动都是各种推导出的实际函数,并不是同一个函数。
自动推导,我们也叫隐式实例化。
但如果我们模板只设置了一个类型参数,但我们传了2个类型不同的值,这时候就无法进行自动推导:
这时候就可以用显式实例化:
template<typename T>
T Max(T a, T b)
{
return a > b ? a : b;
}
int main()
{
//在函数名后的<>中指定模板参数的实际类型
Max<int>(1.1, 3);
Max<char>('a', 99);
return 0;
}
🎶2.13 匹配原则
当编译器进行模板参数匹配时,它会优先考虑完全匹配的情况。如果有一个非模板函数,而且该函数模板还能被实例化成这个非模板函数的话,这时候编译器就不需要特化模板。
template<class T1, class T2>
T1 Add(T1 a, T2 b)
{
std::cout << "T Add()" << std::endl;
return a + b;
}
int Add(int a, int b)
{
std::cout << "int Add()" << std::endl;
return a + b;
}
int main()
{
Add(1, 2); //非模板函数完全匹配,不需特化
Add<int>(1, 2); //指定调用模板函数
Add(1, 1.2); //模板函数可以生成更加匹配的版本
return 0;
}
Tips:
普通函数可以进行自动类型转换,模板函数不允许自动类型转换
📿2.2 类模板
类模板是一种用于生成通用类的模板。它允许在类定义中使用类型参数,以便可以创建适用于多种数据类型的类实例。类模板的语法如下:
template<typename T>
class ClassName
{
// 类成员和方法
};
在数据结构中,可能会存储不同类型的数据,有了类模板,就十分方便了:
template<class T>
class Stack
{
public:
Stack()
{
//...
}
//...
void push_back(const T& val)
{
//...
}
//...
private:
T _arr;
int _size;
int _capacity;
};
int main()
{
Stack<int> st_i; //整型
st_i.push_back(1);
st_i.push_back(2);
Stack<double> st_d; //浮点型
st_d.push_back(1.1);
st_d.push_back(1.2);
}
Tips:
类模板实例化与函数模板实例化不同,类模板实例化需要在类模板后面跟上
<T>
,而且和普通类不一样的实例化也不一样文章来源:https://www.toymoban.com/news/detail-541581.htmltemplate<class T> class A {}; class B {}; int main() { A<int> a; //A是类名 A<int>是类型 B b; //B既是类名也是类型 return 0; }
本期分享就到这里咯,如果有帮助的话点赞支持支持,我们下期再见,如果还有下期的话。文章来源地址https://www.toymoban.com/news/detail-541581.html
到了这里,关于C++初识模板的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!