《21天学通C++》(第十四章) 宏和模板介绍(2)

相较于宏,C++更推荐使用模板编程,因为它们提供了更好的类型安全、更清晰的语法和更易于调试的代码

1.模板函数

语法

template <typename T>
void function(T param) {// 函数体,使用T作为类型参数
}

例子

#include <iostream>
using namespace std; // 模板函数,用于计算两个值的和
template <typename T>
T add(T a, T b) {return a + b;
}int main() {int intResult = add(10, 20);      // 自动推导T为intdouble doubleResult = add(10.5, 20.5); // 自动推导T为doublecout << "Sum of ints: " << intResult << endl;cout << "Sum of doubles: " << doubleResult << endl;// 也可以显式指定模板参数类型long longResult = add<long>(100, 200);//指定为intcout << "Sum of longs: " << longResult << endl;system("pause");return 0;
}

模板函数特化: 模板函数还可以进行特化,为特定类型提供特定的实现。

例子

#include <iostream>
using namespace std;
// 通用模板函数
template <typename T>
T maximum(T a, T b) {return (a > b) ? a : b;
}// 特化模板函数,针对整数类型
template <>
int maximum<int>(int a, int b) {cout << "Maximum of two integers: " << (a > b ? a : b) << endl;return (a > b) ? a : b;
}int main() {int i = maximum(10, 20);    // 使用特化版本double d = maximum(3.14, 2.72); // 使用通用模板版本cout << "Max int: " << i << endl;cout << "Max double: " << d << endl;system("pause");return 0;
}

2.模板类

语法

template <typename T>
class MyClass {
public:T member; // 使用模板参数T作为类的成员变量类型void function(T param) {// 使用模板参数T作为函数参数类型}
};

例子

#include <iostream>
using namespace std;// 模板类Box的定义
template <typename T>
class Box {
private:T contents; // 盒子里存储的对象,类型由模板参数T决定public:// 构造函数,用于初始化盒子里的对象Box(const T& value) : contents(value) {}// 成员函数,用于获取盒子里的对象T getContents() const {return contents;}// 成员函数,用于设置盒子里的对象void setContents(const T& value) {contents = value;}
};int main() {// 创建一个存储整数的盒子Box<int> intBox(10);cout << "The Box contains: " << intBox.getContents() << endl;// 创建一个存储字符串的盒子Box<string> stringBox("Hello, World!");cout << "The Box contains: " << stringBox.getContents() << endl;// 修改盒子里的内容intBox.setContents(20);cout << "After setting a new value, the Box contains: " << intBox.getContents() << endl;system("pause");return 0;
}

3.声明包含多个参数的模板

#include <iostream>
using namespace std; 
// 声明一个有两个类型参数的模板类
template <typename T1, typename T2>
class Pair {
private:T1 first;  // 第一个元素的类型为T1T2 second; // 第二个元素的类型为T2public:// 构造函数,初始化first和secondPair(const T1& f, const T2& s) : first(f), second(s) {}// 获取第一个元素的值T1 getFirst() const { return first; }// 获取第二个元素的值T2 getSecond() const { return second; }
};int main() {// 创建一个整型和双精度浮点型的Pair对象Pair<int, double> intDoublePair(10, 20.5);// 使用cout输出Pair对象的两个元素的值cout << "First: " << intDoublePair.getFirst() << ", Second: " << intDoublePair.getSecond() << endl;system("pause");return 0; 
}

4.声明包含默认参数的模板

#include <iostream>
using namespace std; // 声明一个模板类PairWithDefault,它有两个类型参数,
// 第二个参数T2有默认值int
template <typename T1, typename T2 = int>
class PairWithDefault {
private:T1 first;  // 第一个元素的类型为T1T2 second; // 第二个元素的类型为T2,默认为intpublic:// 构造函数,使用两个参数分别初始化first和secondPairWithDefault(const T1& f, const T2& s = 0) : first(f), second(s) {}// 获取第一个元素的值T1 getFirst() const { return first; }// 获取第二个元素的值T2 getSecond() const { return second; }
};int main() {// 使用默认的第二个参数类型(即int)创建PairWithDefault对象PairWithDefault<double> defaultPair(3.14);cout << "First: " << defaultPair.getFirst() << ", Second: " << defaultPair.getSecond() << endl;// 明确指定第二个参数类型为char,并创建PairWithDefault对象PairWithDefault<double, char> explicitPair(2.71, 'A');cout << "First: " << explicitPair.getFirst() << ", Second: " << static_cast<char>(explicitPair.getSecond()) << endl;system("pause");return 0; 
}

5.参数量可变的模板

语法

template <typename... Types>
class MyClass {// ...
};

例子

