C++中模板的初级使用函数模板(刚刚接触模板概念的小白也能明白)

news2024/9/20 11:54:46

文章目录

  • 模板分类
  • 函数模板
  • 函数模板的原理
  • 函数模板基本语法 —— typename 以及 class
  • 简单的函数模板
  • 多类型模板参数
  • class 和 typename 的选择
  • 类模板

模板分类

模板的核心思想是让编译器在编译时生成适用于具体类型的代码,这个过程称为模板实例化。C++ 中的模板分为两种:函数模板和类模板。
在这里插入图片描述
本文对于模板的讲解仅包含模板中函数模板的部分,即初阶讲解类模板仅包含一小部分提供一些示例

函数模板

  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;
 }
 ......

使用函数重载虽然可以实现,但是有一下几个不好的地方:

  1. 重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数
  2. 代码的可维护性比较低,一个出错可能所有的重载均出错那能否告诉编译器一个模子,让编译器根据不同的类型利用该模子来生成代码呢?

这是我们经常写的两个值交换函数,但是在我们交换不同类型数据的时候,我们就需要对这个交换函数再进行一份书写,这样就会显得整个代码程序写的非常冗余,所以在C++当中,引出了模板的这个概念

在 C++ 中,函数模板是一种可以编写泛型代码的机制。它允许你编写一个函数,而不需要预先定义具体的数据类型。函数模板可以用于处理不同类型的参数,而不需要为每个类型编写不同的函数。通过函数模板,C++ 提供了一种类型无关的编程方法。

函数模板的原理

在这里插入图片描述
在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此。

函数模板基本语法 —— typename 以及 class

template <typename T>
返回类型 函数名(参数列表) {
    // 函数体
}

template <classs T>
返回类型 函数名(参数列表) {
    // 函数体
}

在模板参数列表中,class 和 typename 是等价的,可以互换使用。

简单的函数模板

示例:

#include <iostream>
using namespace std;

template <typename T>
T add(T a, T b) {
    return a + b;
}

int main() {
    cout << add(3, 4) << endl;        // 整数相加,输出 7
    cout << add(3.5, 4.2) << endl;    // 浮点数相加,输出 7.7
    return 0;
}

在这个例子中,add 函数是一个模板函数,它接受两个类型相同的参数,并返回它们的和。模板参数 T 使得这个函数能够同时处理 int、double 等多种类型。

#include <iostream>
using namespace std;

template <class T>
T max_value(T a, T b) {
    return (a > b) ? a : b;
}

int main() {
    cout << max_value(10, 20) << endl;         // 整数比较,输出 20
    cout << max_value(3.14, 2.71) << endl;     // 浮点数比较,输出 3.14
    return 0;
}

在这个例子中,模板参数 T 可以是任何类型,当我们调用 max_value 时,C++ 编译器会根据传递的参数自动推导 T 的类型。这个函数模板可以处理整数、浮点数等不同类型。

多类型模板参数

函数模板可以包含多个模板参数,允许不同类型的输入。例如:

#include <iostream>
using namespace std;

template <typename T1, typename T2>
auto multiply(T1 a, T2 b) -> decltype(a * b) {
    return a * b;
}

int main() {
    cout << multiply(10, 2.5) << endl; // 整数和浮点数相乘,输出 25.0
    return 0;
}
#include <iostream>
using namespace std;

template <class T1, class T2>
auto add(T1 a, T2 b) -> decltype(a + b) {
    return a + b;
}

int main() {
    cout << add(10, 2.5) << endl;       // 整数和浮点数相加,输出 12.5
    cout << add(100L, 200) << endl;     // 长整型和整型相加,输出 300
    return 0;
}

class 和 typename 的选择

如果你是在模板参数列表中声明类型参数,你可以自由选择 class 或 typename,两者没有任何功能上的区别。

template <class T>
void func(T a) {}

template <typename T>
void func(T a) {}

类模板

除了函数模板,C++ 还支持类模板,使类可以处理不同的数据类型。下面是一个简单的类模板的例子,它实现了一个通用的容器类 Box,可以存储任何类型的数据。

格式:

template<class T1, class T2, ..., class Tn> 
class 类模板名
{
 // 类内成员定义
};   

示例

#include <iostream>
using namespace std;

template <class T>
class Box {
private:
    T value;
public:
    Box(T v) : value(v) {}
    void display() const {
        cout << "Box contains: " << value << endl;
    }
};

