c++学习之模板

news2024/11/16 1:51:04

目录

一,模板的概述

二,函数模板

1.函数模板的定义

2.函数模板的注意事项

3.函数模板的重载

4.函数模板的局限性

三,类模板

1.类模板的概念

2.类模板定义方式

3.类模板的成员函数在类外实现

4.函数模板作为类模板的友元

5.在写程序时模板的头文件与源文件分离时的问题。


一,模板的概述

c++提供了函数模板(function template),即建立一个通用的函数,不具体定义函数的参数类型以及函数类型,以他为模板。与该函数功能相同的函数我们定义时,直接利用模板,不必重新定义,大大提高了写代码的效率,其次根据模板定义不同的参数的类型以及函数的类型,实现函数不同的功能。总的来说,C++中的模板是一种支持参数化多态的工具,使用模板可以使用户为类或者函数声明一种一般模式,使得类中的某些数据成员或者成员函数的参数、返回值取得任意类型。C++程序由类和函数组成,模板也分为类模板和函数模板。

这也是c++泛型编程思想:模板。

二,函数模板

1.函数模板的定义

关键字 template

 

 c++提供了关键字tmplate用来实现模板类型的虚拟化,在调用模板时,编译器会自动地将虚拟的类型具体化,对于函数类型,就是函数模板,对于类的抽象化类型,就是类模板。

在这里我们还会用到typename 也是一个关键字,专门用来表示函数模板中的类型

 

例如:

/利用template将T抽象成一个虚拟类型,即T认为是一个类型
//以交换函数来举例  
template<typename T> void myswap(T &x, T &y)//该类型抽象只作用该函数
{
	T tmp = x;
	x = y;
	y = tmp;
}
//再调用函数模板时,会自动将虚拟类型具体化
int main()
{
	int a = 10; int b = 20;
	myswap(a, b);//函数调用时会根据参数类型自动推导出T是哪一个类型
	cout << a << " " << b << endl;
   //20 10
	return 0;
}

可以看到函数模板在面对不同的参数类型都可以实现函数功能,展现了函数模板的多功能。

函数模板会被编译器编译两次:

第一次编译:对函数模板本身编译,即将函数源代码转化为机器码:预处理阶段。

第二次编译:函数调用处将T的类型具体化。

对于实例化过程:

C++ 函数模板中的类型具体化是在函数编译的过程中完成的,当使用函数模板创建一个具体类型的函数时,编译器会根据实际参数的类型来生成对应的函数代码,这个过程也被称为模板类或模板函数的实例化。在实例化时,编译器会将函数模板中的类型参数具体化为实际的类型,同时在编译器内部生成对应的代码。
需要注意的是,C++ 中的函数模板并不是一种动态类型或者泛型编程的方式,而是一种静态的模板化机制。因此,在编译阶段,编译器会将模板代码生成为具体的函数代码,以提高代码的效率和可靠性。

函数模板目标:模板是为了实现泛型,可以减轻编程的工作量,增强函数的重用性。

2.函数模板的注意事项

1.对于函数模板与普通函数,在函数调用时,函数时会优先选择普通函数。

如下图:函数在调用时优先选择普通函数

 2.普通函数和模板函数,像调用函数模板只能强制使用函数模板。

在调用时函数名与参数中间添加<>,表示强制调用函数模板。

当然我们也可以改变其中的类型<double>,强制调用模板类型为double。

 3.函数模板自动类型推导时,不能对函数的参数进行自动类型转换。

template<typename T>
void print(T a, T b)
{
	cout << a << b << endl;
	cout << "函数模板" << endl;
}
int main()
{
	int a = 10; char b = 'c';
	print(a, b);
}

类型不相同就不会调用,这里编译器会自动报错。

3.函数模板的重载

函数模板也可以同名,根据函数的参数以及雷响,在调用会自动调用对应的模板,也就是函数模板的重载。

template<typename T> void myprint(T a, T b)
{
	cout << a << b << endl;
	cout << "调用双参数模板" << endl;
}
template<typename T> void myprint(T a)
{
	cout << a  << endl;
	cout << "调用单参数模板" << endl;
}
int main()
{
	int a = 10;
	myprint(a);
	return 0;
}

