【C++泛型编程】(一)函数模板和类模板

文章目录

  • (一)函数模板和类模板
    • 函数模板
    • 类模板
    • 模板的特化

(一)函数模板和类模板

C++泛型编程(Generic Programming)是一种编程范式,它允许程序员编写与参数无关的代码,也就是说这些代码可以在多种数据类型上重用,而无需为每个类型重新编写。

泛型编程的主要工具是模板(Templates),主要分为两种类型:函数模板和类模板。

函数模板

函数模板允许程序员编写一个通用的函数,该函数可以接受不同类型的参数,并在编译时根据提供的参数类型生成特定的函数版本。其语法如下:

template<typename T>
return_type functionName(T arg1, T arg2) {// 函数体
}
  • template — 声明创建模板
  • typename — 表面其后面的符号是一种数据类型,可以用class代替
  • T — 通用的数据类型。T只是一个约定的名称,可以将其改为其他标识符。
  • return_type : 返回值的类型,需要根据函数体指定,如:voidint或者T

函数模板的实例化

在使用函数模板时,编译器会根据传递的参数类型自动推导模板参数:

functionName(arg1, arg2); // 自动推导

或者你可以显式指定模板参数:

functionName<int>(arg1, arg2); // 显式实例化

示例:返回两个数中的较大者

#include <iostream>// 函数模板:返回两个数中的较大者
template<typename T>
T max(T a, T b) {return (a > b) ? a : b;
}int main() {std::cout << "Max of 5 and 3: " << max(5, 3) << std::endl;// 调用max<int>(5, 10)std::cout << "Max of 5.5 and 3.3: " << max(5.5, 3.3) << std::endl;// 调用max<double>(5.5, 3.3)return 0;
}
Max of 5 and 3: 5
Max of 5.5 and 3.3: 5.5

类模板

类模板则允许你编写一个通用的类,该类可以在编译时根据提供的类型参数生成特定的类版本。基本语法:

template<typename T>
// 类

类模板的定义包括构造函数、成员函数和成员变量等的定义,模板参数在类内部可以用作类型标识符:

template<typename T>
class ClassName {
public:ClassName(T value); // 构造函数模板void setValue(T value); // 成员函数模板private:T data; // 数据成员
};// 类模板的析构函数、构造函数和成员函数的实现通常放在类模板定义的外部。
template<typename T>
ClassName<T>::ClassName(T value) : data(value) {}template<typename T>
void ClassName<T>::setValue(T value) {data = value;
}

类模板的实例化

在使用类模板时,需要为模板参数指定具体的类型。

ClassName<int> obj(42);

示例:一个通用数据类型的栈数据结构

#include <iostream>
// 类模板:一个简单的栈
template<typename T>
class Stack {
public:Stack();~Stack(); void push(T value);T pop();private:T* data;int top;const static int size = 100;
};
// 类模板的构造函数
template<typename T>
Stack<T>::Stack() {data = new T[size];top = -1;
}
// 类模板的析构函数 
template<typename T>  
Stack<T>::~Stack() {  delete[] data; // 释放动态分配的数组  
}  
// 类模板的成员函数:入栈
template<typename T>
void Stack<T>::push(T value) {data[++top] = value;
}
// 类模板的成员函数:出栈
template<typename T>
T Stack<T>::pop() {return data[top--];
}int main() {Stack<int> intStack;intStack.push(1);intStack.push(2);intStack.push(3);std::cout << intStack.pop() << std::endl; // 输出3std::cout << intStack.pop() << std::endl; // 输出2return 0;
}

模板的特化

模板的特化(Template Specialization)是一种对通用模板进行特殊处理的技术,以适应特定类型或条件的需求,可以分为全特化和偏特化两种类型:

  • 全特化:全特化是指对模板的所有模板参数都进行特化处理。例如,如果有一个模板类Test<T1, T2>,全特化可能是为Test<int, char>这样的具体类型提供特定的实现。

  • 偏特化:偏特化是指只对部分模板参数进行特化处理。例如,如果有一个模板类Test<T1, T2>,偏特化可能是为Test<T1, char>这样的部分具体类型提供特定的实现,其中T1仍然是一个模板参数。

示例:

