2021-8-8 C++提升学习 -> 1.1&1.2 函数模板

目录

1.1模板的概念

1.2.1函数模板语法

1.2.2函数模板的注意事项

1.2.3函数模板案例

1.2.4普通函数与模板函数的区别

1.2.5普通函数与函数模板的调用规则

1.2.6模板的局限性


1.1模板的概念

template<typename T>

1.2.1函数模板语法


template<typename T>//声明一个模板,告诉编译器后面代码中紧跟着的T不要报错,T是一个通用数据类型

    利用函数模板交换
    两种方式使用函数模板
    1、自动推导类型

    2、显示指定类型

#include <iostream>
#include <string>
using namespace std;

//函数模板
template<typename T>//声明一个模板,告诉编译器后面代码中紧跟着的T不要报错,T是一个通用数据类型
void mySwap(T &a, T&b)
{
	T temp = a;
	a = b;
	b = temp;
}

//两个整型交换的函数
void swapInt(int &a, int &b)
{
	int temp = a;
	a = b;
	b = temp;

}

//交换两个浮点型函数
void swapDouble(double &a, double &b)
{
	double temp = a;
	a = b;
	b = temp;
}

void test01()
{
	int a = 10;
	int b = 20;

	//利用函数模板交换
	//两种方式使用函数模板
	//1、自动推导类型
	mySwap(a, b);
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	//2、显示指定类型
	mySwap<int>(a, b);
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;


	swapInt(a, b);
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;

	double c = 1.1;
	double d = 2.2;

	swapDouble(c, d);
	cout << "c = " << c << endl;
	cout << "d = " << d << endl;
}
int main() {

	test01();
	system("pause");
}

1.2.2函数模板的注意事项

typename可以替换为class

1、自动推导类,必须推导出一致的数据类型T才可以使用

2、模板必须要确定出T的数据类型,才可以使用

#include <iostream>
#include <string>
using namespace std;

//函数模板注意事项
template<class T>//typename可以替换为class
void mySwap(T &a, T&b)
{
	T temp = a;
	a = b;
	b = temp;
}
//1、自动推导类,必须推导出一致的数据类型T才可以使用
void test01()
{
	int a = 10;
	int b = 20;
	mySwap(a, b);
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
}
//2、模板必须要确定出T的数据类型,才可以使用
template<class T>
void func()
{
	cout << "func 调用" << endl;


}

void test02()
{
	func<int>();
}
int main() {
	test02();
	test01();
	system("pause");
}

1.2.3函数模板案例

实现通用的对数组进行排序的函数
规则 从大到小
算法 选择
测试 char数组 int 数组

#include <iostream>
#include <string>
using namespace std;

//实现通用的对数组进行排序的函数
//规则 从大到小
//算法 选择
//测试 char数组 int 数组

//打印函数模板
template<class T>
void printArr(T arr[], int len)
{
	for (int i = 0; i < len; i++)
	{
		cout << arr[i] << " " ;
	}
	cout << endl;
}
//交换函数模板
template<class T>
void mySwap(T &a, T &b)
{
	int temp = a;
	a = b;
	b = temp;
}
//排序算法
template<class T>
void mySort(T arr[], int len)
{
	for (int i = 0; i < len; i++)
	{
		int max = i;//设定最大值下标
		for (int j = i + 1; j < len; j++)
		{
			//认定的最大值比 遍历的最大值要小 说明J下标的元素才是真正的最大值
			if (arr[max] < arr[j])
			{
				max = j;//更新最大值下标
			}
		}
		if (max != i)
		{
			//交换max和i元素
			mySwap(arr[max], arr[i]);
		}
	}

}

void test01()
{
	//测试char数组
	char charArr[] = "a h n o s d f j";
	int num = sizeof(charArr) / sizeof(char);
	mySort(charArr, num);
	printArr(charArr,num);
}

void test02()
{
	//测试int数组
	int intArr[] = { 1,5,2,7,12,6,8,1};

	int num = sizeof(intArr) / sizeof(int);

	mySort(intArr, num);
	printArr(intArr, num);
}
int main() {

	test01();
	test02();
	system("pause");
}

1.2.4普通函数与模板函数的区别

自动推导型 不会发生隐式类型转换
    cout << myAdd02(a, b) << endl;

显示指定类型 会发生隐式类型转换
    cout << myAdd02<char>(a, c) << endl;