4.函数模板的局限性

对于函数模板,这里的函数类型都是编译器认识的的,倘若遇到自定义类型如结构体或类时,该类型函数模板无法识别,函数无法实现其功能。解决办法如下:

一,一般是将运算符重载。

template<typename T> void myprint (T a)
{
	cout << a << endl;
}
class Data
{
	friend ostream& operator<<(ostream& out, Data x);
public:
	Data(int x)
	{
		data= x;
	}
	~Data(){}
private:
	int data;
};
ostream& operator<<(ostream& out, Data x)
{
	out << x.data;
	return out;
}

template<typename T> void myprint(T a)
{
	cout << a << endl;
}
int main()
{
	Data x(10);
	int a = 10;
	myprint(a);
	myprint(x);//需将函数里的所有运算符重载
	return 0;
}

二,具体化函数模板

再写函数模板,将之前的函数模板的类型删掉,重新具体实现函数模板的类型以及参数以及函数实现。

template<typename T> void myprint (T a)
{
	cout << a << endl;
}
class Data
{
	friend void myprint<Data>(Data a);
public:
	Data(int x)
	{
		data= x;
	}
	~Data(){}
private:
	int data;
};
//具体实例化模板
template<> void myprint<Data>(Data a)
{
	cout << a.data << endl;
}

int main()
{
	Data x(10);
	int a = 10;
	myprint(a);
	myprint(x);//需将函数里的运算符重载
	return 0;
}

三,类模板

1.类模板的概念

与函数模板的概念相类似,有时有两个类或多个类的功能是大体相同的,仅仅因为数据类型不一样,于是乎c++提供了函数模板近似的类模板,用于实现所需数据的类型参数化。

2.类模板定义方式

类模板定义方式如下:

//类模板
//这里的类型就不用typename,为了区分模板,这里就用class表示类
template<class T1, class T2> class Data
{
private:
T1 a;
T2 b;
public:
Data(){}
Data(T1 a, T2 b)
{
this->a = a;
this->b = b;
}

void showData()
{
cout<<a<<" "<<b<<endl;
}
};

对于类模板,在实例化对象时,不能自动推导类型:


int main()
{
	//不能这样定义
	//Data obj(10,20);
	//在实例化对象时,是无法自动推导出类中数据类型,需要标明
	Data<int,int >obj(10, 20);
	obj.showData();
	return 0;
}

3.类模板的成员函数在类外实现

若成员函数在类外实现,则需要注意其类模板的作用域是只在类中的,而成员函数在类外定义时就需要重新在成员函数前定义类模板。

//类模板
template<class T1, class T2> class Data
{
private:
T1 a;
T2 b;
public:
Data(){}
Data(T1 a, T2 b);
void showData();
};

template<class T1, class T2>Data<T1,T2>::Data(T1 a, T2 b)
{
this->a = a;
this->b = b;
}

template<class T1, class T2>void Data<T1,T2>::showData()
{
cout<<a<<" "<<b<<endl;
}

4.函数模板作为类模板的友元

函数可以作为类的友元函数,那么函数模板亦可作为类模板中友元函数模板

template<class T1, class T2>class Data
{
	template<typename T3, typename T4>friend void myPrintData(Data<T3, T4>& ob);//声明为友元
private:
	T1 a;
	T2 b;
public:
	Data() {}
	Data(T1 a, T2 b)
	{
		this->a = a;
		this->b = b;
	}
};
//函数模板
template<typename T3, typename T4> void myPrintData(Data<T3, T4>& ob)
{
	cout << ob.a << " " << ob.b << endl;
}
int main()
{
	Data<int, char> ob1(100, 'A');
	myPrintData(ob1);
}

在函数模板定义中我们可以看到其参数为类,而我们这里是类模板,故参数是需要实例化类的对象,其次需要引用代表对对象的操作。

其次还需要注意设置友元时,其中的template虚拟的类型也需要紧跟。

其中类中的数据类型在这里是所定义的类模板的类型。

5.在写程序时模板的头文件与源文件分离时的问题。

头文件定义类模板.

源文件中实现类中的成员函数(注意需加上数据类型)。如:

template<class T1,class T2> Data<T1,T2>::Data()
{
....
};

