【C++】解析模板的概念及用模板实现一个顺序表

news/2024/5/20 9:31:56 标签: c++, 模板, 顺序表

模板是C++中泛型编程的基础,一个模板就是一个创建类或函数的蓝图或公式。— C++ primer

目录

1 模板概念

模板并不是真正的函数或类,只是一个模具,当有实例化的时候,就会生成相应的函数或类。

模板的种类:
在这里插入图片描述

2 函数模板

2.1 函数模板概念

模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。

2.2 函数模板格式

  1. template<typename T1,typename T2,typename T3,typename T4,.......>,typename是用来定义模板类型的关键字
  2. template<class T1,class T2,class T3,class T4,.......>,这里不能用struct代替class

例:

template <class T> 
T ADD(T left, T right)//模板函数
{
	return left + right;
}

2.3 函数模板的调用原理

在编译阶段,编译器对传入的实参类型进行推演,根据其推演的实参类型,生成具体类型的函数以供调用。

例:

template <class T> 
T ADD(T left, T right)//模板函数
{
	return left + right;
}


int main()
{
	ADD(1, 2);//int类型
	ADD(1.0, 2.0);//double类型
	ADD('A', 'B');//char类型
	return 0;
}

其反汇编中调用的函数为:不同的类型调用了不同的函数。
在这里插入图片描述

2.4 函数模板的实例化

用不同类型的参数使用函数模板时,称为函数模板的实例化。

  1. 隐式实例化:没有明确指定模板参数的实际类型,让编译器根据实参推演模板参数的实际类型。

例:

template <class T> 
T ADD(T left, T right)//模板函数
{
	return left + right;
}


int main()
{
	ADD(1, 2);
	ADD(1.0, 2.0);
	ADD('A', 'B');
	ADD(1, 1.1);//该类型不能通过编译
	//ADD(1,(int)1.1);//强转类型
	return 0;
}

第四种为什么编译不会通过呢?

模板中,编译器一般不会进行隐式类型转换。若没有类型匹配的函数,则直接进行报错。
解决方法:①用户自己强转,②使用多个类模板参数

template <class T1, class T2>//
T2 ADD(T1 left, T2 right)//多模板参数函数
{
	return left + right;
}
  1. 显式实例化:在调用函数名后的<>中指定模板参数的实际类型

例:

template <class T> 
T ADD(T left, T right)//模板函数
{
	return left + right;
}


int main()
{
	ADD(1, 2);
	ADD(1.0, 2.0);
	ADD('A', 'B');
	ADD<int>(1, 1.1);//显式实例化
	return 0;
}

编译器就会根据用户所提供的函数模板生成函数。若类型不匹配,则会隐式类型转换。转换成功则执行代码,转换失败则会报错。

2.5 函数模板调用规则

  1. 模板函数和同名模板函数同时存在,并且该模板函数可以被实例化为该非模板函数。在调用时,若是隐式实例化为该非模板函数,则调用非模板函数,显式实例化为该模板函数,则调用模板函数。
  2. 若是模板函数产生了一个具有更换匹配的函数,则调用模板函数。

 
 
 
 

3 类模板

只要用户对类模板进行了不同类型的实例化,编译器在编译阶段就会生成不同的类。

模板和函数模板大体上相同,但在实例化时有区别:

  1. 模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可。

例:

template <class T>
class SeqList
{
private:
	T* _data;
	size_t _size;
	size_t capacity;
};

3.1 类模板实现一个顺序表

template <class T>
class SeqList
{
public:
	SeqList(size_t capacity = 15)//构造函数
		:_data(new T[capacity])
		,_size(0)
		,_capacity(capacity)
	{}

	SeqList(SeqList<T>& psq)//拷贝构造函数
	{
		if (psq._data != nullptr)
		{
			_data = new T[psq._capacity];
			_capacity = psq._capacity;
			_size = psq._size;
			memcpy(_data, psq._data, sizeof(T) * psq._size);
		}
	}

