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.mzph.cn/bicheng/50519.shtml

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

相关文章

文件共享功能无法使用提示错误代码0x80004005【笔记】

环境情况&#xff1a; 其他电脑可以正常访问共享端&#xff0c;但有一台电脑访问提示错误代码0x80004005。 处理检查&#xff1a; 搜索里输入“启用或关闭Windows功能”按回车键&#xff0c;在“启用或关闭Windows功能”里将“SMB 1.0/CIFS文件共享支持”勾选后&#xff08;故…

uniapp 实现渐变圆弧进度条,并且根据实际数值,控制进度

在uni-app中实现渐变圆弧进度条可以使用canvas来绘制。下面是一个简单的示例: 在template中添加canvas标签: <canvas canvas-id="progressCanvas" style="width: 200px; height: 200px;"></canvas>在script中添加以下代码: export defau…

STM32智能家居控制系统教程

目录 引言环境准备智能家居控制系统基础代码实现&#xff1a;实现智能家居控制系统 4.1 数据采集模块 4.2 数据处理与分析模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;家居监测与优化问题解决方案与优化收尾与总结 1. 引言 智能家居控制系统通…

“微软蓝屏”事件暴露的网络安全问题

“微软蓝屏”事件暴露的网络安全问题 近日&#xff0c;一次由微软视窗系统软件更新引发的全球性“微软蓝屏”事件&#xff0c;不仅成为科技领域的热点新闻&#xff0c;更是一次对全球IT基础设施韧性与安全性的深刻检验。这次事件源于美国电脑安全技术公司“众击”提供的一个带…

【数据结构--排序】

目录 一、排序概述1.1、排序的相关定义1.2、排序用到的结构与函数 二、常见排序算法2.1、冒泡算法&#xff08;交换顺序&#xff09;&#xff08;1&#xff09;算法&#xff08;2&#xff09;性能分析 2.2、简单选择排序&#xff08;1&#xff09;算法&#xff08;2&#xff09…

FastAPI(七十一)实战开发《在线课程学习系统》接口开发-- 查看留言

源码见&#xff1a;"fastapi_study_road-learning_system_online_courses: fastapi框架实战之--在线课程学习系统" 之前FastAPI&#xff08;七十&#xff09;实战开发《在线课程学习系统》接口开发--留言功能开发分享了留言开发&#xff0c;这次我们分享查看留言 梳…

网络服务与应用

一、 文件传输 FTP 1、FTP采用典型的C/S架构&#xff08;即服务器端和客户端模型&#xff09;&#xff0c;客户端与服务器端建立TCP连接之后即可实现文件的上传、下载。 2、FTP传输过程 1&#xff09;、主动模式&#xff08;POST&#xff09;&#xff1a;入站连接 2&#x…

SqlSugar删除没有定义主键的实体类对应的数据库表数据

一般而言&#xff0c;使用SqlSugar的DbFirst功能创建数据库表实体类时&#xff0c;如果数据库表有主键&#xff0c;生成的实体类对应属性也会标识为主键&#xff0c;如下图所示。   但有时候生成的实体类没有自动配置主键&#xff0c;这时可以通过以下方式进行删除操作&…

【计算机网络】HTTP协议实验

一&#xff1a;实验目的 1&#xff1a;理解HTTP协议的基本工作原理。 2&#xff1a;使用Wireshark或其他抓包工具捕获并分析HTTP数据包&#xff0c;理解HTTP通信的具体过程。 3&#xff1a;通过分析抓包数据&#xff0c;识别常见的HTTP状态码及其含义。 二&#xff1a;实验仪…

光伏电站的运维经验

选择逆变器一是要看产品本身的效率和品质&#xff1b;二是要看系统的架构&#xff0c;怎么做的更简单&#xff0c;更可靠&#xff1b;三是要看场景的适应性&#xff1b;四是看服务。箱式逆变房后期运维无需协调多个厂家&#xff0c;大大提升了运维效率。相比自制土建房&#xf…

02集成开发工具配置VScode SSH连接Ubuntu20.04 - 输入密码连接

文章目录 1. running the VScode in Admin mode2. Install the plugin3. New Remote4. Enther the command at the top blanket column in VS Code5. Setup the ssh config file6. Restart VScode7. Connect to the Server8. Open the remote folder 1. running the VScode in …

Python 函数对象和函数调用

Python 函数对象和函数调用 在 Python 中&#xff0c;函数是第一类对象&#xff08;first-class objects&#xff09;。这意味着函数可以像其他对象&#xff08;如整数、字符串、列表等&#xff09;一样被传递、赋值和操作。理解函数对象和函数调用的区别是学习 Python 的关键…

简单了解反射

反射 文章目录 反射获取class对象的三种方式利用反射获取构造方法利用反射获取字段&#xff08;成员变量&#xff09;利用反射获取成员方法反射的作用 获取class对象的三种方式 ①Class.forName(“全类名”);&#xff08;源代码阶段使用&#xff09; ②类名.class&#xff08…

学习C语言之 深入了解指针1

深入了解指针 前面已了解到 1&#xff09;指针就是个变量&#xff0c;用来存放地址&#xff0c;地址是唯一的&#xff0c;可以标识一块内存空间。 2&#xff09;指针的大小是固定的4/8个字节&#xff08;32位平台/64位平台&#xff09;。 3&#xff09;指针是有类型的&#xf…

Linux中如何用ida调试fork后的子进程

原文链接 > https://redqx.github.io/linux/2024/07/24/linux-debugfork.html 本文的一些图片引用可能有一些问题, 比如数据不对劲,但无伤大雅 自己懒得粘贴图片了 环境: wsl-kali-2024 ida-7.7 插件: Lazy_ida, 还有一个什么插件不知道什么名字, 可以把汇编转字节码 …

mac安装Whisper

Whisper 官方git https://github.com/openai/whisper?tabreadme-ov-file 基本上参考官方的安装流程 pip3 install -U openai-whisper pip3 install githttps://github.com/openai/whisper.git pip3 install --upgrade --no-deps --force-reinstall githttps://github.com/…

牛客周赛52--E小红的图上加边(联通块)

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 题目描述 \,\,\,\,\,\,\,\,\,\,小红有一张 nnn 个点 mmm 条边的无向图&#xff0c;每个节点的权值是 aia_iai​。           \,\,\,\,\,\,\,\,\,\,现在小红希望加边把这个图连成连通…

Elasticsearch概念及ELK安装

1、Elasticsearch是什么 它是elastic技术栈中的一部分。完整的技术栈包括&#xff1a; Elasticsearch&#xff1a;用于数据存储、计算和搜索 Logstash/Beats&#xff1a;用于数据收集 Kibana&#xff1a;用于数据可视化 整套技术栈被称为ELK&#xff0c;经常用来做日志收集…

ansible的role目录结构及用法

目录 目录结构介绍案例 目录结构介绍 可以通可以通过使用 ansible-galaxy 命令再当前目录自动生成 role 的基本目录结构。 myrole为文件名&#xff08;角色名&#xff09; ansible-galaxy init myrole如果没有安装Ansible Galaxy&#xff0c;你可以使用以下命令安装&#xff…

Python 函数的参数形式

Python 函数的参数形式 Python 函数的参数有多种形式&#xff0c;每种形式在不同的场景下使用。我们主要介绍以下几种&#xff1a; 位置参数关键字参数默认参数可变位置参数&#xff08;*args&#xff09;可变关键字参数&#xff08;**kwargs&#xff09; 1. 位置参数 位置…