其次在主函数文件实例化对象时进行两次编译,第一次编译在预处理阶段,在头文件,编译类或函数本身,第二次编译在源文件中推导类型或指明类型,可是此时之前第一次编译类中的数据以及成员函数找不到了,第二次无法调用无法具体化并实现函数。

记得包含上源文件主函数才会通过。

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

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

相关文章

《大学英语4》期末考试复习(一)听力原文+答案速记

目录 Unit 1 Long conversation Passage 1 Unit 2 Long conversation Passage 1 Unit 3 Long conversation Passage 1 Unit 4 Long conversation Passage 1 Unit 5 Long conversation Passage 1 Unit 6 Long conversation Passage 1 Unit 7 Long conversat…

Java线程池小结

目录 一.什么是线程池 二.线程池的好处是什么 三.四种基本线程池及其使用 newCachedThreadPool newFixedThreadPool newScheduledThreadPool newSingleThreadExecutor 线程池的四种拒绝策略 选择一:AbortPolicy 选择二:CallerRunsPolicy 选择三:DiscardPolicy 选择四…

【Java】Java核心要点总结70

文章目录 1. volatile 如何保证变量的可⻅性&#xff1f;2. volatile 可以保证原⼦性么&#xff1f;3. synchronized 关键字4. synchronized 和 volatile 的区别5. synchronized 和 ReentrantLock 的区别 1. volatile 如何保证变量的可⻅性&#xff1f; 在Java中&#xff0c;使…

html实现多种风格的时间轴(附源码)

文章目录 1.设计来源1.1 对称风格时间轴1.2 横向风格时间轴1.3 回忆风格时间轴1.4 记事风格时间轴1.5 简易风格时间轴1.6 科技风格时间轴1.7 列表风格时间轴1.8 跑道风格时间轴1.9 人物风格时间轴1.10 容器风格时间轴1.11 沙滩风格时间轴1.12 双边风格时间轴1.13 图文风格时间轴…

【verilog基础】时钟无毛刺切换电路 Clock Glitch Free

文章目录 一、时钟切换电路:容易产生毛刺二、时钟无毛刺切换电路:在S端增加一些控制通路三、异步时钟无毛刺切换电路:使用同步电路解决亚稳态问题四、真题题目解答一、时钟切换电路:容易产生毛刺 1、在芯片运行时经常需要切换时钟源,通常的实现方式是:通过mux来选择不同的…

用试题这把“剑“帮你破除指针与数组之间的那些猫腻

作者主页&#xff1a;paper jie的博客_CSDN博客-C语言,算法详解领域博主 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 本文录入于《系统解析C语言》专栏&#xff0c;本专栏是针对于大学生&#xff0c;编程小白…

【linux】在Linux系统开机的时候卡在/dev/nvme0n1p1:clean / files / blocks界面进不去

一、问题背景 开机的时候没办法开机&#xff0c;一直停留在下面这个界面。 x86/cpu: SGX disabled by BIOS dev/nvme0n1p3:clean, 21118/30523392 fies, 122066176/122070272 blocks dev/nvme0n1p4:clean, 486125/61038592 fies,21657184/244140544b1ocks 试过网上的一些方法…

Ubuntu20.04+Intel SGX(一):环境安装与测试

文章目录 测试环境一、检查服务器是否支持SGX方法1&#xff1a;cpuid查看是否支持SGX方法2&#xff1a;test-sgx.c测试是否支持SGX验证是否支持SPS 二、启动 SGX 服务参考文档启动 SGX方法1&#xff1a;BIOS 启动SGX方法2&#xff1a;软启动 SGX检查SGX是否开启成功 三、安装 S…

C++在线五子棋对战(网页版)项目:环境搭建

Centos-7.6环境搭建 安装wget工具 wget工具是Linux中的一个下载文件的工具&#xff0c;支持通过 HTTP、HTTPS、FTP 三个最常见的TCP/IP协议 下载&#xff0c;并可以使用 HTTP 代理。可以使用以下命令进行下载&#xff1a; sudo yum install wget 下载后&#xff0c;可以使用以…

【Linux】CentOS7 设定本机当前地区时间为虚拟机时间的简单操作

