目录
分析:
函数模板重载
分析:
前面说到,模板的存在可以替换所有的类型,那么如果我们写了函数模板之后,还能否写(同名)具体类型的函数了? 并且在写了之后,如果我们调用这个函数是调用函数模板还是具体的函数?
/*函数模板
*/
template <typename T>
const T& Max(const T& t1,const T& t2) {if (t1 == t2) {return t1;}cout << "const T& Max(const T& t1,const T& t2)" << endl;return t1 > t2 ? t1 : t2;
}/*具体类型函数
*/
const int& Max(const int& i1, const int& i2) {if (i1 == i2) {return i1;}cout << "const int& Max(const int& i1, const int& i2)" << endl;return i1 > i2 ? i1 : i2;
}int main(void) {int i1 = 10;int i2 = 20;Max(i1, i2); // 调用情况: const int& Max(const int& i1, const int& i2)float f1 = 15.5f;float f2 = 16.6f;Max(f1, f2); // const T& Max(const T& t1,const T& t2)char c1 = 'a';char c2 = 'd';Max(c1, c2); // const T& Max(const T& t1,const T& t2)system("pause");return 0;
}
分析:
1. 我们分别使用模板和具体类型(int 类型)实现Max()的函数。 然后我们在main函数中调用函数。
会发现: 当我们传入的值为int类型的时候,会调用具体类型实现的Max()函数,而当我们使用其它的类型的时候,就会调用函数模板。
总结:
1) 首先函数重载和函数模板可以同时存在。
2) 如果我们传入的数据类型和普通函数中的参数类型完全一致,那么就优先调用具体类型的函数实现。
3) 如果传入的数据类型和普通函数中的参数类型有不一样(即使,传入的类型和参数类型可以默认转换, 如: char -> int),那也会优先调用函数模板。
4) 我们在模板定义时,我们定义了一个虚拟类型T,这也就是说,在这个函数模板中使用到虚拟类型T的都是同一个类型。所以,如果我们传入的参数是一个int,一个char,那么此时会调用普通类型的函数实现。
因为: 我们定义的函数模板只有一个虚拟类型名T,也就是参数中的参数类型,只有一种。但是我们传入的是char和int两种类型,所以和函数模板的参数类型不匹配。
但是, 我们定义的普通类型函数的参数是int类型的,char类型可以隐式转换为int类型,所以这时候会调用普通类型函数。
5)所以,1.如果传入的参数和普通函数完全一致,优先调用普通函数实现。
2.如果传入的参数和普通函数不一致,但是符合函数模板的参数要求,则调用函数模板。
3.如果传入的参数和普通函数和函数模板的参数都不一致,但是传入参数可以隐式转换为普通函数的参数类型,那么调用普通函数实现。
函数模板重载
函数模板和函数重载是可以共存的,那么函数模板能不能进行重载呢? 答案是,肯定的。
实际说来,函数模板也是函数,只是编译器帮助我们实现了而已。前面使用函数模板将Swap()函数由多个写为了一个,但是前提是函数的函数实现中除去类型的差距其余都是一样的。
如果我们想要使用相同的模板函数名实现不同的功能,这时候就需要用到函数模板的重载了。 函数模板的重载和普通函数的重载是类似的,都是根据参数进行区别的。
/*模板函数交换一般数据的值
*/
template <typename T>
void Swap(T& t1, T& t2) {T tmp = t1;t1 = t2;t2 = tmp;
}/*模板函数交换数组中的数据
*/
template <typename T>
void Swap(T t1[], T t2[], int len) {// 遍历互换for (int i = 0; i < len; i++) {T tmp = t1[i];t1[i] = t2[i];t2[i] = tmp;}
}template <typename T>
void printA(T t1[], int len) {for (int i = 0; i < len; i++) {cout << t1[i] << " ";}cout << endl;
}int main(void) {int i1 = 10;int i2 = 20;Swap(i1, i2); // 调用情况: const int& Max(const int& i1, const int& i2)int arr1[] = {1,2,3,4,5};int arr2[] = { 6,7,8,9,10 };int len = sizeof(arr1) / sizeof(arr1[0]);Swap(arr1, arr2, len);printA(arr1, len);printA(arr2, len);system("pause");return 0;
}
分析:
1. 我们之前实现的交换数据,只能实现普通的类型进行互换,如果是数组中的数据进行互换,直接arr1 = arr2,这是不正确的。 对数组进行互换,我们需要遍历数组中的每个元素,然后逐一互换。
2. 但是我们前面实现的函数模板自然就不适合数组互换了,所以我们需要对Swap函数进行重载,将函数模板的内部的代码重新实现。以支持数组数据的互换。
3. int a[10]中,数组a是int [10]的类型的。我们在模板参数中如果直接写成T t,那替换过来就是int [10]a,这样写显然不正确,所以我们应该写成T t1[],或者使用指针或者引用。其实和一般情况下,数组传参数的一样的。
4. 代码中,函数模板中的参数,不一定都需要使用虚拟类型,也可以包括一般类型。