C++之函数模板、类模板、模板的特化

news2024/10/2 6:39:59

1.什么是模板?

模板是c++的一种特性,允许函数或者类(对象)通过泛型(generic types)的形式表现或者运行模板可以使得函数或类在对应不同的类型(types)的时候正常工作,而无需为每一种类型分别写一份代码。

为了代码重用,代码就必须是通用的;通用的代码就必须不受数据类型的限制。那么我们可以把数 据类型改为一个设计参数。这种类型的程序设计称为参数化(parameterize) 程序设计。软件模块由模板 (template) 构造。 包括函数模板(function template)和类模板(class template)。

2.类模板的定义如下:


template<类型模板参数表>
class 类名
{
	…… //类声明体
}; //再次指出分号不可少
template<类型模板参数表>
返回类型 类名<模板参数表>::成员函数名1(形参表)
{
	……;//成员函数定义体
}
……
template<类型模板参数表>
返回类型 类名<模板参数表>::成员函数名n(形参表)
{
	……;//成员函数n定义体
}
//类型替换的过程被称为模板实例化 template instantiation
1

3.模板分类?

1.模板参数有两种:

模板类型参数和模板非类型参数

2.模板的类型

1.函数模板

函数模板是参数化的一族函数(a famliy of functions)

通过函数模板,可以实例化一系类函数,这些函数都给予同一套模板框架,但是作用在不通类型的参数上

示例 :(针对不同的数据类型 比较两个数据的大小)

求最大值:int型、char型。double型等等

int Max(int a, int b)
{
	return a > b ? a : b;
}

double Max(double a, double b)
{
	return a > b ? a : b;
}

char Max(char a, char b)
{
	return a > b ? a : b;
}

void main()
{
	cout << Max(5, 3) << endl;
	cout << Max(5.3, 7.3) << endl;
	cout << Max('C', 'c') << endl;
}

模板参数是由传递给模板函数的实参决定的

不允许自动类型转换:每个T必须严格匹配

 

使用模板

template<class T>             //函数模板--经过类型参数化--->模板函数
T Max(T a, T b)
{
	return a > b ? a : b;
}

 //模板的特化--具体化

template<>
const char* Max(const char* a, const char* b)
{
	cout << "const char* Max" << endl;
	return strcmp(a, b) > 0 ? a : b;
}

主函数

void main()
{
	cout << Max(4, 6) << endl;  //类型参数化 int
	cout << Max(3.4, 1.2) << endl; //double
	cout << Max('a', '1') << endl; //char
	cout << Max("333", "555") << endl; //const char*
}

运行结果

 2.类模板

与函数模板类似,类也可以通过参数泛化,从而可以构建出一族不同的类实例(对象)

类模板实参可以是某一类型或常量(仅限int或enum)

类模板特化

允许对一个类模板的某些模板参数类型做特化

特化的作用和好处

对于某种特殊的类型,可能可以做些特别的优化或提供不同的实现

避免在实例化的时候引起一些可能不好的行为

特化一个类模板的时候也意味着需要特化其所有参数化的成员函数

template<class T>
class A
{
public:
	A(T i) :m_i(i) {}
	void print()
	{
		cout << "m_i = " << m_i << endl;
	}
private:
	T m_i;
};
//vector  list stack  queue

template<>
class A<const char*>
{
public:
	A(const char* i)
	{
		cout << "A const char*" << endl;
		m_i = new char[strlen(i) + 1];
		strcpy_s(m_i, strlen(i) + 1, i);
	}
	void print()
	{
		cout << "A::m_i = " << m_i << endl;
	}
	~A()
	{
		delete[]m_i;
	}
private:
	char* m_i;
};
void main()
{
	A<int> a(4);  //将int当成参数传递给模板中的T--》模板类
	a.print();
	A<char> b('6');
	b.print();
	A<double> c(3.5);
	c.print();
	A<const char*> d("helloworld");
	d.print();
}

 

4.模板实例化

模板的声明(declaration)其实并未给出一个函数或者类的完全定义(definition),只是提供了一个函数或者类的语法框架(syntactical skeleton)

实例化是指从模板构建出一个真正的函数或者类的过程。用具体类型代替模板参数的过程叫做实例化;从而产生一个模板实例。

如果实例化一种类型,而该类型并不支持函数所使用的操作,那么就会导致一个编译错误。

实例化有两种类型
1:显示实例化-在代码中明确指定要针对哪种类型进行实例化