#include <iostream>
#include <string>
using namespace std; // 变长模板函数print的声明
// 它可以接受任意数量和类型的参数
template <typename... Args>
void print(const Args&... args) {(cout << ... << args) << endl; // 使用C++17的折叠表达式来连续输出所有参数,并在最后输出换行符
}int main() {// 调用print函数,传递多个不同类型的参数print(1, 2, "Hello", 'a'); // 输出: 1 2 Hello asystem("pause");return 0; // 程序正常结束,返回0
}

6.使用static_assert执行编译阶段检查

static_assert是C++11新增的功能,能够在不满足指定条件时禁止编译,它允许开发者在编译时对程序进行额外的约束和检查,从而提高代码的安全性和可维护性。

语法

static_assert(expression, "error message");
  • expression:要检查的条件,必须是一个在编译时就能确定的布尔表达式
  • “error message”:如果条件不为真,编译器将显示这条错误信息
    例子
#include <iostream>template <int N>
void doSomethingElse() {// 确保N大于0static_assert(N > 0, "N must be positive");// code}int main() {doSomethingElse<1>(); // 通过编译,因为1是正数// doSomethingElse<-1>(); // 不通过编译,因为-1不是正数system("pause");return 0;
}

PS:

  1. 务必使用模板来实现通用概念
  2. 非必要情况,请使用模板而不是宏
  3. 编写模板函数和模板类时,尽可能使用const

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

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

相关文章

汽车之家,如何在“以旧换新”浪潮中大展拳脚?

北京车展刚刚落幕&#xff0c;两重利好正主导汽车市场持续升温&#xff1a;新能源渗透率首破50%&#xff0c;以及以旧换新详细政策进入落地期。 图源&#xff1a;中国政府网 在政策的有力指引下&#xff0c;汽车产业链的各个环节正经历着一场深刻的“连锁反应”。在以旧换新的…

Python运维之多线程!!

一、多线程 二、多线程编程之threading模块 2.1、使用threading进行多线程操作有两种方法&#xff1a; 三、多线程同步之Lock&#xff08;互斥锁&#xff09; 四、多线程同步之Semaphore&#xff08;信号量&#xff09; 五、多线程同步之Condition 六、多线程同步之Event…

CSS和JavaScript

CSS 在html中引入CSS 我们需要先在该项目先建立css文件 html引入CSS,在<head></head>中添加<link>标签 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" co…

mac 本地使用docker 运行es,kibana

1.下载 m芯片一些版本不支持.踩过坑.翻看官网才知道只有部分镜像支持m芯片 https://hub.docker.com/添加链接描述 docker pull elasticsearch:7.17.21 docker pull kibana:7.17.21镜像已经下载下来了 2.创建文件映射-挂载 /Users/lin/dev/dockerMsg 其中lin是自己的用户名…

关于线程池,它的扩展问题你知道吗?(自己总结)

专门想一下为什么线程池不用Excutors&#xff0c;之前的印象是错的&#xff0c;居然还拿来面试里讲&#xff0c;惭愧&#xff0c;这里暂时整理俩小问题&#xff0c;其他的后续可能会更新。。 线程池是创建的越大越好嘛 #线程池创建的越大越好吗 Tip&#xff1a;2024-04-10 更…

本地搭建hydra服务用go以验证oidc流程

目录 1、docker搭建hydra&#xff0c;环境配置&#xff1a; 2、搭建完成后服务调用&#xff1a; 2.1保证服务正常启动&#xff1a; 2.2 通过postman调用&#xff0c;获取client_id&#xff1a; 2.3 通过client_id&#xff0c;实现oauth2/auth调用 3. 通过go语言实现oidc验…

【qt】容器的用法

容器目录 一.QVertor1.应用场景2.增加数据3.删除数据4.修改数据5.查询数据6.是否包含7.数据个数8.交换数据9.移动数据10.嵌套使用 二.QList1.应用场景2.QStringList 三.QLinkedList1.应用场景2.特殊点3.用迭代器来变量 四.QStack1.应用场景2.基本用法 五.QQueue1.应用场景2.基本…

【前端每日一题】day2