普通函数与函数模板的区别
1、普通函数调用的时候可以发生隐式类型转换
2、函数模板 用自动类型推导,不可以发生隐式类型转换
3、函数模板 用显示指定类型,可以发生隐式类型转换

#include <iostream>
#include <string>
using namespace std;


//普通函数与函数模板的区别
//1、普通函数调用的时候可以发生隐式类型转换
//2、函数模板 用自动类型推导,不可以发生隐式类型转换
//3、函数模板 用显示指定类型,可以发生隐式类型转换

//普通函数
int myAdd01(int a, int b)
{
	return a + b;
}

//函数模板
template<class T>
T myAdd02(T a,T b)
{
	return a + b;
}
void test01()
{
	int a = 10;
	int b = 20;
	char c = 'c';
	cout << myAdd01(a, c) << endl;

	//自动推导型 不会发生隐式类型转换
	cout << myAdd02(a, b) << endl;
	//显示指定类型 会发生隐式类型转换
	cout << myAdd02<char>(a, c) << endl;

}

int main() {

	test01();
	system("pause");
}

1.2.5普通函数与函数模板的调用规则

普通函数与函数模板调用规则
1、如果函数模板和普通函数都可以调用,优先调用普通函数
2、可以通过空模板参数列表 强制调用 函数模板
3、函数模板可以发生函数重载
4、如果函数模板可以产生更好的匹配,优先调用函数模板

#include <iostream>
#include <string>
using namespace std;

//普通函数与函数模板调用规则
//1、如果函数模板和普通函数都可以调用,优先调用普通函数
//2、可以通过空模板参数列表 强制调用 函数模板
//3、函数模板可以发生函数重载
//4、如果函数模板可以产生更好的匹配,优先调用函数模板

void myPrint(int a, int b)
{
	cout << "调用的普通函数" << endl;
}

template<class T>
void myPrint(T a, T b)
{
	cout << "调用的模板" << endl;
}

template<class T>
void myPrint(T a, T b, T c)
{
	cout << "调用重载的模板" << endl;
}
void test01()
{
	int a = 10;
	int b = 20;

	myPrint(a, b);

	//通过空模板的参数列表,强制调用函数模板
	myPrint<>(a, b);

	myPrint(a, b, 100);

	//4、如果函数模板可以产生更好的匹配,优先调用函数模板
	char a1 = 'c';
	char a2 = 'd';
	myPrint(a1, a2);
}
int main() {

	test01();
	system("pause");
}//既然使用了函数模板,就不要用普通函数,防止发生二义性

1.2.6模板的局限性

1、利用具体化的模板,可以解决自定义类型的通用化
2、学习模板并不是为了写模板,而是再STL能够运用系统提供的模板

模板的局限性
模板不是万能的,他需要特定的数据类型,需要用具体化方式做特殊实现
 

#include <iostream>
#include <string>
using namespace std;

//模板的局限性
//模板不是万能的,他需要特定的数据类型,需要用具体化方式做特殊实现

class person
{
public:
	person(string name, int age)
	{
		this->m_Age = age;
		this->m_Name = name;
	}
	string m_Name;
	int m_Age;
};



//对比两个数据是否相等函数
template<class T>
bool myCompare(T &a, T &b)
{
	if (a == b)
	{
		return true;
	}
	else
	{
		return false;
	}
}

//利用具体化的person的版本实现代码,具体化优先调用
template<> bool myCompare(person &p1, person &p2)
{
	if (p1.m_Age == p2.m_Age&&p1.m_Name == p2.m_Name)
	{
		return true;
	}
	else
	{
		return false;
	}
}




void test01()
{
	int a = 10;
	int b = 10;
	bool ret = myCompare(a, b);

	if (ret)
	{
		cout << "a == b" << endl;

	}
	else
	{
		cout << "a != b" << endl;
	}
}

void test02()
{
	person p1 = { "ton",10};
	person p2 = { "ton",11};

	bool ret = myCompare(p1, p2);
	if (ret)
	{
		cout << "p1 == p2" << endl;

	}
	else
	{
		cout << "p1 != p2" << endl;
	}
}
int main() {
	test02();
	test01();
	system("pause");
}//1、利用具体化的模板,可以解决自定义类型的通用化
//2、学习模板并不是为了写模板,而是再STL能够运用系统提供的模板

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值