C++语言学习记录-32:模板

模板的作用

C++中,模板的作用就是实现代码的重用,通过将某种数据类型定义为参数,然后将不同的数据类型按照实参形式传送而实现代码重用
比如如下的程序

int min(int x, int y)
{return (x<y)? x:y;}

 float min(float x, float y)
 {return (x<y)? x:y;}
 
 double min(double x, double y)
 {return (x<y)?x:y;}

在以上的例子中,同样的功能和标识符的函数,因为数据类型不同需要进行重载,使用函数模板就可以避免这样浪费的情况发生

函数模板

函数模板将数据类型作为参数,将功能相同的函数使用一个通用的模板来完善,是不同的形参都可以调用该模板,避免函数的重复设计占用资源与时间

template<class T1, class T2,...>
返回值 函数名(形参表){
...
}

class后面所跟的是类型参数名,是后面函数的形参表中参数的名称

#include<iostream>
using std::cout;
using std::endl;
template<class T>
T min(T x, T y)
{
   return (x < y) ?  x: y;
}
void main()
{
   int n1 = 2, n2 = 10;
   double d1 = 1.5, d2 = 5.6;
   cout << "smaller integer" << min(n1, n2)<<endl;
   cout << "smaller double" << min(d1, d2);
}

这个函数模板就可以以一个函数实现之前多个函数的功能,极大节省了时间与空间。
这里的T就起到一个替代作用,在不确定输入的是什么数据类型的情况下代替精确的数据类型

类模板

类模板是类定义的一种模式,他将类中的数据成员各成员函数的参数值故意者返回值定义为模板,在使用中,改模板可以是任何数据类型。
类模板不是一个具体的类,是指具有相同特性但成员的数据类型不同的一族类

template<class T>//或者<typename T>
class 类名{
...
}

下面举一个例子说明模板类是如何使用的

#include<iostream>
using std::cout;
using std::endl;
class A
{
public:
	A(int i) { m_A = i; }
	~A() {}
	static void print()
	{
		std::cout << "A" << endl;
	}
	friend class B;
protected:
	int m_A;
};
class B {
public:
	B(int i)
	{
		m_B = i;
	}
	static void print()
	{
		cout << "B" << endl;
	}
	void show(B b)
	{
		b.a->m_A = 3;
		b.m_B = 2;
	}
private:
	A* a;
	int m_B;
};
template<typename T1, typename T2>
class CTestTemplate
{
public:
	CTestTemplate(T1 t)
	{
		m_number = t;
	}
	void print()
	{
		T2::print();
		cout << m_number << endl;
	}
private:
	T1 m_number;
};
void main()
{
	CTestTemplate<int, B>testtem(3);
	testtem.print();
}

本例首先定义了A类,在该类中又定义了一个输出函数,将A中的成员变量输出,后又定义了一个与A类相似的B类,输出了B类的成员内容。定义了类模板类CTestTemplate,在该类中分别对其中的类成员T1和T2进行了操作,将T1赋给了成员变量,调用了T2的输出函数将结果输出
简单来说,类模板也是给输入类型不确定的类进行设计

模板参数

模板可以看做一种类型,在使用模板函数的时候也就应该会产生它的一个实例。
对平台类型实例化的时候通常需要提供必要的参数,模板函数并不例外,只是C++的模板参数不是一般情况下的参数,而是一种特定的类型。也就是说,在实例化一个函数模板的时候,需要以类型作为参数
对于模板参数的调用,一般有以下两种方式
1.显示实例化模板参数

#include<iostream>
using std::cout;
using std::endl;
template<typename T>
inline T const&max(T const&a, T const&b)
{
	return a < b ? a : b;
}
int main()
{
	cout<<max<double>(4, 4.2);
}

2.隐式地实例化函数模板

#include<iostream>
using std::endl;
using std::cout;
template<typename T>
inline T const& max(T const& a, T const& b)
{
	return a < b ? a : b;
}
int main()
{
	int i = max(42, 66);
	cout << i;
}

这两组代码看起来是相似,不同之处只是在调用时是否明确调用的是模板中的哪一种数据类型。
T只是一个数据类型的“代号”,如果不明确需要调用的数据类型的话,函数便无从下手。

模板的特殊化

模板的特殊化指的是当模板中的pattern有确定的类型时,模板有一个具体的实现。

#include<iostream>
using namespace std;
template<class T>
class Pair
{
	T value1, value2;
public:
	Pair(T first, T second)
	{
		value1 = first;
		value2 = second;
	}
	T module()
	{
		return 0;
	}
};
template<> class Pair<int>
{
	int value1, value2;
public:
	Pair(int first, int second)
	{
		value1 = first;
		value2 = second;
	}
	int module();
};
int Pair<int>::module()
{
	return (value1 % value2);
}
int main()
{
	Pair<int>myints(100, 75);
	Pair<float>myfloats(100.0, 75.0);
	cout << myints.module()<<endl;
	cout << myfloats.module();
	return 0;
}

模运算只能对整型生效,所以这里需要在输入非整型实数时让函数值总是返回0,专门将模板定义为int型使用

重载和函数模板

C++支持函数模板的重载,其匹配规则如下

  • 寻找和使用最符合函数名和函数类型的函数,若找到则调用
  • 寻找一个函数模板,将其实例化产生一个匹配的目标函数,若找到则调用
  • 寻找可以通过类型转换进行参数匹配的重载函数,若找到则调用
  • 如果按以上步骤均未找到匹配函数,则调用错误
  • 如果调用有多于一个的匹配选择,则调用匹配出现二义性

下面使用一个程序详解重载的函数模板

#include<iostream>
using namespace std;
template<class T>
const T& Max(const T& x, const T& y)
{
   cout << "A template function! Max is:";
   return (x > y) ? x : y;
}
template<class T>
const T& Max(const T& a, const T& b, const T& c)
{
   T s;
   s = Max(a, b);
   return Max(s, c);
}
const int& Max(const int& x, const int& y)
{
   cout << "An overload function with int,int Max is:";
   return (x > y) ? x : y;
}
const char Max(const int& x, char const& y)
{
   cout << "An overload function with int, char, Max is:";
   return (x > y) ? x : y;
}
void main()
{
   int i = 10;
   char c = 'a';
   double f = 98.74;
   cout << Max(i, i) << endl;
   cout << Max(c, c) << endl;
   cout << Max(3.3, 5.6, 6.6) << endl;
   cout << Max(i, c) << endl;
   cout << Max(c, i) << endl;
   cout << Max(f, f) << endl;
   cout << Max(f, i) << endl;
}

本例中首先定义了一个函数模板用以取最大值,接下来对该函数模板进行重载,然后分别用不同函数重载函数模板

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值