int main() {
    Box<int> intBox(123);           // 创建存储整数的 Box
    Box<double> doubleBox(3.14);    // 创建存储浮点数的 Box
    Box<string> stringBox("Hello"); // 创建存储字符串的 Box

    intBox.display();      // 输出: Box contains: 123
    doubleBox.display();   // 输出: Box contains: 3.14
    stringBox.display();   // 输出: Box contains: Hello

    return 0;
}

在这个类模板中,class T 表示模板参数 T,可以是任何类型。我们可以创建不同类型的 Box 对象,比如 int, double, 或 string,每个 Box 对象会存储相应类型的数据。

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

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

相关文章

3 种自然语言处理(NLP)技术:RNN、Transformers、BERT

自然语言处理 (NLP) 是人工智能的一个领域&#xff0c;旨在使机器能够理解文本数据。NLP 研究由来已久&#xff0c;但直到最近&#xff0c;随着大数据和更高计算处理能力的引入&#xff0c;它才变得更加突出。 随着 NLP 领域的规模越来越大&#xff0c;许多研究人员都试图提高…

大模型算法二次开发,基本思路详细拆解

前言 随着众多大模型相继问世&#xff0c;大模型二次开发、大模型微调成为一项热门技术。本文为大家总结了大模型二次开发的基本方法与思路&#xff0c;希望对大家有所帮助。 转载自丨吃果冻不吐果冻皮 开发方法分类 1、领域知识注入&#xff1a;Continue PreTraining(增量…

LeetCode_sql_day28(1767.寻找没有被执行的任务对)

描述&#xff1a;1767.寻找没有被执行的任务对 表&#xff1a;Tasks ------------------------- | Column Name | Type | ------------------------- | task_id | int | | subtasks_count | int | ------------------------- task_id 具有唯一值的列。 ta…

简单题88. 合并两个有序数组 (Python)20240920

问题描述&#xff1a; python&#xff1a; class Solution(object):def merge(self, nums1, m, nums2, n):""":type nums1: List[int]:type m: int:type nums2: List[int]:type n: int:rtype: None Do not return anything, modify nums1 in-place instead.&qu…

GSAP动画库:让网页动起来的艺术

GSAP动画库&#xff1a;让网页动起来的艺术 前言 在现代网页设计中&#xff0c;动画效果不仅能够提升用户体验&#xff0c;还能增强视觉吸引力。 GSAP&#xff08;GreenSock Animation Platform&#xff09;是业界领先的动画库&#xff0c;它提供了强大的工具和功能&#xff…

Vue3快熟

Vue3快速上手 1. Vue3简介1.1. 【性能的提升】1.2.【 源码的升级】1.3. 【拥抱TypeScript】1.4. 【新的特性】 2. 创建Vue3工程2.1. 【基于 vue-cli 创建】2.2. 【基于 vite 创建】(推荐)2.3. 【一个简单的效果】 3. Vue3核心语法3.1. 【OptionsAPI 与 CompositionAPI】Options…

医学数据分析实训 项目十 基于深度残差神经网络的皮肤癌检测

文章目录 综合实践三 基于深度残差神经网络的皮肤癌检测实现步骤1&#xff1a;图像数据预处理实现步骤2&#xff1a;模型构建实现步骤3&#xff1a;性能度量提交要求 1 基于深度残差神经网络的皮肤癌检测代码2 结果分析 综合实践三 基于深度残差神经网络的皮肤癌检测 皮肤镜图…

Games101学习 - 着色

本文主要讲述Games101中的着色部分。 文中将使用UE的UTexture2D接口&#xff0c;若不了解可以看这篇&#xff1a; https://blog.csdn.net/grayrail/article/details/142165442 1.面积比计算三角形坐标 通过三角形面积比可以得到三角形的坐标alpha、beta、gamma从而进行插值&a…

MATLAB画图,曲线图如何绘制美观,曲线图10种美化方法

曲线图是比较常用的图形&#xff0c;本文以二维曲线图为例&#xff0c;展示曲线的图的不同美化方法&#xff0c;如图1所示&#xff0c;是一个标准的曲线图&#xff0c;横坐标为x&#xff0c;纵坐标为y, 图1 标准曲线图 调整方法1 首先可以通过改变线的颜色&#xff0c;不同…

react + antDesign封装图片预览组件(支持多张图片)

