C++学习笔记-函数模版与类模版

模板是C++语言中的一个强大特性,它允许程序员编写通用代码以处理不同数据类型的数据,从而实现代码的重用和泛化。

一、C++模板的基本概念

C++模板是一种泛型编程工具,通过参数化类型来编写通用的函数和类。模板的核心思想是允许程序员编写一次代码,然后通过将不同的数据类型作为参数来创建多个具体的实例。这种机制大大提高了代码的重用性和泛化程度。

1. 模板的分类

C++模板主要分为两种:函数模板和类模板。

函数模板:允许编写一般性的函数,其中某些参数的类型被视为模板参数,可以在函数调用时指定。例如,可以编写通用的排序函数,不必为每种数据类型都编写不同的排序算法。
类模板:允许创建通用的类,其中一些成员或成员函数的类型被视为模板参数。这使得可以创建通用的容器类(如向量、链表等)或数据结构。

2. 模板参数

模板参数可以是类型参数或非类型参数。

类型参数:允许指定不同的数据类型,这是最常见的模板参数类型。
非类型参数:允许指定常量或值,以定制化模板的行为。非类型参数可以是整数、枚举、指针等。
二、C++模板的使用

  1. 函数模板
    函数模板允许编写与数据类型无关的函数。其基本语法如下:
template<typename T>  
T functionName(T param1, T param2) {  // 函数实现  
}

例如,编写一个通用的交换函数模板:

template<typename T>  
void swap(T& a, T& b) {  T temp = a;  a = b;  b = temp;  
}

在使用时,编译器会根据传递的参数类型自动推导T的类型。

#include <iostream>  template<typename T>  
T max(T a, T b) {  return (a > b) ? a : b;  
}  int main() {  std::cout << max(5, 3) << std::endl;  // 调用 int 版本的 max  std::cout << max(5.5, 3.3) << std::endl; // 调用 double 版本的 max  return 0;  
}

2. 类模板

类模板允许创建与数据类型无关的类。其基本语法如下:

template<typename T>  
class ClassName {  // 类成员  
};

例如,创建一个通用的盒子类模板:

template<typename T>  
class Box {  
private:  T value;  
public:  Box(T v) : value(v) {}  T getValue() {  return value;  }  
};

在主程序中:

int main() {  Box<int> intBox(10);  std::cout << intBox.getValue() << std::endl; // 输出 10  Box<std::string> stringBox("Hello");  std::cout << stringBox.getValue() << std::endl; // 输出 Hello  return 0;  
}

程序分别输出数值10和字符串“Hello”。

3. 模板特化

模板特化是指为特定类型提供专门化的实现。当需要对某个特定类型进行特殊处理时,可以使用模板特化。

template<typename T>  
class Box {  // 通用实现  
};  // 为 char* 类型提供特化  
template<>  
class Box<char*> {  
private:  char* value;  
public:  Box(char* v) : value(v) {}  const char* getValue() {  return value;  }  
};

4. 模板参数默认值

从C++11开始,模板参数可以有默认值,当不指定模板参数时,会使用默认值,这使得模板的使用更加灵活。

template<typename T = int>  
class DefaultBox {  
private:  T value;  
public:  DefaultBox(T val = 0) : value(val) {}  T getValue() const {  return value;  }  
};  int main() {  DefaultBox<> intBox; // 使用默认的 int 类型  std::cout << intBox.getValue() << std::endl; // 输出 0  DefaultBox<double> doubleBox(3.14);  std::cout << doubleBox.getValue() << std::endl; // 输出 3.14  return 0;  
}

示例中,定义时不指定模板类型的情况下,将默认类型为int。

4.模板与泛型编程的关系

