(转)C++模板函数和重载

2023-11-16

C++模板函数和重载


先来看一个例子:

#include <iostream>
using namespace std ;
//C++函数模版两种定义方式 
//template < typename T>  或  template <class T>
 
template <typename T1> 
T1 check_max(T1 x, T1 y);
 
template <class T>
T  print_value(T x, T y);


//C++重载
 int add(int x,int y);
 int add(int x,int y,int z);
 string add(string str , string str1 , string str2);
 
int main(void)
{
    int x = 33;
    int y = 44;
    long l1 = 333, l2 = 444;
    float f1 = 3.14, f2 = 3.15926;
 
    //系统会自动识别类型 T1为int类型
    cout << "max(x, y) = " << check_max(x, y) << endl;
    //系统会自动识别类型 T1为long类型
    cout << "max(x, y) = " << check_max(l1, l2) << endl;
    //系统会自动识别类型 T1为float类型
    cout << "max(x, y) = " << check_max(f1, f2) << endl;
    cout << "==========================================" << endl ;
    print_value(x,y);
    print_value(l1,l2);
    print_value(f1,f2);
    
    
    //重载的使用
    cout << "==========================================" << endl ;
    cout << add(x,y) << endl ; 
    cout << add(x,y,x) << endl ;
    cout << add("hello"," ","world") << endl ;
    return 0;
}
 
template <typename T1>
T1 check_max(T1 x, T1 y)
{
    return x > y ? x : y;
}
 
template <typename T>
T  print_value(T x, T y)
{
    cout <<"x:"<< x << endl ; 
    cout <<"y:"<< y << endl ;
}
 
int add(int x,int y)
{
    return x+y ;
}
int add(int x,int y,int z)
{
    return x+y+z ;
}
string add(string str , string str1 , string str2)
{
    return str+str1+str2 ;
}

运行结果:

      从代码中我们可以学习到,模板的定义方式一般有两种,分别为:template < typename T>  或  template <class T>。有人可能会问一个typename和一个class这里面有什么区别,其实早期的C++并没有typename这个关键字,所以不论是函数模板还是类模板,都使用class的这种定义方式,后面C++完善,于是多出了typename,用来区分定义的是函数模板还是类模板,但本质都是一样的。

      所谓的函数模板,实际上是建立一个通用的函数,其函数的类型和形参的类型不具体指定,用一个虚拟的类型来代表,这个通用的函数就成为函数模板。凡是函数体相同的函数都可以用这个模板来代替,而不必定义多个函数,只需在模板中定义一次就行了,在调用函数的时候系统会根据实参的类型来取代模板中的虚拟类型,从而实现了不同函数的功能。

      如例程所示,定义了check_max和print_value这两个函数模板,但我这里并没有定义相关的类,调用函数的时候也能输出正确的数值,这就说明不管是声明为typename还是class,本质都是一样的,只是我们可以人为进行区分。check_max就是我们定义的模板函数,用来判断大小,而print_value就是用来打印变量的数据,仅此而已。

     相对于函数重载而言,模板具有得天独厚的优势,它不需要重复定义,所以使用起来比函数重载更简洁,但应注意的一点,函数模板只适用于函数的参数个数相同而类型不同,且函数体相同的情况,如果参数的个数不同,则不能用函数模板,这就是函数模板相对于函数重载的缺陷。

     我们再对上面的程序加以修改,我们再定义一个与模板函数check_max名称一模一样的函数名字,实际上就是函数重载了,看看下面这个例子:

#include <iostream>
using namespace std ;
//C++函数模版两种定义方式 
//template < typename T>  或  template <class T>
template <typename T1> 
T1 check_max(T1 x, T1 y);
//C++重载
 int check_max(int x,int y);
 
int main(void)
{
    int x = 33;
    int y = 44;
    long l1 = 333, l2 = 444;
    float f1 = 3.14, f2 = 3.15926;
 
    //系统会优先调用重载函数,而不是模板函数
    cout << "max(x, y) = " << check_max(x, y) << endl;
    //系统会自动识别类型 T1为long类型
    cout << "max(x, y) = " << check_max(l1, l2) << endl;
    //系统会自动识别类型 T1为float类型
    cout << "max(x, y) = " << check_max(f1, f2) << endl;
    cout << "==========================================" << endl ;
    return 0;
}
 
