题目:2023-2024(1)C++程序设计实验6-by Lyx - 函数模板与类模板
I am not good at socializing with others, nor do I understand the truth behind ambiguity. Is that a loss?
我不擅长逢迎交际,也难以理解暧昧的真意。这样是一种欠缺吗?
一, 题目要求:
1.总体要求
利用函数模板实现对整型数组和字符数组的排序。
2.输入形式
【样例输入】
无需手动输入
3.输出形式
【样例输出】
before sort: 5 55 2 22 4 77
after sort: 2 4 5 22 55 77
before sort: n s a j l k d s
after sort: a d j k l n s s
二,题目解析:
1.答案
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
template<typename T>
void mySwap(T &a, T&b)
{
T temp = a;
a = b;
b = temp;
}
template<class T>
void mySort(T arr[], int len)
{
for (int i = 0; i < len; i++)
{
int min = i;
for (int j = i + 1; j < len; j++)
{
if (arr[min] > arr[j])
{
min = j;
}
}
if (min != i) {
mySwap(arr[min], arr[i]);
}
}
}
template<typename T>
void printArray(T arr[], int len) {
for (int i = 0; i < len; i++) {
cout << arr[i] << " ";
}
cout << endl;
}
void test01()
{
cout<<"before sort: ";
char charArr[8] = {'n','s','a','j','l','k','d','s'};
int num = sizeof(charArr) / sizeof(char);
printArray(charArr, num);
mySort(charArr, num);
cout<<"after sort: ";
printArray(charArr, num);
}
void test02()
{
cout<<"before sort: ";
int intArr[] = {5,55,2,22,4,77};
int num = sizeof(intArr) / sizeof(int);
printArray(intArr, num);
mySort(intArr, num);
cout<<"after sort: ";
printArray(intArr, num);
}
int main() {
test02();
cout<<endl;
test01();
return 0;
}
2.分步解析
1.需要定义的函数模板
①交换函数(自定义mySort(a,b)函数/swap(a,b)函数)
②排序函数(自定义mySort(a,b)函数/sort(a,b)函数)
③输出函数
④输入函数(本题无要求)
⑤整型数组和字符数组的排序实现的集合函数
2.*函数模板的定义与使用
定义
// 定义一个函数模板
template <typename T>
T max(T a, T b) {
return (a > b) ? a : b;
}
使用
// 使用函数模板
int maxInt = max(num1, num2);
float maxFloat = max(float1, float2);
在上述示例中,我们定义了一个函数模板max
,它可以比较两个相同类型的值,并返回较大的值。函数模板的定义以template <typename T>
开头,其中T
是一个占位符类型,表示函数模板可以接受任意类型的参数。
优点
-
通用性:函数模板可以处理多种数据类型,通过使用类型参数来泛化不同的数据类型。这使得代码更加通用、灵活,并且可以在不同的场景中重复使用。
-
可维护性:通过使用函数模板,可以避免重复编写类似的代码。这样可以减少代码量,提高代码的可读性和可维护性。当需要对函数进行修改时,只需要修改一处模板代码,而不需要修改多个相似的函数。
-
减少错误:使用函数模板可以减少因为重复编写类似代码而引入的错误。通过统一的模板代码,可以减少代码的复制粘贴,从而减少了出错的机会。
-
简化复杂性:在大型项目中,可能会涉及多种数据类型的处理。使用函数模板可以简化代码的复杂性,减少了需要编写和维护的代码量,提高了开发效率。
-
提高代码的可读性:函数模板可以使代码更加简洁和易于理解。通过使用模板参数,可以清晰地表达代码的意图,使代码更加易读。
-
提高代码的性能:函数模板可以通过编译器的优化来提高代码的性能。编译器会根据提供的类型为模板创建合适的函数实例,从而避免了运行时的类型转换和开销。
-
代码重用:函数模板可以在不同的场景中重复使用,从而提高了代码的重用性。这样可以减少代码的冗余,提高了开发效率。
3.函数的实现
1)交换函数
用第三变量temp进行a,b交换
template<typename T>
void mySwap(T &a, T&b)
{
T temp = a;
a = b;
b = temp;
}
2)排序函数
分别为选择排序,冒泡排序,插入排序
本例为选择排序(将unsorted value 与sorted value比较,诺小,调换两者)
template<class T>
void mySort(T arr[], int len)
{
for (int i = 0; i < len; i++)
{
int min = i;
for (int j = i + 1; j < len; j++)
{
if (arr[min] > arr[j])
{
min = j;
}
}
if (min != i) {
mySwap(arr[min], arr[i]);
}
}
}
3)输出函数
template<typename T>
void printArray(T arr[], int len) {
for (int i = 0; i < len; i++) {
cout << arr[i] << " ";
}
cout << endl;
4)整合函数
void test01()
{
cout<<"before sort: ";
char charArr[8] = {'n','s','a','j','l','k','d','s'};//可以直接给出num
int num = sizeof(charArr) / sizeof(char);
printArray(charArr, num);
mySort(charArr, num);
cout<<"after sort: ";
printArray(charArr, num);
}
void test02()
{
cout<<"before sort: ";
int intArr[] = {5,55,2,22,4,77};//可以通过(数组字节/元素字节)给出num
int num = sizeof(intArr) / sizeof(int);
printArray(intArr, num);
mySort(intArr, num);
cout<<"after sort: ";
printArray(intArr, num);
}
通过整合函数使主函数简便
int main() {
test02();
cout<<endl;
test01();
return 0;
}
三,常见问题:
*函数模板的定义与使用的常见问题包括以下几点:
- 函数模板的一般形式为:
template <typename T>
返回类型 函数名(形参表){
// 函数体
}
*其中,typename T
表示模板参数,可以是任意类型。
2.使用函数模板时,需要在函数名后面加上尖括号<>
,并在尖括号中指定具体的类型。例如:
函数名<具体类型>(实参表);
3.函数模板的特例化,函数模板的特例化是指为特定类型提供特定的实现。特例化的语法如下:
template <>
返回类型 函数名<特定类型>(形参表){
// 特定类型的实现
}
特例化的优先级比普通函数模板低,但比非模板函数高。
4.函数模板和普通函数的调用优先级
当程序中同时定义同名的函数模板和普通函数时,编译器处理函数调用时的优先级如下:
- 非模板函数优先级最高;
- 模板特例化次之;
- 最后调用函数模板。
5.函数模板的实参推断规则
函数模板的实参推断是指根据函数调用时提供的实参,推断出模板参数的具体类型。实参推断规则如下:
- 如果实参的类型与模板参数的类型完全匹配,则直接使用该类型;
- 如果实参的类型可以隐式转换为模板参数的类型,则使用转换后的类型;
- 如果实参的类型无法匹配模板参数的类型,则编译器报错。