[C++ Primer Plus]实例化与具体化

在代码中包含函数模板本身并不会生成函数定义,它只是一个用于生成函数定义的一个方案。编译器在使用模板为特定类型生成函数定义时,得到的是模板实例。如下程序使用char类型,生成一个Swap的实例:

template <typename T>
void Swap(T& a, T& b); //< 函数模板

void main()
{
	char g = 1;
	char h = 2;
	Swap(g, h); //g=2, h=1
}

template <typename T>
void Swap(T& a, T& b)
{
	T tem;
	tem = a;
	a = b;
	b = tem;
}

注意,模板并非函数定义,但使用char的的模板实例是函数定义,这种实例化方式叫做隐式实例化。

C++还允许使用显示实例化,其语法为:声明所需的种类(用<>符号指示),并在声明前加上关键字template。如下程序使用显示实例化生成了了一个int类型的函数定义:

template <typename T> //< 函数模板
void Swap(T& a, T& b);

template void Swap<int>(int &, int&); //< 使用Swap模板显示地生成int类型函数定义

void main()
{
	char g = 1;
	char h = 2;
	Swap(g, h); //< 隐式实例化

	int i = 10;
	int j = 20;
	Swap(i, j); //< 显示实例化
	cout << "i = " << i << " " << "j = " << j << endl;
}

template <typename T>
void Swap(T& a, T& b)
{
	T tem;
	tem = a;
	a = b;
	b = tem;
}

到此产生了一个疑问,显示实例化有什么用呢?其实可以总结下二者的区别:

隐式实例化:后面有程序用了,编译器才会根据模板生成一个实例函数;

显式实例化:是无论是否有程序用,编译器都会生成一个实例函数;

另一个概念就是显示具体化,也就是特化,即使通用模板特殊化,当程序找到与函数调用匹配的具体化时,将使用该定义,而不再寻找模板。

显示具体化的原型和定义应以template<>打头,并通过名称来支出类型,可以使用下面两个等价的声明之一:

template<> void Swap<int>(int &c1, int &c2);
template<> void Swap(int &c1, int &c2);

意思就是,“不要使用Swap模板来生成函数定义,使用专门为int类型显示定义的函数定义”。

如下程序使用显示具体化完成Swap的特殊形式,即交换两个元素的一部分内容:

 struct job
  {
 	 char name[40];
 	 double salary;
 	 int floor;
  };
  void show(job& j);
 
  template <typename T> //< 函数模板
  void Swap(T& a, T& b);
 
  template void Swap<int>(int &, int&); //< 使用Swap模板显示地生成int类型函数定义
 
  template<> void Swap<job>(job& j1, job& j2);//< 显示具体化,特化Swap模板
  //< or
  //template<> void Swap(job& j1, job& j2);//< 显示具体化,特化Swap模板
 
  void main()
  {
 	 char g = 1;
 	 char h = 2;
 	 Swap(g, h); //< 隐式实例化
 
 	 int i = 10;
 	 int j = 20;
 	 Swap(i, j); //< 显示实例化
 	 cout << "i = " << i << " " << "j = " << j << endl;
 
 	 job sue = { "susan",7300,7 };
 	 job sidney = { "sidney",7800,5 };
 	 Swap(sue, sidney); //< 使用显示具体化
 	 show(sue); //< susan:$7800 on floor:5
 	 show(sidney); //< sidey:$7300 on floor:7
  }
 
  template <typename T>
  void Swap(T& a, T& b) //常规模板
  {
 	 T tem;
 	 tem = a;
 	 a = b;
 	 b = tem;
  }
 
  template<> void Swap<job>(job& j1, job& j2) //< 显示具体化
  {
 	 double t1;
 	 int t2;
 	 t1 = j1.salary;
 	 j1.salary = j2.salary;
 	 j2.salary = t1;
 	 t2 = j1.floor;
 	 j1.floor = j2.floor;
 	 j2.floor = t2;
 	 //< 此处只交换了j1与j2的一部分
  }
 
  void show(job& j)
  {
 	 cout << j.name << ":$" << j.salary << "  "
 		 << "on floor:" << j.floor << endl;
  }

至此已经出现了显示实例化,隐式实例化,显示具体化,非模板函数(即普通函数),那么在函数调用时,是如何选取哪个函数版本呢?答案是:

具体化优先于常规模板,非模板函数优先于具体化和常规模板。

同时,显示实例化,隐式实例化,显示具体化统称为具体化。

struct job
{
	char name[40];
	double salary;
	int floor;
};
void show(job& j);

template <typename T> //< 函数模板
void Swap(T& a, T& b);

template void Swap<int>(int &, int&); //< 使用Swap模板显示地生成int类型函数定义 显示实例化

template<> void Swap<job>(job& j1, job& j2);//< 显示具体化,特化Swap模板
//< or
//template<> void Swap(job& j1, job& j2);//< 显示具体化,特化Swap模板

void Swap(float c1, float c2); //< 非模板函数

void main()
{
	float a = 0.1; //< 调用非模板函数
	float b = 0.2;
	Swap(a, b);
	cout << "a = " << a << " " << "b = " << b << endl; //< a = 0.1 b = 0.2

	char g = 1;
	char h = 2;
	Swap(g, h); //< 隐式实例化
	cout << "g = " << (int)g << " " << "h = " << (int)h << endl; //< g = 2 h =1

	int i = 10;
	int j = 20;
	Swap(i, j); //< 显示实例化
	cout << "i = " << i << " " << "j = " << j << endl; //< i = 20 j = 10

	job sue = { "susan",7300,7 };
	job sidney = { "sidney",7800,5 };
	Swap(sue, sidney); //< 使用显示具体化
	show(sue); //< susan:$7800 on floor:5
	show(sidney); //< sidey:$7300 on floor:7
	
	cin.get();
}

void Swap(float c1, float c2)//< 非模板函数
{
	return;
}

template <typename T>
void Swap(T& a, T& b) //常规模板
{
	T tem;
	tem = a;
	a = b;
	b = tem;
}

template<> void Swap<job>(job& j1, job& j2) //< 显示具体化
{
	double t1;
	int t2;
	t1 = j1.salary;
	j1.salary = j2.salary;
	j2.salary = t1;
	t2 = j1.floor;
	j1.floor = j2.floor;
	j2.floor = t2;
	//< 此处只交换了j1与j2的一部分
}

 void show(job& j)
 {
 	cout << j.name << ":$" << j.salary<<"  "
 		<< "on floor:" << j.floor << endl;
 }

猜你喜欢

转载自blog.csdn.net/u012481976/article/details/80955018
今日推荐