C++_模板初阶
目录1.引言2.泛型编程3.函数模板3.1.函数模板概念3.2.函数模板格式3.3.函数模板的原理3.4.函数模板的实例化3.5.模板参数的匹配原则4.类模板4.1.类模板的定义格式4.2.类模板的实例化5.结语1.引言模板就是让C突飞猛进的一点和C语言拉开了差距接下来我们就来讲讲模板是怎么个回事话不多说直接进入正文——————​​​​​​​ ​​​​​​​ ​​​​​​​2.泛型编程用我们先前所学的知识如何实现交换俩个变量的通用交换函数呢代码如下#includeiostream using namespace std; void swap(int x, int y) { int tem x; x y; y tem; } void swap(double x, double y) { double tem x; x y; y tem; } void swap(char x, char y) { char tem x; x y; y tem; } int main() { return 0; }上述代码是用C的函数重载来实现的但是这个方法有几个不好的地方重载的函数仅仅是类型不同代码复用率比较低 只要有新类型出现就需要用户自己增加对应的重载函数代码的可维护性较低因为一个出错可能所有的重载均出错C语言的方式就更不用说了因为无法函数重载所以甚至函数名都要不一样虽然可以通过回调函数来优化但还是很麻烦这个时候C就提出了模板的概念通过给这个模板填充不同类型来生成具体类型的代码泛型编程编写与类型无关的通用代码是代码复用的一种手段模板是泛型编程的基础。模板又分为函数模板和类模板所以上面的通用交换函数就可以通过模板优化成如下代码函数模板具体在后面模板讲解中再具体讲#includeiostream using namespace std; templateclass T void Swap(T x, T y) { T tem x; x y; y tem; } int main() { int x 1, y 2; Swap(x, y); cout x y endl; char x1 9, y1 8; Swap(x1, y1); cout x1 y1 endl; return 0; }3.函数模板3.1.函数模板概念函数模板代表了一个函数家族该函数模板与类型无关在使用时被参数化根据实参类型产生函数的特定类型版本3.2.函数模板格式templatetypename T1,typename T2,...,typename Tn返回值类型 函数名(参数列表){}上面所讲的通用交换函数就是按照这个格式来实现的接下来我们来细细讲讲这个首先templatetypename T1,typename T2,...,typename Tn中的模板参数列表我们可以跟函数参数列表进行类比首先我们看函数参数列表是怎么样的如下也就是类型加上变量名定义的是一个一个变量void func1(int x1,char x2,doouble x3);而模板参数列表定义的是一个一个的类型也就是说T1T2T3这些既可以是相同的类型也可以是不同的类型而typename就是用来定义模板的关键字用多类型的模板的实例如下#includeiostream using namespace std; templateclass T1,class T2 void Run(T1 x, T2 y) { cout (double)x y endl; } int main() { int x1 1; double x2 10.2; Run(x1, x2); return 0; }知道了如何使用函数模板后其实C中的swap就是 通过函数模板来实现的源码如下图注意typename是用来定义模板参数的关键字也可以用class切记不能使用struct代替class3.3.函数模板的原理函数模板是一个蓝图它本身并不是函数是编译器用使用方式产生特定具体类型函数的模具所以其实模板就是将本来应该我们做的重复的事情交给了编译器在编译器编译阶段对于模板函数的使用编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如当用double类型使用函数模板时编译器通过对实参类型的推演将T确定为double类型然后产生一份专门处理double类型的代码对于字符类型也是如此3.4.函数模板的实例化用不同类型的参数使用函数模板时称为函数模板的实例化。模板参数实例化分为隐式实例化和显式实例化隐式实例化让编译器根据实参推演模板参数的实际类型以下俩种都属于隐式实例化需要注意的是形参部分要加const因为我们在下面传参y的时候对y进行了强转所以传过去的是临时对象临时对象具有常性所以需要用const接收不然就会导致权限放大#includeiostream using namespace std; templateclass T void func1(const T x, const T y) { cout (double)x y endl; } int main() { int x1 1, x2 2; double y 10.2; func1(x1, x2); func1(x1, (int)y); return 0; }显式实例化在函数名后的中指定模板参数的实际类型以上述代码为样例显式实例化核心代码就是如下部分func1double(x1, y);这就代表着T类型是double类型传过去的x1和y如果类型不符就会进行转化显式实例化主要用在如下这种情况#includeiostream using namespace std; templateclass T T* func(int n) { return new T[n]; } int main() { int*p funcint(10); return 0; }这种情况下T不是形参但是我们需要确定T的类型我们只能通过显式实例化来实现当然如果类型不匹配编译器会尝试进行隐式类型转换如果无法转换成功编译器将会报错3.5.模板参数的匹配原则如果同时存在非模板函数和同名的函数模板那么如果说调用时的参数类型可以和非模板函数匹配就不会通过函数模板实例化反之则会通过函数模板实例化举个例子如下#includeiostream using namespace std; templateclass T1,class T2 void add(const T1 x, const T2 y) { cout x y endl; } void add(const int x, const int y) { cout x * y endl; } int main() { add(10, 10); add(10, 10.0); return 0; }add(10,10)就会调用非模板函数add(10,10.0)就会对函数模板实例化注意函数模板不允许自动类型转换简单的说就是推导T的时候不能做隐式类型转换但普通函数可以进行自动类型转换4.类模板4.1.类模板的定义格式templateclass T1,class T2,...,class Tnclass 类模板名{//类内成员定义};以数据结构中的栈为例我们定义一个栈的类模板如下#includeiostream #includestdlib.h using namespace std; templateclass T class Stack { public: Stack(size_t capacity 4) :_capacity(capacity) , _node(new T[capacity]) , _size(0) { } ~Stack() { delete[] _node; _node nullptr; } void Push(const T x) { if (_capacity _size) { T* lin new T[_capacity * 2]; memcpy(lin, _node, sizeof(T) * _size); delete[] _node; _node lin; _capacity * 2; } _node[_size] x; } private: T* _node; size_t _size; size_t _capacity; }; int main() { return 0; }我们也可以把上述代码中的函数声明和定义分离注意是在同一个文件下声明定义分离不能在俩个文件声明定义分离这样会出现链接错误为什么会出现这问题之后在模板进阶部分讲代码如下#includeiostream #includestdlib.h using namespace std; templateclass T class Stack { public: Stack(size_t capacity 4) :_capacity(capacity) , _node(new T[capacity]) , _size(0) { } ~Stack() { delete[] _node; _node nullptr; } void Push(const T x); private: T* _node; size_t _size; size_t _capacity; }; templateclass T void StackT::Push(const T x) { if (_capacity _size) { T* lin new T[_capacity * 2]; memcpy(lin, _node, sizeof(T) * _size); delete[] _node; _node lin; _capacity * 2; } _node[_size] x; } int main() { return 0; }这里用StackT而不是Stack是因为Stack是类模板如果直接用Stack的话并无法知道用的是Stack类模板中的哪一种因为根据类型的不同Stack类模板生成的具体类也不同所以需要用StackT当然上面声明函数虽然是T但是在下面定义的时候我们用X呀Y呀之类也是可以的只是一般不这样用就如下templateclass X void StackX::Push(const X x) { if (_capacity _size) { X* lin new X[_capacity * 2]; memcpy(lin, _node, sizeof(X) * _size); delete[] _node; _node lin; _capacity * 2; } _node[_size] x; }4.2.类模板的实例化类模板的实例化和函数模板的实例化不同类模板的实例化必须是显式实例化。类模板名字不是真正的累只有类实例化之后的结果才是真正的类举个例子代码如下#includeiostream #includestdlib.h using namespace std; templateclass T class Stack { public: Stack(size_t capacity 4) :_capacity(capacity) , _node(new T[capacity]) , _size(0) { } ~Stack() { delete[] _node; _node nullptr; } void Push(const T x); private: T* _node; size_t _size; size_t _capacity; }; templateclass T void StackT::Push(const T x) { if (_capacity _size) { T* lin new T[_capacity * 2]; memcpy(lin, _node, sizeof(T) * _size); delete[] _node; _node lin; _capacity * 2; } _node[_size] x; } int main() { Stackint st1; st1.Push(1); st1.Push(2); st1.Push(3); Stackdoublest2; st2.Push(1.1); st2.Push(1.1); st2.Push(1.1); return 0; }类模板的出现可以让我们不用再像之前一样只用typedef来实现操作就比如上面Stack的情况如果用typedef的话如果我们既想要整形的又想要浮点型的又想要类类型的这个时候typedef只能用于一种类型的功能另外几种类型依旧要重复写但是有了类模板后我们只需要写上对应的类型编译器会自己给我们生成对应的类来实现相关功能极大的提高了代码的可重用性5.结语那么C模板初阶部分的内容就全部讲解完毕啦希望以上内容对你有所帮助感谢观看若觉得写的还可以可以分享给朋友一起来看哦毕竟一起进步更有动力嘛当然能关注一下就更好啦