2:隐式实例化-在首次使用时根据具体情况使用一种合适的类型进行实例化


#include <algorithm>
bool great(char a, char b)
{
	return a > b;
}
class Great
{
public:
	bool operator()(char a, char b)
	{
		return a > b;
	}
};
template<class T>
class GREAT
{
public:
	bool operator()(T a, T b)
	{
		return a > b;
	}
};
void main()
{
	//int a[] = { 7,6,8,9,0,2,2,3,4,5,6,7 };
	char a[] = { '1','a','h','5','3','2','d','k','v','0','x' };
	int n = sizeof(a) / sizeof(a[0]);
	//sort(a, a + n); //将a到a+n从小到大进行排序---模板
	//sort(a, a + n, greater<int>());  //用的库中的greater
	//sort(a, a + n, great);
	//sort(a, a + n, Great()); //调用Great类中的()重载
	sort(a, a + n, GREAT<char>());
	for (int i = 0; i < n; i++)
		cout << a[i] << " ";
	cout << endl;
}

 5.模板实现链栈

1.C语言版


class MyStack
{
private:
	struct StackNode
	{
		int data;
		StackNode* next;
	public:
		StackNode(int val = 0, StackNode* p = nullptr)
			:data(val), next(p) {}
	};
private:
	StackNode* top; // heap;
	int cursize;
	void clone(const MyStack& s)
	{
		Clear();
		cursize = s.cursize;
		StackNode* p = s.top;
		if (p == nullptr) return;
		top = new StackNode(p->data); //
		StackNode* tail = top;
		p = p->next;
		while (p != nullptr)
		{
			tail = tail->next = new StackNode(p->data);
			p = p->next;
		}
	}
public:
	MyStack() :top(nullptr), cursize(0) {}
	MyStack(const MyStack& s)
		:top(nullptr), cursize(s.cursize)
	{
		clone(s);
	} // MyStack yous(mys);
	MyStack& operator=(const MyStack& s)
	{
		if (this != &s)
		{
			clone(s);
		}
		return *this;
	} // mys = hes;// top;
	~MyStack()
	{
		Clear();
	}
	void Clear()
	{
		while (top != nullptr)
		{
			StackNode* q = top;
			top = q->next;
			delete q;
		}
		cursize = 0;
	}
	int Size() const { return cursize; }
	bool Empty() const { return Size() == 0; }
	void Push(int val)
	{
		top = new StackNode(val, top); // 1 2 heap
		cursize += 1;
	}
	int& Top() { return top->data; }
	const int& Top()const { return top->data; }
	void Pop()
	{
		StackNode* q = top;
		top = q->next;
		delete q;
		cursize -= 1;
	}
	bool GetTop(int& val)
	{
		if (Empty()) return false;
		val = top->data;
		StackNode* q = top;
		top = q->next;
		delete q;
		cursize -= 1;
		return true;
	}
};
int main()
{
	MyStack mys;
	for (int i = 0; i < 10; ++i)
	{
		mys.Push(i);
	}
	MyStack ys(mys);
}

2.C++版本                         