目录 情景系统环境操作 情景 新安装的虚拟机时间和当前本地系统时间不一致&#xff0c;现在想要将虚拟机和本机地区的时间调节为一致。 系统环境 CentOS Linux 7 系统界面大致如此。 操作 点击虚拟机界面左上角的 Applications 选项&#xff0c; 选择System-Tools-- Sett…

【C++】C++关于异常的学习

文章目录 C语言传统的处理错误的方式一、异常的概念及用法二、自定义异常体系总结 C语言传统的处理错误的方式 传统的错误处理机制&#xff1a; 1. 终止程序&#xff0c;如 assert &#xff0c;缺陷&#xff1a;用户难以接受。如发生内存错误&#xff0c;除 0 错误时就会终止…

【Python】元组 创建 访问 切片 拼接 解包

2.3 元组 元组在输出时总是有括号的。 元组在输入时可以没有。 像字符串一样&#xff0c;元组是不可变的。 索引、切片以及一些方法很多与列表相似。 1&#xff09;定义 元组是一种不可变序列&#xff0c;它与列表类似&#xff0c;但元组的元素不能修改。元组中的元素可以是任意…

【Vuejs】1720- 详细聊一聊 Vue3 动态组件

&#x1f449; 「相关文章」 深入浅出 Vue3 自定义指令6 个你必须明白 Vue3 的 ref 和 reactive 问题初中级前端必须掌握的 10 个 Vue 优化技巧分享 15 个 Vue3 全家桶开发的避坑经验 动态组件[1]是 Vue3 中非常重要的一个组件类型&#xff0c;它可以让我们在不同的场景下灵活地…

Git远程仓库使用

说明&#xff1a;使用Git&#xff0c;可以实现版本控制和协作开发。需要协作开发&#xff0c;当然需要建立一个Git代码托管的平台。目前可以使用GitHub、码云、GitLab等&#xff0c;码云相当于国内的GitHub&#xff0c;在国内访问速度高于GitHub&#xff1b;而GitLab是搭建私服…

阿里云服务器的可靠性和稳定性如何?是否有SLA保障?

阿里云服务器的可靠性和稳定性如何&#xff1f;是否有SLA保障&#xff1f;   一、阿里云服务器的可靠性   阿里云服务器作为全球领先的云计算服务平台&#xff0c;以其高性能、高可靠性和高安全性获得了广泛好评。为满足企业客户对稳定、可靠云服务的需求&#xff0c;阿里云…

「译文」用ChatGPT助力SEO工作

大家好&#xff0c;我是可夫小子&#xff0c;《小白玩转ChatGPT》专栏作者&#xff0c;关注AIGC、读书和自媒体。 那些使用ChatGPT的先进人士&#xff0c;也没还能完全掌握它内容生成的能力&#xff0c;特别是像博客那样的长文写作能力。 现在&#xff0c;跟大家介绍 一下SEO优…

GeoServer中使用Qgis发布的SLD样式进行图层美化

目录 知识地图 一、前言 二、Qgis符号化转变成SLD 1、Qis中符号化生成 2、SLD样式导出 三、GeoServer数据发布 1、矢量图层发布 2、在GeoServer中发布样式 总结 知识地图 序号博文链接1使用LeafLet叠加Geoserver wms图层到已有底图的方法2关于GeoServer发布服务时数据源…

windows -- 自动安装python包,并启动服务

文章目录 定制python的包编写批处理文件遇到的问题 自动安装python的包&#xff0c;并启动后台服务进程。 定制python的包 基于python的Flask框架&#xff0c;简单开发一个服务器&#xff1b;编写发布python包的setup.py 在my_ff包的同级目录下创建一个setup.py&#xff0c…

【跟小嘉学 Rust 编程】三、Rust 的基本程序概念

系列文章目录 【跟小嘉学 Rust 编程】一、Rust 编程基础 【跟小嘉学 Rust 编程】二、Rust 包管理工具使用 【跟小嘉学 Rust 编程】三、Rust 的基本程序概念 文章目录 系列文章目录前言一、变量以及可变性1.1、变量声明语法1.2、不可变变量1.3、未使用变量警告1.4、使用 let mu…

【雕爷学编程】Arduino动手做(119)---JQ6500语音模块

37款传感器与执行器的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&am…