C++中的函数模板

2023-11-16

觉得大神写的很好,就摘抄下来了,有需要可以查看原版链接,如下: 

以下内容是摘抄博客:C++中的函数模板_年少轻狂,幸福时光-CSDN博客_函数模板

 之前我们知道的交换两个变量的方法有宏定义、函数,这两种方式都能实现两个变量的交换,但是各有各的优缺点
    宏定义:
    - 优点:代码复用,适合所有的类型
    - 缺点:缺少类型检查,宏在预处理阶段就被替换掉,编译器并不知道宏的存在

    函数:
    - 优点:真正的函数调用,编译器对类型进行检查
    - 缺点:类型不同需要重复定义函数,代码无法复用

上边两种方式都各有利弊,但是在C++中,存在泛型编程的概念:即不考虑具体数据类型的编程方式(如下)

C++中的泛型编程有函数模板与类模板,这章我们先来了解函数模板
    函数模板是一种特殊的函数,可以使用不同的类型进行调用,对于功能相同的函数,不需要重复编写代码,并且函数模板与普通函数看起来很类似,区别就是类型可以被参数化

    函数模板通过template与typename两个关键字来定义,如下
 

 

上边就定义了一个变量交换的函数模板,在使用函数模板时有两种方式
    - 自动类型推到调用 Swap(a, b)
    - 具体类型显示调用 Swap<int>(a, b)

    下边以代码来体验一下函数模板

#include <iostream>
 
using namespace std;
 
template <typename T>
void Swap(T& a, T& b)
{
    T tmp = a;
    a = b;
    b = tmp;
}
 
void main()
{
    int a = 10;
    int b = 20;
    Swap(a, b);	//自动推到调用
    //Swap<int>(a, b);//显示指定调用
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
 
    float c = 12.3;
    float d = 23.4;
 
    //Swap(c, d); //自动推到调用
    Swap<float>(c, d); //显示指定调用
    cout << "c = " << c << endl;
    cout << "d = " << d << endl;
    system("pause");
}

可以看到,我们使用函数模板,根据具体类型的参数化,就能适用于不同类型的变量交换,达到了代码复用的效果。

下边来深入理解下函数模板:
    - 对于函数模板中使用的类型不同,编译器会产生不同的函数
    - 编译器会对函数模板进行两次编译
        - 第一次是对函数模板本身进行编译,包括语法检查等
        - 第二次是对参数替换后的代码进行编译,这就相当于编译普通函数一样,进行类型规则检查等。

需要注意的是
    - 函数模板是不允许隐式类型转换的,调用时类型必须严格匹配
 

函数模板还可以定义任意多个不同的类型参数,但是对于多参数函数模板:
    - 编译器是无法自动推导返回值类型的
    - 可以从左向右部分指定类型参数

#include <iostream>
 
using namespace std;
 
template <typename T1, typename T2, typename T3>
T1 add(T2 a, T3 b)
{
    T1 ret;
    ret = static_cast<T1>(a + b);
    return ret;
}
 
void main()
{
    int c = 12;
    float d = 23.4;
    //cout << add(c, d) << endl;	//error,无法自动推导函数返回值
    cout << add<float>(c, d) << endl;	//返回值在第一个类型参数中指定
    cout << add<int, int, float>(c, d) << endl;
    system("pause");
}

在上边的代码中,我们定义了多类型参数的函数模板,调用时需要注意的是函数返回值需要在第一个参数类型中显示指定,后边的类型可自动推导或显示指定。

函数模板跟普通函数一样,也可以被重载
    - C++编译器优先考虑普通函数
    - 如果函数模板可以产生一个更好的匹配,那么就选择函数模板
    - 也可以通过空模板实参列表<>限定编译器只匹配函数模板
 

#include <iostream>
 
using namespace std;
 
template <typename T>
void fun(T a)
{
    cout << "void fun(T1 a)" << endl;
}
 
template <typename T1, typename T2>
void fun(T1 a, T2 b)
{
    cout << "void fun(T1 a, T2 b)" << endl;
}
 
void fun(int a, float b)
{
    cout << "void fun(int a, float b)" << endl;
}
 
void main()
{
    int a = 0;
    float b = 0.0;
    fun(a);   
    fun(a, b);	//普通函数void fun(int a, float b)已经能完美匹配,于是调用普通函数
    fun(b, a);	//这个调用,函数模板有更好的匹配,于是调用函数模板
    fun<>(a, b);	//限定只使用函数模板
    system("pause");
}

从输出可以得到,编译器会优先去调用普通函数,但是当函数模板有更好的匹配时或使用限定符<>时,编译器就会去匹配函数模板。

总结
    - 函数模板是泛型编程在C++中的应用方式之一
    - 函数模板能够根据实参对参数类型进行推导
    - 函数模板支持显示的指定参数类型
    - 函数模板是C++中重要的代码复用方式
    - 函数模板通过具体类型产生不同的函数
    - 函数模板可以定义任意多个不同的类型参数
    - 函数模板中的返回值类型必须显示指定
    - 函数模板可以像普通函数一样重载

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++中的函数模板 的相关文章