template <typename T1>
T1 check_max(T1 x, T1 y)
{
    cout << "调用模板函数打印" << endl ; 
    return x > y ? x : y;
}
 
int check_max(int x,int y)
{
    cout << "调用重载函数打印" << endl ; 
    return x > y ? x : y ;
}

运行结果:

如例程所示,我们定义了一个重载函数,形参和返回值都为int类型的check_max函数,当我们在main函数里调用这个函数,如果传入为int的形参的时候,此时和模板发生了冲突,调用了重载函数来打印,而不是调用模板。

由此我们得出结论:当模板和重载冲突的时候 ,就优先调用重载。

以上转自:https://blog.csdn.net/morixinguan/article/details/80182219


那么,可以得出以下总结:

//函数模板定义--数据类型做参数
#include<iostream>
using namespace std;

/*
函数模板声明
1.函数模板定义由模板说明和函数定义组成,并且一个模板说明对应一个函数定义
2.模板说明的类属参数必须在函数定义中至少出现一次
3.函数参数表中可以使用类属类型参数,也可以使用一般类型参数
*/

/*
template关键字告诉c++编译器现在要进行泛型编程
typename或者class告诉c++编译器T是一个数据类型,不要进行语法检查
typename和class完全可以互相替换
*/
template<typename T>//也可以写成template<class T>
void myswap(T &a, T &b){
    T c = a;
    a = b;
    b = c;
};
//void Print(T &a,T &b){
//    cout << "a=" << a << "\nb=" << b << endl;
//}
//报错:一个模板说明只能对应一个函数定义,想再定义一个函数,必须再写一个模板声明

template<class T>
void Print(T &a, T &b){
    cout << "a=" << a << "\nb=" << b << endl;
}

//多参数的函数模板
template<typename T1,typename T2>
//这种定义当调用函数时就会报错  MySort(a);
//模板说明的类属参数必须在函数定义中至少出现一次
void MySort(T1 a){
    cout << "aaa" << endl;
}

template<typename T>
void Getnum(T a,int b){
    cout << "a=" << a << ";\nb="<<b << endl;
}

void main(){
    int a=1;
    int b = 2;
    //泛型编程函数的使用方法1---自动类型推导
    myswap(a, b);
    Print(a, b);
    //泛型编程函数的使用方法2---显式具体类型调用
    myswap<int>(a, b);
    Print(a, b);
    //MySort(a);    报错 : error C2783: “void MySort(T1)”: 未能为“T2”推导 模板 参数
    cout << "----------------" << endl;
    Getnum(a, 4);
    system("pause");
}
//函数模板重载
#include<iostream>
using namespace std;

/*
函数模板会进行严格的类型匹配,模板类型不提供隐式类型转化
普通函数能够进行自动类型转换
*/

/*
函数模板重载四大规则
函数模板可以像普通函数一样被重载
C++编译器优先考虑普通函数
如果函数模板可以产生一个更好的匹配,那么选择模板
可以通过空模板实参列表的语法限定编译器只通过模板匹配
*/

template<typename T>
void Test1(T a, T b){
    cout << "执行了模板函数Test1()" << endl;
}

void Test2(int a, int b){
    cout << "执行了Test2()" << endl;
}

void Test1(int a, int b){
    cout << "执行了普通函数Test1()" << endl;
}

void Test3(int a, int b){
    cout << "执行了普通函数Test3()" << endl;
}

void ProtectA(){
    int a = 1;
    int b = 2;
    char c = '3';
    //Test1(a, c);  报错   error C2782: “void Test1(T,T)”: 模板 参数“T”不明确
    /*
    因为 a是int型,c是char型  而函数模板要求两个参数都是T型 就是说两个参数的类型必须一致,
    但是 int和char类型不一致  所以报错
    */
    Test2(a, c);//对于普通函数而言,则可以进行隐式类型转换,所以没有问题
}

