C模板编程基础泛型编程入门与实践在 C 中模板Template 是实现泛型编程的重要工具。它可以让我们写出 与类型无关的代码从而减少重复代码提高程序的复用性。本文将从基础概念开始逐步介绍模板的基本思想函数模板类模板模板特化与偏特化模板编译机制实际案例模板链表模板与 STL 的关系适合 C初学者或正在学习STL的同学。一、学习目标学习完这部分内容你应该能够理解什么是 泛型编程掌握 函数模板和类模板 的基本语法学会 模板实例化理解 模板特化与偏特化解决模板使用中的常见问题理解模板与 STL标准库 的关系重点内容包括模板语法规则类型参数与非类型参数模板特化的应用泛型编程思想二、什么是泛型编程2.1 泛型编程的概念泛型编程Generic Programming指的是编写与具体数据类型无关的代码在使用时再指定具体类型。简单理解就是写一次代码可以适用于多种数据类型。例如一个加法函数不应该只支持 int还应该支持doublefloatstring甚至自定义类型2.2 为什么需要模板如果不用模板代码会变成这样int add_int(int a, int b){return a b;}double add_double(double a, double b){return a b;}float add_float(float a, float b){return a b;}问题代码重复难维护扩展困难使用模板后只需要一份代码。2.3 模板的分类C 模板主要分两种1 函数模板用于编写 通用函数例如通用加法通用比较通用排序2 类模板用于创建 通用类例如容器类数据结构算法类STL 中的很多组件都是类模板例如vectorlistmap三、函数模板3.1 基本语法函数模板的写法template typename T返回值类型 函数名(参数列表){函数体}说明template 表示模板声明typename T 表示类型参数T 是一个 类型占位符typename 也可以写成 class。3.2 示例通用加法函数#include iostreamusing namespace std;template typename TT add(T a, T b){return a b;}int main(){int a addint(10,20);double b adddouble(3.1,2.5);coutaendl;coutbendl;}运行结果305.63.3 类型自动推导模板参数也可以 不写类型编译器自动推导。add(5,6);add(3.14,2.86);编译器会自动判断T intT double注意如果参数类型不同add(10,3.14);编译会报错。解决方法adddouble(10,3.14);四、函数模板重载模板函数可以和普通函数一起使用。调用规则1 普通函数优先2 特化模板优先3 最匹配的模板优先示例int add(int a,int b){return ab;}templatetypename TT add(T a,T b){return ab;}当调用add(10,20);优先使用普通函数。五、模板特化有时候通用模板不能满足需求。例如字符串拼接时需要特殊处理。这时可以使用 模板特化。示例通用模板templatetypename TT add(T a,T b){return ab;}string特化templatestring addstring(string a,string b){return a b;}这样add(Hello,World)结果Hello World六、类模板类模板可以创建 通用类结构。6.1 基本语法templatetypename Tclass 类名{public:T data;T get(){return data;}};6.2 示例简单容器templatetypename Tclass Container{private:T data;public:Container(T value){datavalue;}T get(){return data;}};使用Containerint c1(100);Containerdouble c2(3.14);不同类型会生成不同对象。七、模板参数类型模板参数分两种类型参数typename T非类型参数表示 常量参数例如templatetypename T,int Nclass Array{T data[N];};使用Arrayint,10 arr;说明数组大小是 编译期确定的。八、模板特化与偏特化8.1 全特化为某个具体类型提供专门实现。例如templateclass Printerstring{public:void print(string s){cout字符串:sendl;}};8.2 偏特化只固定 部分模板参数。例如templatetypename Tclass PairT,int{};表示第二个参数固定为 int。九、模板编译机制C 模板采用实例化时编译意思是只有当模板被使用时编译器才会生成代码。例如addint()adddouble()编译器会生成两个函数add_intadd_double常见错误1 类型推导失败例如add(10,3.14)解决adddouble(10,3.14)2 运算符不支持如果模板使用 运算符自定义类必须实现operator3 非类型参数必须是常量错误int n5;Arrayint,n arr;正确const int n5;Arrayint,n arr;十、模板实战通用链表利用模板可以实现 支持任意类型的链表。核心思路1 定义节点模板2 定义链表模板3 实现基本操作例如push_backpush_frontinsertremovegetprint这样一个链表可以支持LinkedListintLinkedListstringLinkedListdouble代码复用率非常高。十一、模板与STLSTL标准模板库就是 模板编程的典型应用。STL主要包含容器vectorlistmap算法sortfindreverse迭代器连接容器和算法。示例vectorint nums{5,2,9,1};sort(nums.begin(),nums.end());排序结果1 2 5 9十二、总结模板是 C 中非常重要的技术它是 泛型编程的核心工具。关键知识点1 模板分为函数模板类模板2 模板可以实现代码复用类型安全3 模板支持重载特化偏特化4 STL 的底层实现几乎全部依赖模板。掌握模板编程后你将更容易理解STL源码泛型算法高级C设计如果你愿意我还可以帮你把这篇文章 升级成更高级的 CSDN 爆款技术博客版本包括图解模板机制更简单的模板理解模型STL源码级理解面试常问模板题这样会 比原文章质量高很多。好的下面我给你做一个 升级版技术博客结构CSDN / 掘金 / 知乎都适合发。特点是结构更清晰更偏工程理解面试友好阅读体验更好更像高质量技术博客而不是笔记你可以直接发布。C模板编程入门从泛型思想到STL底层实现超详细在学习 C 的过程中模板Template 是一个非常重要的知识点。很多人第一次接触模板时都会觉得语法复杂、报错难看懂、代码很抽象。但实际上模板背后的思想并不复杂。如果你想真正理解为什么 STL 能支持各种类型为什么 vectorint 和 vectorstring 都能用为什么 sort() 能排序任何数据类型那么你必须掌握 C模板编程Template Programming。这篇文章将系统讲清什么是泛型编程函数模板类模板模板特化偏特化模板编译机制模板与 STL 的关系读完之后你基本就能理解 STL 的设计思想。一、什么是泛型编程1.1 泛型编程的核心思想泛型编程Generic Programming的核心理念是写一次代码让它适用于多种数据类型。换句话说代码 不依赖具体类型。举个简单例子。我们想写一个加法函数int add(int a,int b){return ab;}如果支持 doubledouble add(double a,double b){return ab;}如果支持 floatfloat add(float a,float b){return ab;}你会发现代码逻辑完全一样。这就是 代码重复问题。1.2 模板的作用模板就是解决这个问题的。使用模板后templatetypename TT add(T a,T b){return ab;}现在这个函数可以支持intdoublefloatstring甚至自定义类型这就是 泛型编程的核心价值提高代码复用减少重复代码保证类型安全二、C模板的分类C 模板主要分为两类1 函数模板用于创建 通用函数例如add()max()swap()2 类模板用于创建 通用类例如vectorTlistTmapK,VSTL 中几乎所有容器都是 类模板。三、函数模板3.1 基本语法函数模板的基本结构templatetypename TT functionName(T param1,T param2){//函数逻辑}说明template 模板声明typename T 类型参数T 类型占位符typename 也可以写成 class。3.2 示例通用加法函数#includeiostreamusing namespace std;templatetypename TT add(T a,T b){return ab;}int main(){coutaddint(10,20)endl;coutadddouble(3.14,2.86)endl;}输出3063.3 自动类型推导模板参数可以自动推导add(10,20);add(3.14,2.86);编译器会自动判断TintTdouble注意如果参数类型不同add(10,3.14);会报错。解决方法adddouble(10,3.14);四、函数模板重载模板函数可以和普通函数一起使用。例如int add(int a,int b){return ab;}templatetypename TT add(T a,T b){return ab;}调用add(10,20);会优先调用 普通函数。原因编译器优先选择最精确匹配。五、模板特化有时候通用模板不能满足需求。例如字符串拼接。普通模板templatetypename TT add(T a,T b){return ab;}如果是 string我们希望Hello World而不是HelloWorld可以使用 模板特化templatestring addstring(string a,string b){return a b;}这样add(Hello,World)输出Hello World六、类模板类模板用于创建 通用类结构。6.1 基本语法templatetypename Tclass Container{private:T data;public:Container(T value){datavalue;}T get(){return data;}};6.2 使用类模板Containerint a(10);Containerdouble b(3.14);Containerstring c(Hello);编译器会自动生成Container_intContainer_doubleContainer_string七、模板参数类型模板参数有两种。7.1 类型参数templatetypename T表示任意类型。7.2 非类型参数表示 常量参数。例如templatetypename T,int Nclass Array{T data[N];};使用Arrayint,10 arr;这里10就是模板参数。八、模板特化与偏特化8.1 全特化完全指定模板参数。例如templateclass Printerstring{};8.2 偏特化只指定部分参数。例如templatetypename Tclass PairT,int{};意思是第二个参数必须是 int九、模板编译机制C 模板采用按需实例化Lazy Instantiation意思是模板只有在 被使用时 才会生成代码。例如addint()adddouble()编译器会生成add_intadd_double常见错误1 类型推导失败add(10,3.14);解决adddouble(10,3.14);2 运算符不支持如果模板内部使用自定义类必须实现operator3 非类型参数必须是常量错误int n5;Arrayint,n正确const int n5;十、模板实战通用链表利用模板可以实现 通用链表。例如LinkedListintLinkedListdoubleLinkedListstring支持push_backpush_frontinsertremovegetprint编程语言cmodou99.comc语言的魅力编程语言cwww.modou99.comc语言的魅力编程语言cm.modou99.comc语言的魅力编程语言cjyhedl.comc语言的魅力编程语言cwww.jyhedl.comc语言的魅力编程语言cm.jyhedl.comc语言的魅力编程语言cnetshop168.comc语言的魅力编程语言cwww.netshop168.comc语言的魅力编程语言cm.netshop168.comc语言的魅力编程语言cmodou99.comc语言的魅力编程语言cwww.modou99.comc语言的魅力编程语言cm.modou99.comc语言的魅力编程语言cjyhedl.comc语言的魅力编程语言cwww.jyhedl.comc语言的魅力编程语言cm.jyhedl.comc语言的魅力编程语言cnetshop168.comc语言的魅力编程语言cwww.netshop168.comc语言的魅力编程语言cm.netshop168.comc语言的魅力编程语言cmodou99.comc语言的魅力编程语言cwww.modou99.comc语言的魅力编程语言cm.modou99.comc语言的魅力编程语言cjyhedl.comc语言的魅力编程语言cwww.jyhedl.comc语言的魅力编程语言cm.jyhedl.comc语言的魅力编程语言cnetshop168.comc语言的魅力编程语言cwww.netshop168.comc语言的魅力编程语言cm.netshop168.comc语言的魅力模板链表的优点支持任意数据类型代码复用率高结构清晰这也是 STL 容器的设计思想。十一、模板与STL的关系STLStandard Template Library完全建立在模板之上。STL主要包括三部分容器vectorlistmapset算法sortfindreverse迭代器用于连接容器 算法例如vectorint nums{5,2,9,1};sort(nums.begin(),nums.end());输出1 2 5 9十二、总结模板是 C 中非常重要的语言特性。核心价值一次编写多次复用需要掌握的关键点1️⃣ 函数模板2️⃣ 类模板3️⃣ 模板实例化4️⃣ 模板特化5️⃣ 偏特化6️⃣ 模板编译机制同时模板也是理解 STL源码和高级C设计 的基础。如果想继续深入可以学习模板元编程SFINAEconcepttype traitsSTL源码