#include <iostream>// 通用模板类定义
template<typename T1, typename T2>
class Test {
public:void show() {std::cout << "General template" << std::endl;}
};// 全特化示例:为Test<int, char>提供特定实现
template<>
class Test<int, char> {
public:void show() {std::cout << "Full specialization for Test<int, char>" << std::endl;}
};// 偏特化示例:为Test<T1, char>提供特定实现,其中T1是任意类型
template<typename T1>
class Test<T1, char> {
public:void show() {std::cout << "Partial specialization for Test<T1, char>" << std::endl;}
};int main() {// 使用通用模板类Test<double, double> t1;t1.show(); // 输出:General template// 使用全特化类Test<int, char> t2;t2.show(); // 输出:Full specialization for Test<int, char>// 使用偏特化类Test<float, char> t3;t3.show(); // 输出:Partial specialization for Test<T1, char>return 0;
}

对于函数模板,一般采用重载(Overloading)代替特化。例如,如果你有一个函数模板,并且想要为int类型提供特定的实现,你可以简单地重载该函数模板:

#include <iostream>// 通用函数模板
template<typename T>
void print(T value) {std::cout << "Generic print: " << value << std::endl;
}// 重载函数模板,为int类型提供特定实现
void print(int value) {std::cout << "Specialized print for int: " << value << std::endl;
}int main() {print(10);     // 调用重载版本,输出 "Specialized print for int: 10"print(3.14);   // 调用通用模板版本,输出 "Generic print: 3.14"print("Hello"); // 调用通用模板版本,输出 "Generic print: Hello"return 0;
}

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

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

相关文章

docker-nginx目录宿主机映射

一.拉取nginx镜像 docker pull nginx 二.运行 docker run -d -it -p 22222:80 --namenginx 三.拷贝配置文件到宿主机 docker cp 4199da4355c5:/usr/share/nginx/html /home/docker/nginx 四.再次运行 docker run -d -it -p 22222:80 --namenginx -v /home/docker/nginx…

第10篇:创建Nios II工程之控制单个七段数码管

Q&#xff1a;还记得之前使用Verilog case语句来描述实现七段数码管的逻辑功能。本期我们创建Nios II工程用C语言代码实现相同的功能。 A&#xff1a;基本原理&#xff1a;一个七段数码管由7个发光二极管LED组成&#xff0c;所以控制一个数码管的显示即控制7个LED。我们在之前…

手把手教你上手开源性能监控神器Arthas

前言 在日常的工作中&#xff0c;对于商业项目尤其是并发量较高的项目&#xff0c;系统在一些情况下会莫名其妙把CPU打满并且导致服务宕机&#xff0c;虽然90%的情况下&#xff0c;是迭代发版的代码有bug&#xff0c;但是既然有这个情况&#xff0c;线上出现事故了&#xff0c…

海外大带宽服务器的带宽大小是如何定义的?

海外大带宽服务器的带宽大小通常是由提供的数据传输速率来衡量的。Rak部落小编为您整理发布海外大带宽服务器的带宽大小是如何定义的? 带宽的大小决定了服务器能够处理的数据量和传输速度&#xff0c;这对于确保服务器性能至关重要。在详细定义中&#xff0c;带宽可以根据以下…

PLM帮助离散行业解决行业痛点

近年来&#xff0c;离散行业发生了巨大的变化和动荡&#xff0c;如果您经营一家想要向前发展并获得市场份额的企业&#xff0c;那么脱颖而出而不是融入其中至关重要。这就是为什么企业需要重视使用最先进的技术&#xff0c;向客户清楚地表明您的企业在经济不确定时期依旧稳如泰…

对C语言符号的一些冷门知识运用的剖析和总结

符号 目录* 符号 注释 - 奇怪的注释 - C风格的注释无法嵌套 - 一些特殊的注释 - 注释的规则建议 反斜杠’’ - 反斜杠有续行的作用&#xff0c;但要注意续行后不能添加空格 * 回车也能起到换行的作用&#xff0c;那续行符的意义在哪&#xff1f; - 反斜杠的转义功能 单引号…

Hadoop部署模式

Hadoop部署模式常用部署方式有三种&#xff0c;分别是&#xff1a;单机模式、伪分布式模式、完全分布式模式&#xff0c;除此之外&#xff0c;还有云平台部署和容器化部署。下面分别说明5种部署方式的特点。 1. 单机模式&#xff08;Standalone Mode&#xff09;&#xff1a;又…

AI工具实用性探讨

AI工具介绍 人工智能&#xff08;AI&#xff09;工具是利用人工智能技术和算法来完成特定任务或提供特定服务的软件应用程序。这些工具可以模拟人类的智能行为&#xff0c;如学习、推理、识别、理解和交流&#xff0c;从而实现自动化、智能化和高效化的目标。以下是一些常用的A…

公钥私钥?一文搞懂非对称加密