void ProtectB(){
    int a=1,b=2;
    char c = '3',d='4';
    Test1(a, b);//这里调用普通函数
    Test1<>(a, b);//这里调用模板函数--规则4
    Test1(c, d);//这里调用模板函数--规则3---假设没有模板函数  仍然会调用普通函数
    Test3(c, d);
}

void main(){
    ProtectB();
    system("pause");
}

以上转自:https://www.cnblogs.com/zhanggaofeng/category/906670.html

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

(转)C++模板函数和重载 的相关文章

  • 调用拷贝构造函数的几种情况(附面试题)

    1 深拷贝和浅拷贝 拷贝构造函数的使用 有时候需要自己定义拷贝构造函数 以避免浅拷贝问题 在什么情况下需要用户自己定义拷贝构造函数 一般情况下 当类中成员有指针变量 类中有动态内存分配时常常需要用户自己定义拷贝构造函数 在什么情况下系统会调
  • 解决“17: 错误:程序中有游离的‘\240’,\302’

    参考链接 https blog csdn net asuphy article details 54602426 执行如下命令即可 sed i s o240 o302 g dy haikang test cpp
  • Vc/MFC中自定义消息及其PostMessage触发使用

    http blog csdn net ztz0223 article details 2058402 http blog csdn net a8082649 article details 7733527 http bbs csdn net
  • std::nth_element bug引起的crash问题

    1 源码 auto less compare const MirroringGroup mg1 const MirroringGroup mg2 gt bool return mg1 usage lt mg2 usage std nth e
  • c/c++入门教程 - 1.基础c/c++ - 1.0 Visual Studio 2019安装环境搭建

    推荐视频课程 https www bilibili com video BV1et411b73Z p 2 已投币三连 b站果然是个学习的网站 本来是想在linux环境下运行QT 于是先学了几个月linux嵌入式驱动开发 后来发现太底层了 与
  • C/C++中浮点数格式学习——以IEEE75432位单精度为例

    这是浮点数的通常表示形式 在IEEE754中 单精度浮点数有如下形式 32位单精度 单精度二进制小数 使用32个比特存储 1 8 23位长 S Exp Fraction 31 30至23偏正值 实际的指数大小 127 22至0位编号 从右边
  • 如何学好C语言的数据结构与算法?

    C语言的数据结构与算法 难就难在链表 学会了链表 可能后面就一点都不难了 书籍推荐 数据结构与算法分析 C语言描述版 要深入学习的话可以选择这本书 因为针对链表的讲解是比较详细的 所以可以很快理解链表 跟着书上一点点实现基本操作 增删改查
  • GDAL多光谱与全色图像融合简单使用

    目录 简述 C 代码 效果对比 GDAL融合效果和原始多光谱波段对比 GDAL融合效果和原始全色波段对比 ARCGIS融合效果与原始全色和多光谱对比 GDAL融合效果与ArcGIS融合效果对比 简述 最近在GDAL的代码中看见了gdalpa
  • vector,list,deque区别

    http blog csdn net renkaihao article details 6803866 vector和built in数组类似 它拥有一段连续的内存空间 并且起始地址不变 因此它能非常好的支持随即存取 即 操作符 但由于它
  • C++中的RTTI

    文章目录 dynamic cast运算符 指针类型的dynamic cast 引用类型的dynamic cast typeid运算符 使用RTTI type info类 参考资料 RTTI Runtime Type Information
  • LeetCode题目笔记——17.19消失的两个数字

    文章目录 题目描述 题目难度 困难 方法一 暴力 代码 代码优化 方法二 数学方法 代码 总结 题目描述 题目直达 题目难度 困难 方法一 暴力 虽然题目说你能在 O N 时间内只用 O 1 的空间找到它们吗 但是也没有限制我们不能用暴力
  • 值得学习与推荐的c/c++框架和函数库

    这几天不上班 翻翻Evernote中记录的一些笔记 刚好有时间把记录的一些好玩链接转载一下 这篇文章里提到的很多库都用过 尤其是图像处理相关库 尤其是opencv及cximage 当时做图像算法时 很多算法就是从上面找来 然后自己修改的 比
  • floor(),ceil()函数

    地板 天花板函数 均包含在math h中 意思分别为 返回不大于形参的最小整数和不小于形参的最大整数 include
  • Trace Function Enter, Exit and Leave

    http developer nokia com community wiki Trace Function Enter Exit and Leave
  • 模板的完全特例化和部分特例化

    介绍 完全特例化就是类型完全明确的版本 而部分特例化指的是 只知道是几个参数的函数而不知道参数的类型 或者是只知道是引用或者是指针类型 而不知道具体是char 还是 int 模板特例化实例1 template
  • C++:指向类的成员的指针

    引 想必接触过C的朋友们对C语言中指针的概念已经有了深入的了解 如果初步进行了解的朋友可以看一下 C语言基础学习笔记 指针展开来讲的基本知识点包括 指针的概念 指针的定义和初始化及简单使用 指针函数和函数指针 有关指针函数和函数指针的内容上
  • visual studio 一直显示正在准备解决方案

    首先重启电脑 无法解决的情况下执行以下步骤 Kill Visual Studio Open Visual Studio without loading a solution Disable AnkhSvn as Source Control
  • 虚函数不能声明为static

    虚函数申明为static报错 class Foo public Foo default static virtual Foo int main Foo foo return 0 main cpp 10 25 error member Foo
  • enable_shared_from_this使用介绍

    文章目录 enable shared from this定义 使用场合 源码实现 注意 enable shared from this定义 定义于头文件 template lt class T gt class enable shared
  • C/C++编程:令人印象深刻的高级技巧案例

    C C 编程语言在软件开发领域有着悠久的历史 由于其高效 灵活和底层访问能力 至今仍然被广泛应用 本文将介绍一些在C C 编程中令人印象深刻的高级技巧 帮助读者提升编程水平 更加高效地使用这两种强大的编程语言 一 指针运算与内存管理 C C