泛型编程的概念:泛型编程强调编写可重用、与类型无关的代码。它旨在减少代码重复,提高代码复用性和可维护性。泛型编程通常依赖于某种形式的参数化类型或函数,这些参数在编译时或运行时被替换为具体的类型或值。而模板是泛型编程在C++中的一种具体实现。通过模板,C++程序员可以定义与类型无关的函数和类。模板参数可以是类型(类模板和函数模板中的类型参数),也可以是非类型(如整数或指针)。编译器在编译时根据提供的具体类型或值生成模板的实例。
优点
类型安全:模板在编译时根据提供的类型生成具体的代码,这意味着类型错误可以在编译时被捕获,而不是在运行时。这有助于编写更安全、更可靠的代码。
代码复用:通过使用模板,你可以编写与类型无关的代码,这些代码可以应用于多种数据类型。这避免了为每种数据类型编写单独函数的需要,从而减少了代码重复,提高了代码复用性。
性能优化:由于模板在编译时生成具体的代码,因此它们通常与手动编写的针对特定类型的代码具有相同的性能。这消除了使用泛型编程时常见的性能开销。
泛型编程:模板支持泛型编程,允许你编写独立于任何特定数据类型的算法和数据结构。这使得C++代码更加灵活和可重用。
表达力强:模板提供了强大的表达力,允许你编写高度抽象和通用的代码。这有助于创建复杂的算法和数据结构,同时保持代码的清晰和可维护性。

5.模板优缺点

缺点
  • 编译时间增加:由于模板在编译时生成具体的代码,因此当模板被大量使用时,编译时间可能会显著增加。这可能会影响开发过程的效率。
  • 代码膨胀:对于每种使用的类型,模板都会生成相应的代码。这可能导致生成的二进制文件大小显著增加,特别是当模板被广泛使用时。
    复杂性:模板的语法和规则相对复杂,可能需要一定的时间来学习和掌握。此外,模板错误消息通常非常冗长和难以理解,这可能会增加调试和修复错误的难度。
  • 模板元编程的复杂性:虽然模板元编程(TMP)提供了极高的灵活性和表达力,但它也引入了额外的复杂性。TMP涉及在编译时执行计算和操作,这可能需要深入理解模板的工作原理和C++编译器的行为。
  • 模板实例化限制:在某些情况下,模板的实例化可能会受到C++编译器的限制。例如,某些编译器可能对模板实例化的深度或递归次数有限制。这可能会限制模板的使用范围或要求开发者采取额外的措施来绕过这些限制。
  • 可读性和可维护性:虽然模板可以提高代码复用性和性能,但它们也可能降低代码的可读性和可维护性。特别是当模板代码变得复杂时,其他开发者可能难以理解其工作原理和用途。
优点
  • 类型安全:模板在编译时根据提供的类型生成具体的代码,这意味着类型错误可以在编译时被捕获,而不是在运行时。这有助于编写更安全、更可靠的代码。
  • 代码复用:通过使用模板,你可以编写与类型无关的代码,这些代码可以应用于多种数据类型。这避免了为每种数据类型编写单独函数的需要,从而减少了代码重复,提高了代码复用性。
  • 性能优化:由于模板在编译时生成具体的代码,因此它们通常与手动编写的针对特定类型的代码具有相同的性能。这消除了使用泛型编程时常见的性能开销。
  • 表达力强:模板提供了强大的表达力,允许你编写高度抽象和通用的代码。这有助于创建复杂的算法和数据结构,同时保持代码的清晰和可维护性。

三、C++模板的高级特性

1. 模板元编程

模板元编程是利用模板在编译时执行计算和操作类型的技术。它允许在编译时生成和执行代码,从而提高程序的性能和灵活性。

2. 变量模板(C++14)

变量模板允许定义模板化的变量。这在定义常量值时非常有用,尤其是当这些常量值依赖于类型时。

template<typename T>  
constexpr T pi = T(3.1415926535897932385);

3. C++11及以后的新特性

随着C++标准的发展,模板也引入了许多新特性,如类型推导(auto和decltype)、Lambda表达式、基于范围的for循环等,这些特性进一步增强了模板的灵活性和易用性。

四、总结

C++模板是C++语言中的一个重要特性,它使得代码能够重用和泛化,提高了编程的效率和代码质量。无论是函数模板还是类模板,都是编写高效、通用代码的重要工具。通过理解和掌握模板的使用,可以大大提高C++编程的灵活性和效率。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring验证码

