C++学习笔记36 模版的显式具体化和显式实例化

C++的模版有时候很可能无法处理某些类型。

例如:

#include <iostream>
using namespace std;
class man{
private:
	string name;
	int data;
public:
	man(string s,int i):name(s),data(i){
	}
	void show()const{
		cout<<"this name is "<<name<<" ,data="<<data<<endl;
	}
};
template <class T>
void mSwap(T t1,T t2){
	T temp=t1;
	t1=t2;
	t2=temp;
	cout<<"Here are template version "<<t1<<" and "<<t2<<" swap successed!"<<endl;

};
int main()
{
	mSwap(88,66);
	man m1("guang",99);
	man m2("jing",10);
	mSwap(m1,m2);
}

编译结果:

可以看到会出现很多错误。(虽然这不是重点。)

假设我希望mSwap只是交换两个man的data,而name还保持与原来一样。该怎么做呢?

这个时候,就需要我们为特定的类型提供具体化的模版定义了。

具体化包括显式具体化以及隐式实例化和显式实例化。

1.显式具体化的原型和定义应以template<>开头,并通过名称来指出类型。

template<>
void mSwap(man &m1,man &m2)

或者

template<>
void mSwap<man>(man &m1,man &m2)

修改后的例子:

#include <iostream>
using namespace std;
class man{
private:
	string name;
	int data;
public:
	man(string s,int i):name(s),data(i){
	}
	void show()const{
		cout<<"this name is "<<name<<" ,data="<<data<<endl;
	}
	void setData(int d){
		data=d;
	}
	int getData()const{
		return data;
	}
};
template <class T>
void mSwap(T &t1,T &t2){
	T temp=t1;
	t1=t2;
	t2=temp;
	cout<<"Here are template version "<<t1<<" and "<<t2<<" swap successed!"<<endl;

};
template<>
void mSwap(man &m1,man &m2){
	int temp=m1.getData();
	m1.setData(m2.getData());
	m2.setData(temp);
	cout<<"Here are the man version,successed!"<<endl;
}
int main()
{
	int i=88,j=66;
	mSwap(i,j);
	man m1("guang",99);
	man m2("jing",10);
	mSwap(m1,m2);
	m1.show();
	m2.show();
}

运行截图:

这就是模版显式具体化的作用了。

需要注意的是,具体化优先于常规模版,而非模版函数优先于具体化和常规模版。

2.实例化

要进一步了解模版,必须理解术语实例化和具体化。记住,在代码中包含函数模版本身并不会生成函数定义,它只是一个用于生成函数定义的方案。编译器使用模版为特定类型生成函数定义时,得到的是模版实例,例如,上面的mSwap(i,j),函数调用mSwap(i,j)导致编译器生成mSwap()的一个实例,该实例使用int类型。

模版并非是函数定义,但使用int的模版实例是函数定义。这种实例化方式被称为隐式实例化。

C++还可以显式实例化。

语法为,声明所需的种类--用<>符号指示类型,并在声明之前加上关键字template:

templata void mSwap<man>(man &,man &)

该声明的意思是“使用mSwap()模版生成man类型的函数定义”。

C++学习笔记36 模版的显式具体化和显式实例化,布布扣,bubuko.com

时间: 2024-12-17 08:39:00

C++学习笔记36 模版的显式具体化和显式实例化的相关文章

C++学习笔记34 模版的原理

模版在C++中具有非常重要的地位,STL就是大量运用模版写出来的. 模版的优点我就不一一列举了.这里我只说一下模版的原理. 当编译器遇到模版方法定义的时候,编译器进行语法检查,但是并不会编译模版.编译器无法编译模版定义,因为编译器不知道要使用的类型是什么,编译器不知道x和y的类型的情况下无法为x=y这样的语句生成代码. 当编译器遇到一个实例化的模版的时候,例如vector<int> vi(这里我只是拿vector举例,实际上基本类型的vector代码好像会自动存在编译器中),编译器会将模版类定

C++学习笔记36 (模板的细节明确template specialization)和显式实例(template instantiation)

C++有时模板很可能无法处理某些类型的. 例如: #include <iostream> using namespace std; class man{ private: string name; int data; public: man(string s,int i):name(s),data(i){ } void show()const{ cout<<"this name is "<<name<<" ,data="

[原创]java WEB学习笔记36:Java Bean 概述,及在JSP 中的使用,原理

本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 ---------------------------------

android学习笔记36——使用原始XML文件

XML文件 android中使用XML文件,需要开发者手动创建res/xml文件夹. 实例如下: book.xml==> <?xml version="1.0" encoding="utf-8"?> <books> <book publishDate="2016.05.05" price="88.6">android学习笔记</book> <book publishD

C++中函数模板,显式具体化,显式实例化:

函数模板 形如: template<typename T>  //没有分号 void func(T &a,T &b); 称为函数模板,其中,template和typename为关键字,typename可以用class来替代.T(可以用其他的名称)表示一种泛型,既可以表示int型,也可以表示double或其他类型,将它想象成C++里面的数据类型的集合. 也就是说: void func(T &a,T &b)= void func(int &a,int &am

C++学习笔记36:类模板

类模板的目的 设计通用的类型式,以适应广泛的成员数据型式 类模板的定义格式 template<模板形式参数列表>class 类名称{...}; 原型:template<typename T> class A; 类模板的成员 像普通类的成员一样定义 定义在类中或类外均可,后者需要在类名后列些模板参数,以区别非模板类的成员函数 template<typename T> T A<T>::f(u) 类成员函数的模板 成员函数可以使用其他模板 template<

C++学习笔记之模版 remove_reference(引用移除)

int main() { int a[] = {1,2,3}; decltype(*a) b = a[0]; a[0] = 4; cout << b; //输出4 return 0; } 输出为4,因为decltype(*a)返回*a的类型,实际上是一个int&,我们就想有没有办法去掉这个引用 尝试1 template <typename T> class remove_reference { public: typedef T type; }; int main() {

Android学习笔记(36):Android的两种事件处理方式

Android提供了两种事件处理的方式:基于回调的事件处理 和 基于监听的事件处理. 我们来说的容易理解一点: (1)基于回调的事件处理就是继承GUI组件,并重写该组件的事件处理方法.除了一些特定的情况,大部分情况使用基于回调的事件处理方式并不是最好的选择. (2)基于监听的事件处理就是在监听器中定义事件的处理方式,再为组件绑定监听器.这种方式无疑是更能够体现面向对象思想的. 基于回调的事件处理: View类包含如下的方法可以用于重写: boolean onKeyDown(int keyCode

Scala中Context Bounds代码实战及其在Spark中的应用源码解析之Scala学习笔记-36

package com.leegh.parameterization /** * @author Guohui Li */ class Pair_Ordering[T: Ordering](val first: T, val second: T) { def bigger(implicit ordered: Ordering[T]) = { if (ordered.compare(first, second) > 0) first else second }} object Context_Bo