用JS写一个快速排序算法 function quickSort(arr) {if (arr.length < 1) {return arr;}const pivot arr[Math.floor(arr.length / 2)];const left [];const right [];for (let i 0; i < arr.length; i) {if (i Math.floor(arr.length / 2)) {continue; // Skip piv…

OS复习笔记ch5-3

引言 上一节我们学习了关于信号量机制的一些内容&#xff0c;包括信号量的含义&#xff0c;对应的PV操作等。 如图所示&#xff0c;上一节主要是针对信号量的互斥&#xff0c;其实信号量机制还可以做很多事情&#xff0c;比如实现进程同步和前驱关系&#xff0c;这一节我们先复…

【Spring】JdbcTemplate

JdbcTemplate 是 Spring 提供的一个 JDBC 模板类&#xff0c;是对 JDBC 的封装&#xff0c;简化 JDBC 代码 也可以让 Spring 集成其它的 ORM 框架&#xff0c;例如&#xff1a;MyBatis、Hibernate 等 使用 JdbcTemplate 完成增删改查 一、环境准备 数据库&#xff1a; 准备…

Marin说PCB之如何快速打印输出整板的丝印位号图?

当小编我辛辛苦苦加班加点的把手上的板子做到投板评审状态的时候&#xff0c;坐在我旁边的日本同事龟田小郎君说让我把板子上的丝印也要调一下&#xff0c;我当时就急了&#xff0c;这么大的板子&#xff0c;将近1W多PIN 了都&#xff0c;光调丝印都要老半天啊&#xff0c;而且…

Python基础学习之datetime模块

在Python编程中&#xff0c;处理日期和时间是一个常见的需求。Python的datetime模块提供了丰富的类和方法&#xff0c;用于表示和操作日期、时间、时间间隔等。本文将详细介绍Python的datetime模块&#xff0c;并给出一些实用的示例。 1. datetime模块概览 datetime模块是Pyt…

Docx文件误删除如何恢复?别再花冤枉钱了,4个高效恢复软件!

不管是工作还是学习&#xff0c;总是会与各种各样的文件打交道。文件量越多就越容易出现文件丢失、文件误删的情况。遇到这些情况&#xff0c;失去的文件还能找回来吗&#xff1f;只要掌握了一些数据恢复方法&#xff0c;是很有机会恢复回来的&#xff0c;下面我会将这些方法分…

[机器学习系列]深入探索回归决策树:从参数选择到模型可视化

目录 一、回归决策树的参数 二、准备数据 三、构建回归决策树 (一)拟合模型 (二)预测数据 (三)查看特征重要性 (四)查看模型拟合效果 (五) 可视化回归决策树真实值和预测值 (六)可视化决策树并保存 部分结果如下&#xff1a; 一、回归决策树的参数 DecisionTreeRegress…

zookeeper之分布式环境搭建

ZooKeeper的分布式环境搭建是一个涉及多个步骤的过程&#xff0c;主要包括准备工作、安装ZooKeeper、配置集群、启动服务以及验证集群状态。以下是搭建ZooKeeper分布式环境的基本步骤&#xff1a; 1. 准备工作 确保所有节点的系统时间同步。确保所有节点之间网络互通&#xf…

Redis-5 分布式锁

一.为什么要使用分布式锁&#xff1f; 传统的互斥锁synchronized只能作用于同一台虚拟机上的线程&#xff0c;在使用服务器集群部署的情况下&#xff0c;互斥锁就会失效&#xff0c;因此要采用分布式锁来处理不同服务器上的线程访问同一资源的情况。 二.redis的分布式锁是如何…

NVIDIA_SMI has failed because it couldn’t communicate with the NVIDIA driver

参考&#xff1a;https://www.zhihu.com/question/474222642/answer/3127013936 https://blog.csdn.net/ZhouDevin/article/details/128265656 nvidia-smi查看报错&#xff0c;nvcc正常 1&#xff09;查看nvidia版本 ls /usr/src | grep nvidia nvidia-550.78 2&#xff09;…

暗区突围国际服pc端怎么获取测试资格 twitch掉落资格获取教程

《暗区突围》是由腾讯魔方工作室群开发的第一人称射击类手游。游戏以从暗区撤离并收集物资满载而归作为最终目的&#xff0c;带出的战利品可以存储在仓库中&#xff0c;又可以出售用以换取游戏金钱。游戏中玩家可以创建男性或女性角色&#xff0c;可以通过选择脸型、发型、发色…

冒泡法排序方法与找到出现最多的字符及出现次数

一. 简介 本文学习一下&#xff0c;字符大小排序&#xff0c;获取最大值与最小值。 输出字符串中出现最多的字符&#xff0c;以及出现次数。 二. 冒泡法排序方法与获取最大最小值 1. 冒泡法排序 终端随机输入一个字符串&#xff0c;只包括字符0-9&#xff0c;字符串长度…

2024-05-08 postgres-查询树Query-分析

摘要: pg的词法分析和语法分析使用的技术与mysql相同&#xff0c;此法分析使用bison&#xff0c;语法分析使用了flex。之后ANSI SQL句子被转换为查询树。 Query 结构体保存了文本类型的 SQL,经过语法分析后的分析结果&#xff0c;Query 结构体的成员与 SOL语句的各个子句基本…