前言&#xff1a;使用Hutool 1.什么是Hutool&#xff1f; 2.代码复制到test类中 3.代码爆红&#xff0c;说明需要引入依赖 4.根据名取Maven仓库相关依赖 5.在pom.xml文件中进行配置 6.引入成功 7. 运行程序 打开d盘&#xff0c;发现已经生成了验证码的图片&#xff0c;路径在…

Codeforces Round 654 (Div. 2) C. A Cookie for You (模拟)

我认为这道题就是个脑筋急转弯。 首先我们知道当a b < n m的时候&#xff0c;饼干总数都不够人的总数&#xff0c;那肯定是NO。 并且注意题干&#xff0c;我们可以得知当a b的时候&#xff0c;第一类和第二类人可以任意选两种饼干中的一种。 之后我们可以分类讨论一下。 …

网格布局 HTML CSS grid layout demo

文章目录 页面效果代码 (HTML CSS)参考 页面效果 代码 (HTML CSS) <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"…

[ BLE4.0 ] 伦茨ST17H66开发-串口UART0的接收与发送

目录 一、前言 二、实现步骤 1.设置回调函数 2.关闭睡眠模式 三、效果展示 四、工程源代码 一、前言 串口通信在任何一款单片机开发中都是尤为重要的。本文涉及的开发所使用的例程依然是基于[ BLE4.0 ] 伦茨ST17H66开发-OSAL系统中添加自己的Task任务文章的工程源码&#x…

windows@powershell@任务计划@自动任务计划@taskschd.msc.md

文章目录 使用任务计划windows中的任务计划任务计划命令行程序开发windows 应用中相关api传统图形界面FAQ schtasks 命令常见用法创建计划任务删除计划任务查询计划任务修改计划任务运行计划任务 PowerShell ScheduledTasks常用 cmdlet 简介1. Get-ScheduledTask2. Register-Sc…

Git远程仓库推送

这里我只连接了两个站点的远程仓库&#xff0c;一个是国内的Gitee&#xff0c;另一个是Github&#xff0c;这两个站点的连接方式主要有两种&#xff0c;第一种就是通过https来连接远程仓库&#xff0c;另一种是通过ssh公钥来连接&#xff0c;这两个站点练接的大致过程都是一样的…

我出一道面试题,看看你能拿 3k 还是 30k!

大家好&#xff0c;我是程序员鱼皮。欢迎屏幕前的各位来到今天的模拟面试现场&#xff0c;接下来我会出一道经典的后端面试题&#xff0c;你只需要进行 4 个简单的选择&#xff0c;就能判断出来你的水平是新手&#xff08;3k&#xff09;、初级&#xff08;10k&#xff09;、中…

4 款最佳 C# 无头浏览器

摘要&#xff1a; 在当今大数据时代&#xff0c;高效的数据采集成为众多项目的关键一环。对于偏好C#语言的开发者而言&#xff0c;无头浏览器是实现网页自动化交互、数据抓取的强大工具。本文将深入探讨四款顶尖的C#无头浏览器库&#xff0c;分析它们的特性和应用场景&#xf…

怎么把C盘分成两个盘?让C盘分区更简单,赶快试试!

在日常使用电脑的过程中&#xff0c;有时我们可能希望将C盘分割成两个独立的分区&#xff0c;以便更好地管理文件和数据。这种操作需要谨慎进行&#xff0c;因为错误的分区操作可能导致数据丢失。那么&#xff0c;我们该怎么把C盘分成两个盘呢&#xff1f;下面&#xff0c;我将…

lua 游戏架构 之 游戏 AI (六)ai_auto_skill

定义一个为ai_auto_skill的类&#xff0c;继承自ai_base类。ai_auto_skill类的目的是在AI自动战斗模式下&#xff0c;根据配置和条件自动选择并使用技能。 lua 游戏架构 之 游戏 AI &#xff08;一&#xff09;ai_base-CSDN博客文章浏览阅读379次。定义了一套接口和属性&#…

vue3在元素上绑定自定义事件弹出虚拟键盘

