c++函数模板基础知识

导航

1.函数模板及注意事项
2.用模板写个排序函数
3.普通函数与函数模板的区别
4.普通函数与函数模板的调用
5.模板的局限性
———————————————————————————————————
1.函数模板
语法:template< typename T>
typename也可以用class
其中T为通用类型,下面看两个例子
例1:

#include <iostream>
using namespace std;
//交换两个整型函数
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,b = 20;
	double c = 1.1,d = 2.2;
	swapint(a,b);
	swapDouble(c,d);
	cout<<"a = "<<a<<endl;
	cout<<"b = "<<b<<endl;
	cout<<"c = "<<c<<endl;
	cout<<"d = "<<d<<endl;
}
int main()
{
	test01();
	system("pause");
	return 0;
}

为将两个不同类型的值互换我们要写两个函数,若string类型互换呢,就又要写一个函数,这时候我们就可以用到模板

例2:

#include <iostream>
using namespace std;
//函数模板
template<typename T>
void swapT(T &a,T &b)
{
	T temp = a;
	a = b;
	b = temp;
}
void test02()
{
	int a = 10,b = 20;
	double c = 1.1,d = 2.2;
	//1.自动类型推导
	swapT(a,b);
	//2.显示指定类型
	swapT<double>(c,d);
	cout<<"a = "<<a<<endl;
	cout<<"b = "<<b<<endl;
	cout<<"c = "<<c<<endl;
	cout<<"d = "<<d<<endl;
}

int main()
{
	test02();
	system("pause");
	return 0;
}

这里我们写一个模板套用即可,模板套用有两种方法
1.自动类型推导——(swap(a,b))
2.显示指定类型——(swap< int >(a,b))

注意事项
1.自动推导类型,必须推导出一致的数据类型,才可以使用
2.模板必须确定T的数据类型,才可以使用

例1:(注意1)

#include <iostream>
using namespace std;

//函数模板
template<typename T>
void swapT(T &a,T &b)
{
	T temp = a;
	a = b;
	b = temp;
}

//注意事项
void test()
{
	int a = 10;
	int b = 20;
	char c = 'a';
	swapT(a,b);  //正确
	//swapT(a,c);	//错误
}

int main()
{
	test();
	system("pause");
	return 0;
}

例2:(注意2)

#include <iostream>
using namespace std;

//函数模板
template<typename T>
void func()
{
	cout<<"func()调用"<<endl;
}

//注意事项
void test()
{
	func<void>();  //这里必须加数据类型,不然无法调用
}

int main()
{
	test();
	system("pause");
	return 0;
}

———————————————————————————————————
2.利用模板写排序函数

#include <iostream>
using namespace std;

//对不同数据类型数组进行排序
//从大到小,算法为选择排序
//类型char型,int型
template<class 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 max = i;
		for(int j=i+1;j<len;j++)
		{
			if(arr[j]>arr[max])
			{
				max = j;
			}
		}
		if(max != i)
		{
			//交换max与i下标
			myswap(arr[i],arr[max]);
		}
	}
}

//提供打印数组模板
template<class T>
void myprintArr(T arr[],int len)
{
	for(int i=0;i<len;i++)
	{
		cout<<arr[i]<<" ";
	}
}


void test01()
{
	//测试char数组
	char charArr[] = "badcfe";
	int len = sizeof(charArr)/sizeof(char);
	mysort(charArr,len);
	myprintArr(charArr,len);
}

void test02()
{
	//测试int数组
	int intArr[] = {7,2,5,4,3,1};
	int len = sizeof(intArr)/sizeof(int);
	mysort(intArr,len);
	myprintArr(intArr,len);
}

int main()
{
	test02();
	system("pause");
	return 0;
}

利用模板写会省力一些

———————————————————————————————————
3.普通函数与函数模板的区别

1.普通函数调用可以发生隐式类型转换
2.函数模板用自动类型推导,不可以发生隐式类型转换
3.函数模板用显示指定类型,可以发生隐式类型转换

例:

#include <iostream>
using namespace std;

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

//调用模板
template<class T>
T fun(T a, T b)
{
	return a+b;
}

void test02()
{
	int a =10,b =20;
	char c = 'a';
	//1.调用普通函数 可以会发生隐式类型转换
	cout<<func(a,b)<<endl;  
	cout<<func(a,c)<<endl;
	//2.用函数模板自动类型推导,不发生隐式类型转换
	cout<<fun(a,b)<<endl;
	//3.函数模板用显示指定类型,可以发生隐式转换
	cout<<fun<int>(a,c)<<endl;   //这里要提供指定类型
}

int main()
{
	test02();
	system("pause");
	return 0;
}

———————————————————————————————————
4.普通函数与函数模板的调用规则

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

调用规则1

#include <iostream>
using namespace std;

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

//函数模板
template<class T>
void myprint(T &a,T &b)
{
	cout<<"函数模板调用"<<endl;
}

void test()
{
	int a=10,b=20;
	myprint(a,b);
}

int main()
{
	test();
	system("pause");
	return 0;
}

结果是先调用普通函数

调用规则2

#include <iostream>
using namespace std;

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

//函数模板
template<class T>
void myprint(T &a,T &b)
{
	cout<<"函数模板调用"<<endl;
}

void test()
{
	int a=10,b=20;
	myprint<>(a,b);  //使用空模板参数列表强制调用
}

int main()
{
	test();
	system("pause");
	return 0;
}

调用规则3

若函数模板发生重载,其中调用参数不同即可

调用规则4

#include <iostream>
using namespace std;

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

//函数模板	
template<class T>
void myprint(T a,T b)
{
	cout<<"函数模板调用"<<endl;
}

void test()
{
	char a = 'a',b = 'c';
	myprint(a,b);   
}

int main()
{
	test();
	system("pause");
	return 0;
}

这里会调用函数模板

———————————————————————————————————
5.模板的局限性
若只传入一些普通类型的单个数据,是可以的,若传入数组或者类,就要使用具体化的方法实现

例:

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

//写一个类
class Person
{
public:
	Person(string name,int age)
	{
		this->name = name;
		this->age = age;
	}

	string name;
	int age;
};

//模板 用于单个普通的类型,数组或者自定义就不行,应该用具体方法实现
template<class T>
bool compare(T a,T b)
{
	if(a==b)
	{
		return true;
	}
	else
	{
		return false;
	}
}

//写一个person类的模板,里面传入的也要改为对应的类型
template<> bool compare(Person p1,Person p2)
{
	if(p1.name == p2.name && p1.age == p2.age)
	{
		return true;
	}
	else
	{
		return false;
	}
}

void test()
{
	int a=10,b =10;
	bool ret = compare(a,b);
	//测试普通的类型
	if(ret)
	{
		cout<<"a == b"<<endl;
	}
	else
	{
		cout<<"a != b"<<endl;
	}

	//测试Person类 
	Person p1("小明",12);
	Person p2("小明",12);
	bool ret1 = compare(p1,p2);
	if(ret1)
	{
		cout<<"p1 == p2"<<endl;
	}
	else
	{
		cout<<"p1 != p2"<<endl;
	}
}

int main()
{
	test();
	system("pause");
	return 0;
}
发布了8 篇原创文章 · 获赞 2 · 访问量 144

猜你喜欢

转载自blog.csdn.net/cl939974883/article/details/104076235