随机推荐

  • springboot使用外置的tomcat,启动的时候没有启动springboot应用

    springboot使用外置的tomcat 启动的时候没有启动springboot应用 虽然可以访问首页 但是点击超链接访问controller却是404错误 前台
  • 恐造成下一个“千年虫”的闰秒,遭科技巨头们联合抵制

    整理 彭慧中 责编 屠敏 出品 CSDN ID CSDNnews 近日 谷歌 Meta 微软和亚马逊四位科技巨头呼吁将闰秒取消 并称闰秒会对网络造成巨大影响 闰秒或将成为下一个类似 千年虫 bug的罪魁祸首 原来 除了闰年与闰月外 还有闰秒
  • Alibaba限流组件——Sentinel核心概念与流量控制

    目录 1 Sentinel介绍 1 1 Sentinel是什么 1 2 组成 1 3 关键概念 2 Sentinel流量控制案例 2 1 引入依赖 2 2 使用Sentinel提供的API实现流量控制 2 2 1 写一个有返回值的接口 2
  • MyBatis 工具学习笔记(基础)

    What s this 是一款优秀的持久层框架 用于简化 JDBC 开发 是 Apache 的一个开源项目 Java EE 三层架构 表现层 业务层 持久层 存储层 持久层 负责将数据保存到数据库的那一层代码 ORM Object Rela
  • Lumen开发:Lumen的异常处理机制

    版权声明 本文为博主原创文章 未经博主允许不得转载 Lumen的核心类Application引用了专门用于异常处理的RegistersExceptionHandlers class Application extends Container
  • 内存段分配方案

    复杂度3 5 机密度3 5 最后更新2021 04 21 每个进程都有自己的有效地址空间 这个地址空间有些段已经预先被分配或占用 共享 有些等待进程自己进行分配 对进程来说 有2个参数4种组合 32位或64位程序 内核态进程或者用户态进程
  • Spring Boot 静态资源处理(六)

    目录 1 Servlet 方式相同 2 Spring MVC 方式 2 1 为静态资源添加版本号 2 1 1 指定版本号 2 1 2 使用 MD5 作为版本号 2 2 gzip 压缩 3 3 chain cache 2 4 省略 webja
  • 【VUE - 工具 - TIFF】01、前端vue+tiffjs预览显示在线tiff图片

    前言 需求 通过其他工具前置切出来 并放在服务器目录下的tiff图片 项目需要在前端预览显示 实现方式 基于vue tiffjs实现 实现 1 实现效果 npm VUE实现 1 安装依赖 npm i tiff js S yarn add t
  • 计算机在多媒体技术中的应用,06多媒体技术在计算机试题中的应用.doc

    06多媒体技术在计算机试题中的应用 第1题 下列关于多媒体技术主要特征的描述 正确的是 A 多媒体信息必须是数字信息 B 计算机主要处理模拟信息 C 模拟数据是多媒体技术的核心 D Flash动画是模拟化数据 答案 A 第2题 存储一张20
  • http协议面试

    1 说一下什么是Http协议 对器客户端和 服务器端之间数据传输的格式规范 格式简称为 超文本传输协议 2 什么是Http协议无状态协议 怎么解决Http协议无状态协议 曾经去某创业公司问到 无状态协议对于事务处理没有记忆能力 缺少状态意味
  • CUDA详解-GPU架构

    每个线程有自己的私有本地内存 Local Memory 而每个线程块有包含共享内存 Shared Memory 可以被线程块中所有线程共享 其生命周期与线程块一致 此外 所有的线程都可以访问全局内存 Global Memory 还可以访问一
  • html图片加载太慢如何解决办法,如何解决CSS JS和图片对网站加载速度的影响

    对于网站加载速度的严格要求一致是seo优化过程中的重点 如何提升网站加载速度 服务器 网站内容元素等都有很大的关系 本篇文章将从CSS JS和图片三个方面进行详细的讲解 1 图片 1 指定图像尺寸 加载图像之前 您的浏览器开始渲染页面 制定
  • Remote Sensing 从投稿到录用

    一 刊物介绍 最新升级版大类分区仍然是二区TOP期刊 这个期刊现在业界褒贬不一 今年影响因子已经上升到4 848 可以作为一区文章被拒之后的首选 研究方向 无线传感器网络的定位与导航 投稿 Remote Sensing Remote Sen
  • RabbitMQ C++客户端 RabbitMQ Client for Windows/Linux 超简单接收发送接口-最近更新2019-09-06

    消息队列设计精要 解耦是消息队列要解决的最本质问题 所谓解耦 简单点讲就是一个事务 只关心核心的流程 而需要依赖其他系统但不那么重要的事情 有通知即可 无需等待结果 如果下游有很多系统关心你的系统发出的通知的时候 果断地使用消息队列吧 掰开
  • Docker 镜像使用

    目录 1 列出镜像列表 2 获取一个新的镜像 3 查找镜像 4 拖取镜像 5 删除镜像 6 创建镜像 a 更新镜像 b 构建镜像 设置镜像标签 当运行容器时 使用的镜像如果在本地中不存在 docker 就会自动从 docker 镜像仓库中下
  • Scala学习(九)---List集合

    文章目录 1 List 1 1 不可变List集合 1 2 可变集合ListBuffer 1 List List集合默认为不可变集合 List集合在实例化的时候 无法通过new关键字进行实例化 只能通过伴生apply方法来对其进行实例化 1
  • Ping操作 ICMP的数据包的分析(基础学习)

    学习链接 https zhuanlan zhihu com p 142665708 https blog csdn net weixin 43742894 article details 115415782 ICMP概述 全称interne
  • 机器学习-贝叶斯网络-笔记

    贝叶斯网络描述 1 贝叶斯网络 Bayesian network 又称信念网络 Belief Network 或有向无环图模型 directedacyclic graphical model 是一种概率图模型是一种模拟人类推理过程中因果关系
  • 内存泄漏分析

    原因 造成内存泄漏的网上很多 单例 handler 内部类持有外部类的对象 广播注册未反注册 静态变量 资源未释放等 工具 MAT 插件 可以直观的观察内存变化情况 dumpsys meminfo packagename 观察视图是否存在泄
  • (转)C++模板函数和重载

    C 模板函数和重载 先来看一个例子 include