最近开发中遇到一个需求: 焊接机器人的屏幕上集成web前端网页, 但是没有接入键盘。这就需要web端开发一个虚拟键盘,在网上找个很多虚拟键盘没有特别适合,索性自己写个简单的 图片: 代码: (代码可能比较垃圾冗余,也没时间优化,凑合看吧) 第一步:创建键盘组件 为了方便使用…

3.2.微调

微调 ​ 对于一些样本数量有限的数据集&#xff0c;如果使用较大的模型&#xff0c;可能很快过拟合&#xff0c;较小的模型可能效果不好。这个问题的一个解决方案是收集更多数据&#xff0c;但其实在很多情况下这是很难做到的。 ​ 另一种方法就是迁移学习(transfer learning…

c++如何理解多态与虚函数

目录 **前言****1. 何为多态**1.1 **编译时多态**1.1.1 函数重载1.1.2 模板 **1.2 运行时多态****1.2.1 虚函数****1.2.2 为什么要用父类指针去调用子类函数** **2. 注意****2.1 基类的析构函数应写为虚函数****2.2 构造函数不能设为虚函数** **本文参考** 前言 在学习 c 的虚…

打造重庆市数字化教育“新名片”,广阳湾珊瑚中学凭实力“出圈”!

分布于教学楼连廊顶部的智能照明设备,根据不同的时间和场景需求自动调节灯光亮度和开关状态;安装于各个教室内的智能黑板、学校同步时钟、学生互动设备,在极简以太全光网的赋能下,为师生提供丰富的教学体验与学习支持......行走于重庆市广阳湾珊瑚中学,像是与充满科技感的“校园…

病理AI领域的基础模型汇总|顶刊专题汇总·24-07-26

小罗碎碎念 本期文献主题&#xff1a;病理AI领域的最新基础模型 今天的推文是一期生日特辑&#xff0c;定时在下午六点二十一分发表&#xff08;今天农历六月二十一&#xff0c;哈哈&#xff09;&#xff0c;算是自己给自己的24岁生日礼物&#xff0c;希望24岁这一年&#xff0…

ollama本地部署大语言模型记录

目录 安装Ollama更改模型存放位置 拉取模型GemmaMistralQwen1.5(通义千问)codellama 部署Open webui测试性能知识广度问题1问题2 代码能力总结 最近突然对大语言模型感兴趣 同时在平时的一些线下断网的CTF比赛中&#xff0c;大语言模型也可以作为一个能对话交互的高级知识检索…

SSRF中伪协议学习

SSRF常用的伪协议 file:// 从文件系统中获取文件内容,如file:///etc/passwd dict:// 字典服务协议,访问字典资源,如 dict:///ip:6739/info: ftp:// 可用于网络端口扫描 sftp:// SSH文件传输协议或安全文件传输协议 ldap://轻量级目录访问协议 tftp:// 简单文件传输协议 gopher…

【JavaScript】函数声明和函数表达式的区别

文章目录 一、函数声明1. 定义方式2. 作用域提升&#xff08;Hoisting&#xff09;3. 块级作用域 二、函数表达式1. 定义方式2. 作用域提升&#xff08;Hoisting&#xff09;3. 自引用 三、其他区别1. 函数名2. 可读性和代码组织3. 使用场景 四、总结函数声明函数表达式 在Java…

【大模型系列】Video-LaVIT(2024.06)

Paper&#xff1a;https://arxiv.org/abs/2402.03161Github&#xff1a;https://video-lavit.github.io/Title&#xff1a;Video-LaVIT: Unified Video-Language Pre-training with Decoupled Visual-Motional TokenizationAuthor&#xff1a;Yang Jin&#xff0c; 北大&#x…

Java面试八股之@Qualifier的作用

Qualifier的作用 Qualifier 是 Spring 框架中的一个非常有用的注解&#xff0c;它主要用于解决在依赖注入过程中出现的歧义问题。当 Spring 容器中有多个相同类型的 Bean 时&#xff0c;Qualifier 可以帮助指明应该使用哪一个具体的 Bean 进行注入。 Qualifier 的作用&#x…