随机推荐

  • 使用 docker 搭建 clickhouse 集群

    转载来自 blog miaoji io p 57 写在前面 你好 欢迎浏览我的博客 这篇文章将记录我使用docker搭建clickhouse集群的过程 工具准备 服务器准备 这里我们准备三台服务器 分别配置hostname为server01
  • SpringBoot中静态资源文件的存放位置

    1 静态资源路径是指系统可以直接访问的路径 且路径下的所有文件均可被用户 通过浏览器直接读取 2 在Springboot中默认的静态资源路径有 classpath META INF resources classpath resources
  • 微信小程序——组件库

    文章目录 WeUI ColorUI LinUI echarts for weixin WeUI WeUI是微信官方设计团队为微信Web开发量身打造的一个UI样式库 可以理解为一种类似于Bootstrap的前端UI库 使用WeUI来编写小程序
  • rosrun 和 roslaunch 的时候 TAB 的自动补全出现问题

    rosrun 和 roslaunch 的时候 TAB 的自动补全出现问题 rospack Warning error while crawling home sun boost filesystem status Permission de
  • javaRebel(jRebel)使用手记

    想必大家对项目开发中 调试类文件修改时 容器自动重新加载漫长的过程早已厌倦 我今天闲来无事 于是 想试试javaRebel jRebel 这个东西 javaRebel jRebel 现在是收费软件 不过在网上可以下载到确解版的 在网上查了一
  • please remember me(auto login)

    记住我 用户自动登录的实现 auto login 一 什么是用户自动登录 对于我们的网站向已注册用户提供某些专门的服务 比如网上购物 在线下载 收费浏览等等 就会要求用户在使用这些服务之前进入登录页面 输入用户名和密码 并进行验证 如果用户
  • 搜索引擎(简化版)-分析总结

    整体思路 访问网址 进入首页 输入搜索内容 HTTP服务器接收到HTTP响应 解析取出其中的搜索内容 将搜索内容传输给CGI程序 既搜索客户端 由搜索客户端将搜索内容构造成一个请求 发送给搜索服务器 搜索服务器将请求解析 将搜索内容进行分词
  • hello_Makefile_c++

    1 错误 hello o In function start text 0x0 multiple definition of start usr lib gcc i486 linux gnu 4 4 3 lib crt1 o text 0x
  • html锚点反向联动,Vue监听滚动实现锚点定位(双向)示例_苏颜_前端开发者

    在项目需求中需要实现一个滚轴联动锚点的功能 效果图如下 功能代码demo如下 item name item export default data return scroll list name 第一条 backgroundcolor 90
  • MIPI DSI协议解析

    今天我们一起来学习一下MIPI DSI协议 1 Overview DSI 全称Display Serial Interface 是由MIPI联盟定义的处理器与外设之间的移动设备接口规范 该规范建立在现有的标准的基础上 并采用了MIPI联盟D
  • 从数据库导出List<Map>数据动态生成sheet(数据量少可以参考看看)

    有个问题要注意 数据库导出Map数据如果值为空 这个字段和值不会查询出来 因为我上面配置没成功 execl列名 我用的是sql中文别名截取 就不用创建实体类了 如果你上面没问题就忽略 第一步POM文件
  • arcTo方法理解

    arcTo方法理解 arcTo方法有五个参数 ctx arcTo x1 y1 x2 y2 radius arcTo的参数中包括两个点 x1 y1 x2 y2 radius半径 起点和第一个控制点组成的延长线与第一个控制点和第二个控制点组成的
  • QT笔记- 排序函数qSort()基本用法

    函数 qSort 函数是Qt的一个全局函数 但已被弃用 使用sort 可代替 其原型如下 template
  • 字符串数组反转输出 以空格为单词分隔符 C++

    给出字符串数组及其长度 字符串有若干单词和空格组成 下边代码将数组中单词反转输出 输入 Welcom to Hubei Wuhan 输出为 Wuhan Hubei to Welcom 代码思路为 1 定义两个指针 分别指向一个单词的开头和结
  • 常用终止goroutine的方法

    var wg sync WaitGroup func foo defer wg Done for fmt Println 我是foo函数内的Print time Sleep time Millisecond 500 func main wg
  • 十问了解人工智能

    一 什么是人工智能 人工智能 Artificial Intelligence 简称AI 是指通过计算机技术实现的智能行为 这种行为可以表现为感知 推理 学习 理解 交互等能力 它是一种技术和科学 旨在让计算机能够像人类一样思考 决策和行动
  • Kali linux安装中文输入法

    kali安装中文输入法 pinyin 以下所有步骤在root和update更新后执行 首先安装ibus到系统里 所有指令复制即可使用 apt get install ibus ibus pinyin 安装时会选择是否继续 输入y或者yes即
  • Flask学习

    flask 1 py from flask import Flask app Flask name app route def index return h1 hello world h1 app run flask 2 py from f
  • 基于Pygame的兔獾大战游戏的设计与实现_kaic

    当今社会是一个信息社会且时代发展迅速 时代发展迅速伴随而来的是越来越大的压力 所以通过游戏解压的需求越来越大 游戏也逐渐成为人们日常的娱乐方式 兔獾大战游戏设计了简单的游戏界面和容易让用户理解的游戏操作方式 使得用户可以更好的进行游戏体验
  • C++中的函数模板

    觉得大神写的很好 就摘抄下来了 有需要可以查看原版链接 如下 以下内容是摘抄博客 C 中的函数模板 年少轻狂 幸福时光 CSDN博客 函数模板 之前我们知道的交换两个变量的方法有宏定义 函数 这两种方式都能实现两个变量的交换 但是各有各的优