二手车网站开发多少钱网站建设的项目计划
- 作者: 五速梦信息网
- 时间: 2026年03月21日 11:18
当前位置: 首页 > news >正文
二手车网站开发多少钱,网站建设的项目计划,上海大企业公司排名,服务器域名是什么文章目录 C模板编程前言第一章: 初始模板与函数模版1.1 什么是泛型编程#xff1f;1.1.1 为什么要有泛型编程#xff1f;1.1.1 泛型编程的优势 1.2 函数模板的基础1.2.1 什么是函数模板#xff1f;1.2.2 函数模板的定义格式1.2.3 示例#xff1a;通用的交换函数输出示例模板编程前言第一章: 初始模板与函数模版1.1 什么是泛型编程1.1.1 为什么要有泛型编程1.1.1 泛型编程的优势 1.2 函数模板的基础1.2.1 什么是函数模板1.2.2 函数模板的定义格式1.2.3 示例通用的交换函数输出示例 1.2.4 模板中的typename与class 1.3 函数模板的原理1.3.1 函数模板的实例化1.3.2 隐式实例化与显式实例化 第二章: 类模板2.1 类模板概念 2.1.1 类模板的定义格式 2.1.2 示例简单的类模板输出示例 2.2 类模板的实例化2.3 类模板中的成员函数定义 2.4 为什么不建议类模板的定义和声明分离2.4.1 模板的编译时行为2.4.2 链接器无法找到定义2.4.3 无法预编译模板2.4.4 解决方案将声明和定义放在同一个头文件中 第三章: 模板的匹配原则3.1 模板的匹配原则 写在最后 C模板编程 欢迎讨论如果你在学习过程中有任何问题或想法欢迎在评论区留言我们一起交流学习。你的支持是我继续创作的动力 点赞、收藏与分享觉得这篇文章对你有帮助吗别忘了点赞、收藏并分享给更多的小伙伴哦你们的支持是我不断进步的动力 分享给更多人如果你觉得这篇文章对你有帮助欢迎分享给更多对C感兴趣的朋友让我们一起进步 前言 C作为一门强大的编程语言以其丰富的功能和灵活的设计著称。模板编程是C中非常重要的一个特性通过模板可以实现泛型编程编写与数据类型无关的代码极大地提高了代码的复用性和可维护性。本文将从泛型编程、函数模板、类模板等几个方面详细讲解C模板的使用并结合实际的代码示例进行分析帮助大家全面掌握模板编程的知识。 本篇文章将包含以下几个部分 泛型编程的基本概念函数模板的定义与使用类模板的实现模板的匹配原则 通过阅读本文你将能够掌握C模板编程的基础知识理解其背后的工作原理并学会如何在实际项目中应用这些技术。 第一章: 初始模板与函数模版 1.1 什么是泛型编程 泛型编程Generic Programming是C中的一种编程范式旨在编写与数据类型无关的通用代码。这意味着你可以编写一次代码并通过不同的数据类型进行复用。C通过模板Template来实现泛型编程模板是泛型编程的核心工具。 1.1.1 为什么要有泛型编程 问题提出如何实现一个通用的交换函数呢 void Swap(int left, int right) {int temp left;left right;right temp; } void Swap(double left, double right) {double temp left;left right;right temp; } void Swap(char left, char right) {char temp left;left right;right temp; } //….等等使用函数重载虽然可以实现但是有一下几个不好的地方 重载的函数仅仅是类型不同代码复用率比较低只要有新类型出现时就需要用户自己增加对应的函数代码的可维护性比较低一个出错可能所有的重载均出错 那能否告诉编译器一个模子让编译器根据不同的类型利用该模子来生成代码呢 如果在C中也能够存在这样一个模具通过给这个模具中填充不同材料(类型)来获得不同 材料的铸件(即生成具体类型的代码那将会节省许多头发。巧的是前人早已将树栽好我们只需在此乘凉。这就是泛型编程 泛型编程编写与类型无关的通用代码是代码复用的一种手段。模板是泛型编程的基础。 1.1.1 泛型编程的优势 泛型编程的主要优势包括 代码复用性强通过模板你可以避免为每个数据类型单独编写相同功能的代码。提高代码的可维护性代码只需编写一次减少了冗余代码后续如果需要修改或修复只需在一处进行。减少编写错误重复编写代码时容易出错而模板可以让编译器自动生成所需代码减少人为失误。 1.2 函数模板的基础 1.2.1 什么是函数模板 函数模板Function Template是一个与类型无关的函数“蓝图”。通过模板参数编译器在编译期间会根据实际的数据类型生成相应的函数版本。 1.2.2 函数模板的定义格式 我们可以通过以下格式来定义一个函数模板 templatetypename T 返回类型 函数名(参数列表) {// 函数体 }template告诉编译器接下来的内容是模板。typename T定义一个模板参数T可以用来表示任何类型。返回类型和参数列表可以使用T作为数据类型。 注意typename是用来定义模板参数关键字也可以使用class(切记不能使用struct代替 class)下文会讲到 1.2.3 示例通用的交换函数 那我们就可以使用模板来编写交换函数它可以交换任意类型的数据 /*** brief 通用的交换函数* tparam T 通用的类型参数由编译器根据实参推断* param left 左侧变量* param right 右侧变量/ templatetypename T void Swap(T left, T right) {T temp left;left right;right temp; }int main() {int a 10, b 20;double x 1.1, y 2.2;char c1 A, c2 B;// 使用模板函数进行交换Swap(a, b); Swap(x, y); Swap(c1, c2); std::cout 交换后的整数: a b std::endl;std::cout 交换后的浮点数: x y std::endl;std::cout 交换后的字符: c1 c2 std::endl;return 0; }输出示例 交换后的整数: 20 10 交换后的浮点数: 2.2 1.1 交换后的字符: B A1.2.4 模板中的typename与class 在定义模板时typename和class是可以互换的。你可以选择以下两种方式 templatetypename T // 使用 typename templateclass T // 使用 class虽然两者功能相同但推荐使用typename因为它能够更好地表达该参数是一个类型参数避免与类的定义产生混淆。 1.3 函数模板的原理 函数模板的核心在于它不是一个真正的函数而是一个编译器用来生成特定类型函数的蓝图。编译器根据模板的使用情况推导出具体的类型并生成相应的代码。这一过程称为模板的实例化。 1.3.1 函数模板的实例化 当我们调用模板函数时编译器会根据实际的参数类型生成对应的函数版本。比如 templateclass T T Add(const T left, const T right) {return left right; }int main() {int a 10, b 20;double x 1.1, y 2.2;Add(a, b); // 生成 Addint 版本Add(x, y); // 生成 Adddouble 版本return 0; }在编译器编译阶段对于模板函数的使用编译器需要根据传入的实参类型来推演生成对应 类型的函数以供调用。比如当用double类型使用函数模板时编译器通过对实参类型的推演 将T确定为double类型然后产生一份专门处理double类型的代码对于字符类型也是如此。 1.3.2 隐式实例化与显式实例化 templateclass TT Add(const T left, const T right) {return left right; } int main() {int a1 10, a2 20;double d1 10.0, d2 20.0;Add(a1, a2);Add(d1, d2);Add(a1, d1);/ 该语句不能通过编译因为在编译期间当编译器看到该实例化时需要推演其实参类型 通过实参a1将T推演为int通过实参d1将T推演为double类型但模板参数列表中只有 一个T 编译器无法确定此处到底该将T确定为int 或者 double类型而报错 注意在模板中编译器一般不会进行类型转换操作因为一旦转化出问题编译器就需要 背黑锅/// 此时有两种处理方式1. 用户自己来强制转化 2. 使用显式实例化Add(a1, (int)d1);//自己强制转换return 0; }模板实例化分为两种 隐式实例化编译器根据实参推导出模板参数并自动生成函数。例如上面的Add函数就是隐式实例化。显式实例化如果想要强制指定模板参数可以使用显式实例化 就是第二种处理方式 int main(void) {int a 10;double b 20.0;// 显式实例化Addint(a, b);return 0; };第二章: 类模板 2.1 类模板概念 类模板Class Template是用于定义与类型无关的类它允许我们在类的定义中使用模板参数编译时再根据实际类型进行类的实例化。类模板与函数模板类似只不过它是用来生成类的。 2.1.1 类模板的定义格式 定义类模板的语法格式如下 templateclass T class 类名 {// 类的成员变量和方法 };templateclass T告诉编译器这是一个模板类T是一个类型参数。类的成员和方法可以使用T作为数据类型编译时由用户提供的类型来替代T。 2.1.2 示例简单的类模板 下面是一个简单的栈Stack类模板用于存储任意类型的数据 #includeiostreamusing namespace std;/** brief 栈的类模板* tparam T 通用的类型参数/ templateclass T class Stack { public:Stack(size_t capacity 4) {_array new T[capacity];_capacity capacity;_size 0;}~Stack() {delete[] _array;}/// brief 将元素压入栈中void Push(const T data) {if (_size _capacity) {Expand(); // 扩容}_array[_size] data;}/// brief 弹出栈顶元素void Pop() {if (_size 0) {–_size;}}/// brief 返回栈顶元素T Top() {if (_size 0) {return _array[_size - 1];}throw out_of_range(栈为空);}/// brief 检查栈是否为空bool IsEmpty() const {return _size 0;}/// brief 获取栈中元素的数量size_t Size() const {return _size;}private:T _array;size_t _capacity;size_t _size;/// brief 扩展栈的容量void Expand() {size_t newCapacity _capacity * 2;T* newArray new T[newCapacity];for (size_t i 0; i _size; i) {newArray[i] _array[i];}delete[] _array;_array newArray;_capacity newCapacity;} };int main() {Stackint st; // 创建存储整数的栈st.Push(10);st.Push(20);st.Push(30);cout 栈顶元素: st.Top() endl;st.Pop();cout 弹出后栈顶元素: st.Top() endl;return 0; }输出示例 栈顶元素: 30 弹出后栈顶元素: 20在这个类模板中T是一个通用类型参数。Stackint是Stack类模板的一个实例化表示它是一个存储int类型数据的栈。编译器会根据实际使用的类型自动生成相应的类。 2.2 类模板的实例化 与函数模板不同类模板在使用时必须显示地提供类型参数。实例化类模板时必须在类名后面的尖括号中指定实际的类型参数。例如 Stackint st1; // 实例化为处理 int 类型的栈 Stackdouble st2; // 实例化为处理 double 类型的栈这里的Stackint和Stackdouble分别表示不同的类型即不同的模板实例。编译器会根据模板参数生成相应的类代码。 2.3 类模板中的成员函数定义 对于类模板成员函数可以在类定义内或定义外实现。类模板的成员函数定义外置时需要在函数名之前加上模板声明和模板参数。例如 templateclass T void StackT::Push(const T data) {if (_size _capacity) {Expand(); // 扩容}_array[_size] data; }2.4 为什么不建议类模板的定义和声明分离 在C中类模板的实现与普通类有一个显著的区别模板是在编译时根据实际类型实例化的而不是像普通的类那样在编译期和链接期处理。这导致了一个很重要的问题如果将类模板的声明和定义分离到不同的文件中可能会导致链接错误。以下是详细原因 2.4.1 模板的编译时行为 类模板的本质是一个“蓝图”它并不是一个完整的类而是一个在需要时根据实际类型生成代码的模式。因此模板只有在实际使用实例化时编译器才会生成对应的类型的代码。编译器无法预先知道你会使用哪些类型来实例化模板因此它不会为模板生成实际的代码。 2.4.2 链接器无法找到定义 当你将类模板的声明放在头文件中而把定义放在.cpp文件中时模板实例化的过程可能发生在不同的编译单元中。因为模板只有在编译期被实例化链接器在链接时无法看到模板的定义除非在编译时所有模板的实例化代码都可见。如果定义在.cpp文件中其他使用模板的编译单元无法找到这个定义导致链接器报错。 2.4.3 无法预编译模板 与普通类不同类模板无法被预编译或只在一个编译单元中定义然后供其他单元使用。普通的类在编译过程中编译器会生成目标代码并储存在.obj文件中链接时其他编译单元可以引用这些已生成的代码。而类模板无法这样做因为它需要知道使用时的类型才能生成实际的代码。 2.4.4 解决方案将声明和定义放在同一个头文件中 为了避免上述问题C的惯用方法是将类模板的声明和定义都放在同一个头文件中。这使得每个使用模板的编译单元在实例化模板时编译器能够访问到模板的定义并根据需要生成实际的代码。这种方式确保了编译器能够在编译期处理模板的实例化而不会在链接时出现找不到定义的问题。 错误用法 // Stack.h templatetypename T class Stack { public:void Push(const T value);// 声明在头文件中 };// Stack.cpp templatetypename T void StackT::Push(const T value) {// 定义在.cpp文件中 }在这种情况下如果不同编译单元使用了Stackint或Stackdouble链接器可能会报错因为它无法找到模板的定义。 正确用法 // Stack.h templatetypename T class Stack { public:void Push(const T value); };templatetypename T void StackT::Push(const T value) {// 声明和定义都在头文件中 }这种方法确保每个编译单元都能访问到模板的完整定义避免链接时的错误。 总结 类模板的代码只有在实例化时才生成因此类模板的定义必须在每个使用它的编译单元中可见。将模板的声明和定义放在同一个头文件中可以确保模板实例化时能够访问到其定义避免链接错误。这也是为什么大多数C开发者在编写模板时会将模板的实现放在头文件中的原因。 注意 函数模板与类模板不同当代大多数编译器支持函数模板的声明和定义分离这是因为函数模板的实例化往往只涉及函数的具体调用不像类模板这么复杂具体之后的博客会更详细的讲解此处的内容敬请期待哦 第三章: 模板的匹配原则 3.1 模板的匹配原则 C编译器在调用模板时会根据实参类型和函数参数类型进行匹配。模板的匹配规则如下 优先调用非模板函数如果存在一个与实参完全匹配的非模板函数编译器将优先调用非模板函数而不是通过模板生成一个实例。 例如 int Add(int a, int b) {return a b; }templatetypename T T Add(T a, T b) {return a b; }int main() {int a 10, b 20;cout Add(a, b) endl; // 调用非模板版本 }如果非模板函数没有匹配则调用模板实例如果模板函数比非模板函数更能匹配参数类型编译器将生成模板实例。 例如 double Add(double a, double b) {return a b; }templatetypename T T Add(T a, T b) {return a b; }int main() {int a 10, b 20;double x 1.1, y 2.2;cout Add(a, b) endl; // 调用模板实例 Addintcout Add(x, y) endl; // 调用非模板版本 Add(double, double) }写在最后 本文基础的讲解了C模板编程的基础知识涵盖了泛型编程、函数模板、类模板、模板匹配原则等概念。通过这些模板功能C开发者可以编写更加灵活和可复用的代码大幅提高编程效率。 模板编程虽然强大但使用时也需要谨慎尤其是在处理模板特化和匹配规则时。如果能够合理地使用模板技术相信你的代码质量将会有显著提升。 以上就是关于【C篇】引领C模板初体验泛型编程的力量与妙用的内容啦在之后会有另一篇博客来讲解有关模板的更多进阶内容敬请期待哦然后各位大佬有什么问题欢迎在评论区指正或者私信我也是可以的啦您的支持是我创作的最大动力❤️
- 上一篇: 二手车网站策划wordpress 虚拟数据
- 下一篇: 二手车为什么做网站网站开发有什么点子
相关文章
-
二手车网站策划wordpress 虚拟数据
二手车网站策划wordpress 虚拟数据
- 技术栈
- 2026年03月21日
-
二手车的网站建设例子小程序定制公司排行榜
二手车的网站建设例子小程序定制公司排行榜
- 技术栈
- 2026年03月21日
-
二级院系网站建设网站开发 强制兼容模式
二级院系网站建设网站开发 强制兼容模式
- 技术栈
- 2026年03月21日
-
二手车为什么做网站网站开发有什么点子
二手车为什么做网站网站开发有什么点子
- 技术栈
- 2026年03月21日
-
二手房网签合同在哪个网站做微信高端网站建设
二手房网签合同在哪个网站做微信高端网站建设
- 技术栈
- 2026年03月21日
-
二手房网站建设书长安公司网站设计
二手房网站建设书长安公司网站设计
- 技术栈
- 2026年03月21日