非对称加密 非对称加密&#xff1a; 通信双方分别创建公钥和私钥&#xff0c;并且保证公钥所加密的信息&#xff0c;只有配对的私钥可以解密&#xff0c;接下来&#xff0c;双方公开交换公钥&#xff0c;通信时&#xff0c;使用对方的公钥进行加密&#xff0c;如此&#xff0…

java 内部类理解

一、简介 在Java中&#xff0c;可以将一个类定义在另一个类里面或者一个方法里面&#xff0c;这样的类称为内部类。广泛意义上的内部类一般来说包括这四种&#xff1a;成员内部类、局部内部类、匿名内部类和静态内部类。下面就先来了解一下这四种内部类的用法。 二、成员内部…

代码随想录day55 | 动态规划P15 | ● 392.判断子序列 ● 115.不同的子序列

392.判断子序列 给定字符串 s 和 t &#xff0c;判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些&#xff08;也可以不删除&#xff09;字符而不改变剩余字符相对位置形成的新字符串。&#xff08;例如&#xff0c;"ace"是"abcde"的…

国内小白用什么方法充值使用ChatGPT4.0?

首先说一下IOS礼品卡订阅&#xff0c;目前最经济实惠的订阅方式&#xff0c;具体操作步骤 使用IOS设备充值&#xff0c;用 App Stroe 兑换券 1、支付宝地址切换旧金山&#xff0c;在里面买app store 的兑换卷 2、美区Apple ID登陆app store &#xff0c;充值兑换券 3、IOS设…

JavaScript中的事件模型

JavaScript中的事件模型分为&#xff1a;事件和事件流、原始事件、标准事件和IE事件。 事件与事件流 JavaScript中的事件&#xff0c;可以理解为HTML文档或者浏览器中发生的一种交互操作&#xff0c;让网页有互动的功能。常见的事件就是加载事件、鼠标事件和自定义事件。 因…

Find My资讯|苹果设备在修复期间可以保持启用“Find My“功能

iOS 17.5 中有一项名为"维修状态"的新功能&#xff0c;可让送修的设备保持启用"查找我的"&#xff08;Find My&#xff09;功能。此前&#xff0c;用户在送修设备时必须禁用跟踪设备位置的"查找我的"功能&#xff0c;但iOS 17.5发布后&#xff0…

vscode远程免密ssh原理与实操方法

什么是SSH SSH是一种加密协议&#xff0c;全称为Secure Shell&#xff0c;用于安全地远程登录到服务器或其他远程设备上执行命令或传输文件。它提供了一种安全的加密通信机制&#xff0c;使得远程登录和文件传输等操作不会被恶意攻击者窃取或篡改&#xff0c;确保了数据的保密…

Jackson系统开发方法

1、Jackson分析方法是面向数据流的分析方法。这一方法从目标系统的输入、输出数据结构入手&#xff0c;导出程序框架结构&#xff0c;再补充其它细节&#xff0c;就可得到完整的程序结构图。 2、应用场景&#xff1a;这一方法对输入、输出数据结构明确的中小型系统特别有效&am…

数据库(MySQL)—— 初识和创建用户

数据库&#xff08;MySQL&#xff09;—— 初识 什么是数据库数据库的种类创建用户mysql -h 主机名或IP地址 -u 用户名 -p 登录mysqlSELECT USER(); 查看当前用户切换用户GRANT ALL PRIVILEGES ON 赋予用户权限 REVOKE 撤销权限示例注意事项 MySQL的图形化界面工具查看所有用户…

【oracle数据库安装篇三】Linux6.8单机环境oracle11g容灾ADG搭建

说明 DataGuard 是在主节点与备用节点间通过日志同步来保证数据的同步&#xff0c;可以实现数据库快速切换与灾难性恢复。用户能够在对主数据库影响很小的情况下&#xff0c;实现主备数据库的同步。 关联文章 【oracle数据库安装篇一】Linux5.6基于LVM安装oracle11gR2单机 【…

追踪攻击数据包中的真实IP地址:方法与技巧

在网络安全领域&#xff0c;追踪攻击数据包中的真实IP地址是一项至关重要的任务。通过确定攻击者的真实IP地址&#xff0c;可以有效地识别和阻止网络攻击行为&#xff0c;提高网络安全防御水平。IP数据云IP地址查询将介绍几种常用的方法和技巧&#xff0c;帮助安全人员有效追踪…

嵌入式C语言教程:实现气压监测系统

气压监测在气象学、航空和户外活动装备中非常重要。本教程将介绍如何在STM32微控制器上使用数字气压传感器实现实时气压监测系统。 一、开发环境准备 硬件要求 微控制器&#xff1a;STM32L476RG&#xff0c;具备低功耗特性和足够的处理能力。开发板&#xff1a;STM32L4 Disc…