template<class T> //
class MyStack
{
public:
	struct StackNode
	{
		T data; // int data;
		StackNode* next;
	public:
		StackNode(const T& val = T(), StackNode* p = nullptr)
			:data(val), next(p) {}
	};
private:
	StackNode* top; // heap;
	int cursize;
	void clone(const MyStack& s)
	{
		Clear();
		cursize = s.cursize;
		StackNode* p = s.top;
		if (p == nullptr) return;
		top = new StackNode(p->data); //
		StackNode* tail = top;
		p = p->next;
		while (p != nullptr)
		{
			tail = tail->next = new StackNode(p->data);
			p = p->next;
		}
	}
public:
	MyStack() :top(nullptr), cursize(0) {}
	MyStack(const MyStack<T>& s)
		:top(nullptr), cursize(s.cursize)
	{
		clone(s);
	} // MyStack yous(mys);
	MyStack<T>& operator=(const MyStack<T>& s)
	{
		if (this != &s)
		{
			clone(s);
		}
		return *this;
	} // mys = hes;// top;
	~MyStack()
	{
		Clear();
	}
	void Clear()
	{
		while (top != nullptr)
		{
			StackNode* q = top;
			top = q->next;
			delete q;
		}
		cursize = 0;
	}
	int Size() const { return cursize; }
	bool Empty() const { return Size() == 0; }
	void Push(const T& val) // T
	{
		top = new StackNode(val, top); // 1 2 heap
		cursize += 1;
	}
	T& Top() { return top->data; }
	const T& Top()const { return top->data; }
	void Pop()
	{
		StackNode* q = top;
		top = q->next;
		delete q;
		cursize -= 1;
	}
	bool GetTop(T& val);
};
template<class T>
bool MyStack<T>::GetTop(T& val)
{
	if (Empty()) return false;
	val = top->data;
	StackNode* q = top;
	top = q->next;
	delete q;
	cursize -= 1;
	return true;
}
int main()
{
	MyStack<int> imys;
	MyStack<char> cmys;
	MyStack<Point> pmys;
	MyStack<int>::StackNode x;
	for (int i = 0; i < 3; ++i)
	{
		pmys.Push(Point(i, i + 10));
	}
	Point px;
	while (pmys.GetTop(px))
	{
		cout << px.PointX() << " : " << px.PointY() << endl;
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/7588.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数组的substring方法和substr方法

数组的substring()方法、substr()方法都可以用于字符串截取 substr(start,length) 从指定下标开始截取指定长度的字符串&#xff0c;不改变字符串 start 必要&#xff0c;开始下标&#xff0c;若是负数&#xff0c;则从字符串尾部开始截取length 可选&#xff0c;若省略&…

2022年下半年系统架构师考试题

很多题目想不起来了&#xff0c;欢迎大佬们补充 综合知识 SASS、PASS 、IASS分别代表什么&#xff08;区别是什么&#xff09; A.软件即服务&#xff0c;平台即服务&#xff0c;基础设施即服务 目前Gpu的最高峰值是多少 A.100TFlops B.50TFlops C.10TFlops D.1TFlops Ai芯片…

antd常用组件 select,form等

参考代码为typescriptreact 树选择 TreeSelect 下拉选项的父子节点选中不相关 import { TreeSelect } from antd;<TreeSelectshowSearchstyle{{ width: 100% }}treeData{yyIndustryOptions} // treeNodes 数据dropdownStyle{{ maxHeight: 400, overflow: auto }} //下拉…

基于Python仓库管理系统的设计与实现django框架

摘 要 随着信息化时代的到来&#xff0c;系统管理都趋向于智能化、系统化&#xff0c;仓库管理系统也不例外&#xff0c;但目前国内的有些公司仍然都使用人工管理&#xff0c;公司规模越来越大&#xff0c;同时信息量也越来越庞大&#xff0c;人工管理显然已无法应对时代的变化…

Django 中间件

文章目录Django中间件默认中间件源码分析自定义中间件process_request&#xff08;掌握&#xff09;process_response&#xff08;掌握&#xff09;process_view(了解)process_template_response(了解)process_execption(了解)Django中间件 只要是涉及到全局相关的功能都可以使…

python基于PHP+MySQL的在线汽车租赁管理系统

随着时代的发展,汽车已经成为当代人们代步的主要工具。但是很多时候人们并没有购车的念头,这个时候就出现了一种新的行业,就是汽车租赁行业,这样不仅可以解决用车的需求,而且可以节省大量的购车成本,为了能够方便用户进行汽车租赁我们开发了PHP在线汽车租赁管理系统,本系统分为…

软件版本号详解

我们现在的生活离不开软件&#xff0c;版本号一般不会引起大家的关注&#xff0c;但是一旦软件出现了Bug或者其他问题&#xff0c;这个时候&#xff0c;软件的提供方都会让用户提供其软件的版本号。软件版本号长什么样呢&#xff1f;上面这张截图是我们常用的手机APP&#xff0…

关于git你应该知道的一些东西

前言 好好写代码&#xff0c;好好的反思踩过的坑&#xff0c;然后尽量不要给别人挖坑。这是我对自己&#xff0c;以及每个刚入行或即将的小伙伴的建议。一个软件工程项目&#xff0c;是一个系统性极强且较为复杂的工作&#xff0c;会有很多人参与到这个工作中来&#xff0c;如何…

Yarn pengding任务的原因之一:Reserved

一、背景 系统&#xff1a;linux centos7.4 Yarn&#xff1a;3.0.0-cdh6.3.2 二、现象 业务方通知&#xff0c;大部分使用yarn的任务都长时间处于执行中的状态。 三、问题排查 查看yarn的ui发现&#xff0c;memory reserved的值&#xff0c;已经和memory total等值了。 然…

Unity内实现无卡顿取图像推流/截屏等功能

文章目录 一、Unity提供的ScreenCapture取图像接口二、我们一个一个看API:三、Unity日本大神keijiro还提供了一种异步截图的方案,完整代码如下:一、Unity提供的ScreenCapture取图像接口 众所周知,Unity提供了ScreenCapture API用来获取引擎最终渲染到屏幕的图像: 二、我…

深度学习入门(三十五)计算性能 编译器和解释器

深度学习入门&#xff08;三十五&#xff09;计算性能 编译器和解释器前言计算性能——编译器和解释器教材1 符号式编程2 混合式编程3 Sequential的混合式编程3.1 通过混合式编程加速3.2 序列化4 小结前言 核心内容来自博客链接1博客连接2希望大家多多支持作者 本文记录用&…

【离散数学】第一章 测试

1. A. 对 B. 错 正确答案&#xff1a;A 2. A. 对 B. 错 正确答案&#xff1a;B 3. A. 错 B. 对 正确答案&#xff1a;B 4.p↔q⇔p↔q A. 对 B. 错 正确答案&#xff1a;A 5. A. 对 B. 错 正确答案&#xff1a;A 6.n个命题变元组成的命题公式共有( )种不同的…

小胶质细胞仅仅是神经系统内的“配角”?

大脑中存在着数量众多的神经胶质细胞&#xff0c;约占人类大脑细胞的 90%&#xff1b;不同类型的胶质细胞在起源、组成、形态和解剖学上都是不同的&#xff0c;而且它们发挥着不同的功能。 图 1. 中枢神经系统的四种神经细胞 小胶质细胞与 AD 疾病进程 小胶质细胞是一类来源于…

数据分析的重要性体现在哪?

近几年&#xff0c;数据分析成为了当今IT界的新起之秀&#xff0c;在我国互联网飞速发展的浪潮下&#xff0c;无论是公司职员还是个体商户或大公司管理者&#xff0c;都需要学习掌握数据分析的能力&#xff0c;它已经成为数据时代各行各业突破各自行业发展瓶颈的最有效手段。 那…

微信小程序复习题

文章目录填空题选择题判断题分析题&#xff08;20&#xff09;分析代码显示效果页面设计题&#xff08;40&#xff09;填空题 微信小程序创始人是 张小龙 &#xff0c;英文缩写 Mini Program小程序是一种无需下载和无需安装即可使用的应用&#xff0c;它实现了应用“ 触手可得…

[附源码]java毕业设计基于web的硕士研究生入学考务管理

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

5、Redis的发布和订阅

文章目录5、Redis的发布和订阅5.1、什么是发布和订阅5.2、Redis的发布和订阅5.2.1、客户端可以订阅频道如下图5.2.2、当给这个频道发布消息后&#xff0c;消息就会发送给订阅的客户端5.3、发布订阅命令行实现5.3.1、打开一个客户端订阅channel15.3.2、打开另一个客户端&#xf…

Day32——二叉树专题

文章目录28.删除二叉搜索树的节点29.修剪二叉搜索树30.将有序数组转换为二叉搜索树31. 把二叉搜索树转换为累加树28.删除二叉搜索树的节点 题目链接&#xff1a;450. 删除二叉搜索树中的节点 - 力扣&#xff08;LeetCode&#xff09; 如果目标节点大于当前节点值&#xff0c;则…

MapReduce编程模型——自定义序列化类实现多指标统计

&#x1f3e0;Hadoop序列化 &#x1f449;序列化 序列化就是把内存中的对象&#xff0c;转换成字节序列(或其他数据传输协议)以便于存储(持久化)和网络传输。反序列化就是将收到字节序列(或其他数据传输协议)或者是硬盘的持久化数据&#xff0c;转换成内存中的对象。 &#…

7天酒店亮相中国国际饭店业大会元宇宙线上展 创见酒店投资新未来

11月12日&#xff0c;由中国饭店协会主办的第一届酒旅菁英品牌嘉年华“元宇宙”线上展成功举行。7天酒店“元宇宙”展馆首度亮相&#xff0c;通过数字化交互、虚拟展厅、线上路演等&#xff0c;为行业和市场带来耳目一新的创新营销形式。 作为第七届中国国际饭店业大会的线上分…