相关新闻

Saucer开发者指南:从源码结构到平台特定API调用的深度探索

Saucer开发者指南:从源码结构到平台特定API调用的深度探索

Saucer开发者指南:从源码结构到平台特定API调用的深度探索 【免费下载链接】saucer 🛸 A modern, cross-platform C webview library 项目地址: https://gitcode.com/gh_mirrors/sa/saucer Saucer是一个现代化的跨平台C WebView库,专为…

2026/7/12 19:59:39阅读更多 →
Nokhwa与WebAssembly:浏览器环境下的摄像头捕获终极指南

Nokhwa与WebAssembly:浏览器环境下的摄像头捕获终极指南

Nokhwa与WebAssembly:浏览器环境下的摄像头捕获终极指南 【免费下载链接】nokhwa Cross Platform Rust Library for Powerful Webcam/Camera Capture 项目地址: https://gitcode.com/gh_mirrors/no/nokhwa 在当今Web应用开发中,浏览器端的摄像头访…

2026/7/12 19:54:39阅读更多 →
密评整改倒计时 15 天:达梦 DMJOB 日志“裸奔”惹大祸,我用 Java 旁路加密+盲索引,硬刚 5 个生死坑!

密评整改倒计时 15 天:达梦 DMJOB 日志“裸奔”惹大祸,我用 Java 旁路加密+盲索引,硬刚 5 个生死坑!

