初始函数模板

问题一:函数模板有什么用?

所谓模板,实际上是建立一个通用函数或类,其类内部的类型和函数的形参类型不具体指定,用一个虚拟的类型来代表。这种通用的方式称为模板。模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码。

这是C++提供的模板(template)编程的概念。从中大致可以看出模板可实现独立于任何特定类型的方式编写代码。然后我们通过一个例子去感受下函数模板的作用。

问题是交换两个元素并返回,元素有各种类型,如char、int、double等,如果使用普通函数那么就可能要针对每种类型写一个函数。函数模板代码如下:

template<typename T> //我的模板叫T
void myswap(T &a, T &b) {//T和其他的类一样的使用
	cout << "我是函数模板" << endl;
	T c = a;
	a = b;
	b = c;
}

然后我们在主函数中调用我们的函数模板:

void main() {
	int aa = 10, bb = 20;
	double a = 10.11, b = 20.22;
	myswap(aa, bb);
	myswap(a, b);
	cout << "交换后" << endl;
	cout << "aa=" << a << " bb=" << b << endl;
	cout << "a=" << a << " b=" << b << endl;
}

结果如下:

可以看出一个函数模板实现了对两种不同类型的数据实现了交换。

问题二:函数模板生成函数实例的过程

前面我们说函数模板可以当抽象类使用,因此也可以进行实例化,那么其实例化过程是怎样的?

在程序运行过程中,模板函数会进行两次编译,第一次编译函数模板,第二次编译是根据泛型具体的类型进行编译并进行实例化,我们结合反汇编可以更深入的理解。

 可以看出函数模板根据具体的类型实例化出了对应的函数

问题三:普通函数与模板函数重载

1.可以重载吗?(可以)

2.重载了优先调用哪个函数呢?(普通函数)

3.当有对应的普通函数是我可以硬用函数模板吗?(可以)

下面我们通过具体的例子对这几个问题进行回答。

template<typename T> //我的模板叫T
void myswap(T &a, T &b) {
	cout << "我是函数模板" << endl;
	T c = a;
	a = b;
	b = c;
}

void myswap(int &a, int &b) {
	cout << "我是普通函数" << endl;
	int c = a;
	a = b;
	b = c;
}

上面声明了一个普通函数和一个函数模板,下面对这两个函数进行调用 

void main() {
	int aa = 10, bb = 20;
	double a = 10.11, b = 20.22;
	cout << "aa=" << a << " bb=" << b << endl;
	cout << "a=" << a << " b=" << b << endl;
	myswap(aa, bb);
	myswap(a, b);
	cout << "交换后" << endl;
	cout << "aa=" << a << " bb=" << b << endl;
	cout << "a=" << a << " b=" << b << endl;
}

 

由此可以得出
1. 可以重载

2. 当有对应的普通函数时,相比函数模板,程序优先调用普通函数。

那么我对应的普通函数是我可以硬用函数模板吗?可以的,函数模板的实例化有隐性实例化和显式实例化。函数模板隐式实例化指的是在发生函数调用的时候,如果没有发现相匹配的函数存在,编译器就会寻找同名函数模板,如果可以成功进行参数类型推演,就对函数模板进行实例化。对于函数模板而言,不管是否发生函数调用,都可以通过显示实例化声明将函数模板实例化。

下面我们通过一个例子来说明如何进行显式实例化

void main() {
	int aa = 10, bb = 20;
	double a = 10.11, b = 20.22;
	cout << "aa=" << a << " bb=" << b << endl;
	cout << "a=" << a << " b=" << b << endl;
	myswap<int>(aa, bb);
	myswap(a, b);
	cout << "交换后" << endl;
	cout << "aa=" << a << " bb=" << b << endl;
	cout << "a=" << a << " b=" << b << endl;
}

可以看出,就算有匹配的函数时,我们依然可以通过显式实例化调用函数模板。 

问题四:出现不符合函数模板实现方式的特例怎么做? 特化

模板特化:就是在实例化模板时,对特定类型的实参进行特殊处理,即实例化一个特殊的实例版本。

假如我们要交换两个有两个元素的元组的第二个元素,显然,上面的模板函数就不适用了,就要对这类函数进行特化。

template < >
void myswap(pair<int,int> &a, pair<int, int> &b) {
	int c = a.second;
	a.second = b.second;
	b.second = c;
}

void main() {
	pair<int, int> a = { 1,2 }, b = {3,3};
	cout <<"a:  "<<a.first << " " << a.second << endl;
	cout << "b:  " << b.first << " " << b.second << endl;
	myswap(a, b);
	cout << "交换后" << endl;
	cout << "a:  " << a.first << " " << a.second << endl;
	cout << "b:  " << b.first << " " << b.second << endl;
}

显然,完成了交换。

 上面特化模板函数的声明所用的语句template < >表明这个函数是函数模板的特化。

另外有一个问题,可以同时声明template < >void myswap(int &a, int &b) 和void myswap(int &a, int &b)这样的两个函数吗?答案是可以的,第一个函数是函数模板的一部分,而第二个是普通函数,当有匹配的函数时,如果没有硬用函数模板,依然优先调用普通函数。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值