	~SeqList()//析构函数
	{
		if (_data)
			delete[] _data;
		_size = _capacity = 0;
	}

	void SeqListPushBack(T data)//尾部插入
	{
		if (_size == _capacity)
		{
			cout << "顺序表已满,不能插入" << endl;
			return;
		}
		_data[_size++] = data;
	}

	void SeqListPopBack()//尾部删除
	{
		if (_size == 0)
		{
			cout << "顺序表为空,不能删除" << endl;
			return;
		}
		_size--;
	}
	T SeqListSize()//查看元素个数
	{
		return _size;
	}
	
	T& operator[](int index)
	{
		assert(index >= 0 && index < _capacity);
		return _data[index];
	}

private:
	T* _data;
	size_t _size;
	size_t _capacity;
};

http://www.niftyadmin.cn/n/1664482.html

相关文章

推荐一些经过实践检验的学习方法

作者做了多年的Java培训教师&#xff0c;也接触过不少初学者&#xff0c;根据多年的教学互动经验&#xff0c;总结了一些能少走弯路的学习方法&#xff0c;供大家参考。 第一&#xff0c;是要多学多练&#xff0c;这似乎是废话&#xff0c;但真正能非常上心学习的人还真是少数&…

MacOS如何关闭Prometheus?

背景 macos 用brew 安装的Prometheus&#xff0c;启动正常。 终端使用 brew services stop prometheus 命令关闭无效 终端使用 curl -X POST http://localhost:9090/-/quit 命令关闭无效 关闭Prometheus 1、【终端】输入命令查看端口号 ps -ef |grep prometheus 2、【终端】…

3.6《深入理解计算机系统》笔记(四)虚拟存储器,malloc,垃圾回收【插图】...

概述 ●我们电脑上运行的程序都是使用虚拟存储&#xff0c;跟物理内存根本不搭边。 ●既然虚拟内存是在磁盘上的&#xff0c;为什么它又运行这么好&#xff0c;并没有感觉卡顿&#xff1f;这要感谢程序的局部性! ●虚拟存储器的调度是一个操作系统必须做好的事情&#xff01;不…

Redis的string数据结构各场景项目实战

目录 目录 目录 前言 本文示例环境 String类型的使用场景 string-缓存场景&#xff1a;session缓存 0、场景介绍&#xff1a; 1、环境&#xff1a; 2、配置&#xff1a; 3、 java代码&#xff1a; 4、 测试&#xff1a; string-缓存场景&#xff1a;单值/对象缓存…

【Linux】一篇文章彻底搞定信号!

信号1.信号是什么&#xff1f;2.信号的种类3.信号的产生3.1硬件产生3.2软件产生4.信号的注册4.1非可靠信号的注册4.2可靠信号的注册5.信号的注销5.1非可靠信号的注销5.2可靠信号的注销6.信号阻塞6.1信号是怎样阻塞的&#xff1f;6.2sigprocmask7.信号未决7.1未决概念7.2sigpend…

c语音-第零次作业

1.你认为大学的学习生活、同学关系、师生应该是怎样&#xff1f; 我认为大学学习应该以自我学习为主&#xff0c;由以往的被动学习改为主动学习&#xff0c;探索新世界&#xff0c;除学习专业知识外对自身欠缺的地方也应该加以补足&#xff1b;同学之间要互相帮助&#xff0c;更…

attach: task_for_pid(xxxx) failed: ‘(os/kern) failure‘ (5)

项目场景&#xff1a; 项目场景&#xff1a;mac使用jmap命令出现此错误 Error attaching to process: sun.jvm.hotspot.debugger.DebuggerException: Cant attach symbolicator to the process 问题描述&#xff1a; Attaching to process ID 7243, please wait... Error att…

logsource and ALO

1、首先配置sourcedb上的nfs服务,oggstd上挂载sourcedb的online redo和archive log的目录oggsource上配置&#xff1a;vi /etc/exports /u01/app/oracle 134.178.1.182(rw,no_root_squash,no_all_squash,sync)save and exitexportfs -rlinux 6.X service nfs start service r…