🔥关注墨瑾轩,带你探索编程的奥秘!🚀 🔥超萌技术攻略,轻松晋级编程高手🚀 🔥技术宝库已备好,就等你来挖掘🚀 🔥订阅墨瑾轩,智趣学习不…

2026/7/12 19:54:39阅读更多 →
PUBG地图黑客编译与构建完整流程:终极指南

PUBG地图黑客编译与构建完整流程:终极指南

PUBG地图黑客编译与构建完整流程:终极指南 【免费下载链接】PUBG-map-hack Map hack solution for PUBG 项目地址: https://gitcode.com/gh_mirrors/pu/PUBG-map-hack 想要在PUBG游戏中获得地图优势吗?这篇完整教程将带你了解PUBG地图黑客的编译与…

2026/7/12 21:09:44阅读更多 →
艾尔登法环存档编辑器的完整指南:从新手到精通

艾尔登法环存档编辑器的完整指南:从新手到精通

艾尔登法环存档编辑器的完整指南:从新手到精通 【免费下载链接】ER-Save-Editor Elden Ring Save Editor. Compatible with PC and Playstation saves. 项目地址: https://gitcode.com/GitHub_Trending/er/ER-Save-Editor 你是否曾在艾尔登法环的世界中渴望调…

2026/7/12 21:09:44阅读更多 →
font-spider-plus常见问题解决:GBK编码、动态渲染页面等难题应对终极指南

font-spider-plus常见问题解决:GBK编码、动态渲染页面等难题应对终极指南

font-spider-plus常见问题解决:GBK编码、动态渲染页面等难题应对终极指南 【免费下载链接】font-spider-plus font-spider-plus(字蛛)是一个智能 WebFont 压缩工具,它能自动分析出本地页面和线上页面使用的 WebFont 并进行按需压缩…

2026/7/12 21:09:44阅读更多 →
OpenIO SDS多租户管理:如何构建企业级存储服务平台

OpenIO SDS多租户管理:如何构建企业级存储服务平台

OpenIO SDS多租户管理:如何构建企业级存储服务平台 【免费下载链接】oio-sds High Performance Software-Defined Object Storage for Big Data and AI, that supports Amazon S3 and Openstack Swift 项目地址: https://gitcode.com/gh_mirrors/oi/oio-sds …

2026/7/12 21:09:44阅读更多 →
如何在C项目中集成SipHash:开发者实战教程

如何在C项目中集成SipHash:开发者实战教程

如何在C项目中集成SipHash:开发者实战教程 【免费下载链接】SipHash High-speed secure pseudorandom function for short messages 项目地址: https://gitcode.com/gh_mirrors/siph/SipHash SipHash是一种为短消息优化的高速安全伪随机函数(PRF…

2026/7/12 21:09:44阅读更多 →
VMwareHardenedLoader:深度解析虚拟机反检测技术的实现原理与实践应用

VMwareHardenedLoader:深度解析虚拟机反检测技术的实现原理与实践应用

VMwareHardenedLoader:深度解析虚拟机反检测技术的实现原理与实践应用 【免费下载链接】VmwareHardenedLoader Vmware Hardened VM detection mitigation loader (anti anti-vm) 项目地址: https://gitcode.com/gh_mirrors/vm/VmwareHardenedLoader 在当今的…

2026/7/12 21:04:44阅读更多 →
VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异当你在VSCode中启动一个新的TypeScript项目时,第一个技术决策往往从安装方式开始。这个看似简单的选择——全局安装还是项目本地安装——实际上会深刻影响你的开发流程、团队协作和…

2026/7/12 0:02:11阅读更多 →
智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手 【免费下载链接】zhihuishu 智慧树刷课插件,自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 智慧树刷课插件是一款专为智慧树在线教育平台设计的Chrome浏…

2026/7/12 0:02:11阅读更多 →
Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 你是否在GOG或Epic Games Store购买了心仪的游戏…

2026/7/12 0:02:11阅读更多 →
VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异当你在VSCode中启动一个新的TypeScript项目时,第一个技术决策往往从安装方式开始。这个看似简单的选择——全局安装还是项目本地安装——实际上会深刻影响你的开发流程、团队协作和…

2026/7/12 0:02:11阅读更多 →
智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手 【免费下载链接】zhihuishu 智慧树刷课插件,自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 智慧树刷课插件是一款专为智慧树在线教育平台设计的Chrome浏…

2026/7/12 0:02:11阅读更多 →
Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 你是否在GOG或Epic Games Store购买了心仪的游戏…

2026/7/12 0:02:11阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/11 16:20:28阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/11 23:15:38阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/11 18:12:23阅读更多 →