模块初阶学习
当我们在过去想要实现一个功能时,例如Swap交换函数时,我们需要不断考虑参数的正确与否。如果是在c语言,我们还需要不断更改函数名字,以防止函数名重复。在c++我们可以通过函数名重载解决这个问题,但还是有一些小问题,例如,我们要想适配所有类型数据的转换,我们就得写n个swap函数重载。有没有什么方法能够建立一个模子,让编译器自己去写对应输入参数对应的函数的呢?有的兄弟,有的,那就是模块。
函数模版
函数模版,用template<typename T1,template T2 .......>然后下一行带一个函数定义构成
函数模版代表了一个函数家族,与特定具体类型无关,函数模版里面T1等参数由使用时决定类型,根据输入的实参推断出,此时T1......Tn应该是什么类型。
template<typename T>
void Swap(T& left, T& right)
{
T tmp = left;
left = right;
right = tmp;
return 0;
}
函数模版的实例化分为隐式实例化和显式实例化。隐式实例化就是让编译器自己根据实参去判断模块参数T的类型,例如如下的代码,b1就是隐式实例化函数的数据。但是隐式实例化也有缺点,例如如果我们将a1和a3作为Add模块的两个实参,那就会发生报错,为什么呢?a1是int类型的数据,a3是double类型的数据,当我们同时把两个数据传过去,编译器会迷糊,他不知道T到底是int还是double。此时,我们有三个办法来解决这个报错。1.改变模版参数数量。多加几个T2,T3等等等,以适配不同的类型。2.强转类型,可以主动把a1或者a2强转类型为另外一个参数的类型。3.第三点就是,显式实例化。
显式实例化,在模版函数后面加上<参数类型>,就可以指定模版里面的参数的类型。如b2的类型转换。
模版函数也可以和普通函数重载。当调用函数时既可以调用模版函数也可以调用全局普通函数时,默认使用普通函数。因为模版函数本质上是编译器根据你的需求实例化一个函数出来。
template <typename T>
T Add(const T& a1, const T& a2)
{
return a1 + a2;
}
int Add(const int& a1, cosnt int& a2)
{
return a1+a2;
}
int main()
{
int a1 = 3;
int a2 = 4;
int b1 = Add(a1, a2);
double a3 = 5;
double a4 = 6;
int b2 = Add<int>(a1, a3);
return 0;
}
类模版
类模版的定义格式其实与函数模版相似,只不过里面的typename换成class。并且类模版必须的显式实例化,并且我们要知道,Date是类名字,Date<int>才是类型
template <class T>
class Date
{
};
int main()
{
Date<int>d1;
Date<double>d2;
return 0;
}