需求场景&#xff1a;最近在开发后台系统时经常遇到图片预览问题&#xff0c;如果一个一个的引用antDesign的图片预览组件就有点繁琐了&#xff0c;于是在antDesign图片预览组件的基础上二次封装了一下&#xff0c;避免重复无用代码的出现 效果 公共预览组件代码 import React…

Python安装不再难!全平台保姆级教程带你轻松搞定!

Python介绍 Python是一种功能强大且灵活的编程语言&#xff0c;被广泛应用于各个领域。以下是Python在不同应用领域的一些常见用途&#xff1a; 网络开发 Python提供了丰富的库和框架&#xff0c;使其成为网络开发的理想选择。诸如Django、Flask和Pyramid等框架可以帮助开发人员…

从 HDFS 迁移到 MinIO 企业对象存储

云原生、面向 Kubernetes 、基于微服务的架构推动了对 MinIO 等网络存储的需求。在云原生环境中&#xff0c;对象存储的优势很多 - 它允许独立于存储硬件对计算硬件进行弹性扩展。它使应用程序无状态&#xff0c;因为状态是通过网络存储的&#xff0c;并且通过降低操作复杂性&a…

Vue使用组件需要加前缀而React使用组件库的区别

Vue 写在模版中的内容最终会被render&#xff0c;render时会区分标签与组件。 通过-短横线命名法 或 大驼峰命名法使用组件 <a-button><a-button/> <MyComponent></MyComponent>但是-短横线命名法容易引起歧义&#xff0c;比如组件名是一个单词(无法…

learn C++ NO.17——继承

什么是继承&#xff1f; 用冒号 : 后跟基类名称来声明一个类是从某个基类继承而来的。继承方式可以是 public、protected 或 private&#xff0c;这决定了基类成员在子类中的访问权限。 下面通过代码简单进行一下演示. 派生类Student即子类&#xff0c;而基类Person是它的父…

浏览器恢复历史记录应该怎么操作?简单几步轻松搞定

浏览器的历史记录是用户上网过程中产生的所有浏览活动的记录。这些历史记录对于查找之前访问过的网站、恢复误关闭的页面&#xff0c;以及跟踪浏览活动有很大的帮助。当然有时候我们可能会不小心将浏览器历史记录给删除了&#xff0c;那浏览器清除的历史记录可以恢复吗&#xf…

Linux 信号的产生

1. 概念 在Linux系统中&#xff0c;信号是一种进程间通信的机制&#xff0c;它允许操作系统或其他进程向特定进程发送异步通知。我们可以通过命令 kill -l来查看信号的种类&#xff1a; Linux系统中的信号可以分为两大类&#xff1a;传统信号和实时信号。从上图可以看出它们分…

代码随想录算法训练营第40天 动态规划part07| 题目: 198.打家劫舍 、 213.打家劫舍II 、 337.打家劫舍III

代码随想录算法训练营第40天 动态规划part07| 题目&#xff1a; 198.打家劫舍 、 213.打家劫舍II 、37.打家劫舍III 文章来源&#xff1a;代码随想录 题目名称&#xff1a;198.打家劫舍 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff…

【随手笔记】485

1. 基础知识 2线&#xff0c;半双工&#xff0c;多点通信 电压差传递信号 逻辑 1&#xff1a; 两线间电压差为 2V ~ 6V 逻辑0 &#xff1a; 两线间电压差为-2V ~ -6V 10米最高速率达 35Mbps 1200米 速率达100Kbps 抗共模干扰能力强 一般支持32个节点 推荐使用点对点线型 总线…

IDEA开发HelloWorld程序

IDEA管理Java程序的结构 project&#xff08;项目、工程&#xff09;---project中可以创建多个modulemodule&#xff08;模块&#xff09;---module中可以创建多个packagepackage&#xff08;包&#xff09;---package中可以创建多个classclass&#xff08;类&#xff09;---c…

木牛科技PMO总监关沨受邀为第四届中国项目经理大会演讲嘉宾

全国项目经理专业人士年度盛会 北京木牛领航科技有限公司PMO总监关沨女士受邀为PMO评论主办的全国项目经理专业人士年度盛会——2024第四届中国项目经理大会演讲嘉宾&#xff0c;演讲议题为“如何培养能打胜仗的项目经理”。大会将于10月26-27日在北京举办&#xff0c;主题为&a…