C/C++ - 函数进阶(C++)

目录

默认参数

函数重载

内联函数

函数模板

递归函数

回调函数


默认参数

  • 定义

    • 默认参数是在函数声明或定义中指定的具有默认值的函数参数。
    • 默认参数允许在调用函数时可以省略对应的参数,使用默认值进行替代。
  • 使用

    • 默认参数可以用于全局函数和成员函数。
    • 默认参数的定义通常放在函数声明中,但也可以在函数定义中进行。
    • 默认参数只能在参数列表的末尾进行定义,即后续参数必须都有默认值。
  • 解析

    • 当调用带有默认参数的函数时,如果省略了对应的参数,编译器会使用默认值进行替代。
    • 如果调用函数时提供了实际参数,则实际参数将覆盖默认参数的值。
    • 默认参数的值在编译时确定,对于每个函数调用都是固定的。
  • 特性

    • 默认参数的定义只能在函数声明或定义中进行一次。
    • 默认参数通常在函数的原型或头文件中进行定义,以便在多个文件中共享。
    • 默认参数的值可以是常量、全局变量、静态变量或其他常量表达式。
  • 示例

    #include <iostream>
    #include <Windows.h>
    
    int Fun1(int a, int b = 10/*默认参数*/)
    {
    	return a + b;
    }
    
    //默认参数只能在参数列表的末尾进行定义
    //int Fun2(int a, int b = 1, int c)
    //{
    //	return a + b + c;
    //}
    
    int Fun2(int a, int b = 1, int c = 2)
    {
    	return a + b + c;
    }
    
    bool ExitProcess(int nPid = 0)
    {
    	//TODO
    	//结束进程
    	//参数PID == 0 则结束自身 否则结束指定进程
    	if (nPid == 0)
    	{
    		std::cout << "结束自身进程" << std::endl;
    		return 1;
    	}
    	std::cout << "结束指定进程" << std::endl;
    }
    
    int main()
    {
    	std::cout << Fun1(1) << std::endl;
    	std::cout << Fun2(1) << std::endl;
    	std::cout << Fun2(1 , 2) << std::endl;
    	std::cout << Fun2(1 , 2 , 3) << std::endl;
    
    	ExitProcess();
    	ExitProcess(123);
    
    	return 0;
    }
    

函数重载

  • 定义

    • 函数重载是指在同一作用域内,根据函数的参数类型、参数个数或参数顺序,定义多个具有相同名称但不同特征的函数。
    • 通过函数重载,可以使用相同的函数名来表示具有不同行为和功能的函数。
  • 使用

    • 函数重载允许使用相同的函数名,但函数特征必须不同,包括参数类型、参数个数或参数顺序。
    • 函数重载可以应用于全局函数和成员函数。
  • 解析

    • 在调用重载函数时,编译器会根据函数调用的参数类型、参数个数或参数顺序,选择最匹配的函数进行调用。
    • 编译器会进行函数匹配,优先选择完全匹配的重载函数。如果没有完全匹配的函数,编译器会尝试进行隐式类型转换,选择最匹配的函数。
    • 如果有多个重载函数都能匹配调用,编译器会产生二义性错误。
  • 特性

    • 仅根据函数的返回类型不可以进行函数重载。
    • 函数重载不能仅通过函数的 const 修饰符进行区分。
    • 函数重载不能仅通过函数的参数名进行区分,参数名对于函数重载没有影响。
    • 函数重载中的默认参数可以用于区分不同的函数。
  • 示例

    #include <iostream>
    
    //全局作用域
    int Add(int a, int b) //整数类型
    {
    	return a + b;
    }
    
    float Add(float f1, float f2) //小数类型
    {
    	return f1 + f2;
    }
    
    //无法仅通过返回值类型完成重载
    //int Fun()
    //{
    //
    //}
    //
    //float Fun()
    //{
    //
    //}
    
    //函数重载不能仅通过函数的 const 修饰符进行区分
    //int Fun(int a)
    //{
    //
    //}
    //
    //int Fun(const int a)
    //{
    //
    //}
    
    //函数重载不能仅通过函数的参数名进行区分,参数名对于函数重载没有影响
    //int Fun(int a)
    //{
    //
    //}
    //
    //int Fun(int b)
    //{
    //
    //}
    
    int main()
    {
    	//函数重载
    	//个数不同
    	//类型不同
    	//数量不同
    	Add(1.0f, 2.0f);
    	Add(1, 1);
    
    
    	return 0;
    }
    

内联函数

  • 定义

    • 内联函数是在函数声明或定义中使用 inline​​ 关键字标记的函数。
    • 内联函数的主要目的是减少函数调用的开销,将函数的代码插入到函数调用的地方。
  • 使用

    • 内联函数适用于较短的函数代码,通常在头文件中定义。
    • 内联函数可以用于全局函数和成员函数。
  • 解析

    • 当调用内联函数时,编译器会将函数的代码直接插入到函数调用的地方,而不是生成函数调用的指令。
    • 内联函数的展开是在编译时完成的,而不是在运行时。
    • 内联函数的展开可能导致代码膨胀,因此适用于较短的函数代码。
  • 特性

    • 内联函数的定义通常放在头文件中,以便在多个文件中共享。
    • 内联函数只是对编译器的建议,编译器可以选择忽略内联函数的建议,特别是对于较大的函数或复杂的函数。
    • 内联函数不能递归调用自身。
    • 内联函数不能包含复杂的控制流结构,如循环和递归。
  • 示例

    #include <iostream>
    
    //宏函数
    #define ADD(X,Y) ((X) + (Y))
    
    //普通函数
    int Add1(int a, int b)
    {
    	return a + b;
    }
    
    //内联函数
    inline int Add2(int a, int b)
    {
    	return a + b;
    }
    
    int main()
    {
    	//mov         dword ptr [a],3
    	int a = ADD(1, 2);
    
    	//push        2
    	//push        1
    	//call        Add1(0401276h)
    	//add         esp, 8
    	//mov         dword ptr[b], eax
    	int b = Add1(1, 2);
    
    	//mov         eax, 1
    	//add         eax, 2
    	//mov         dword ptr[c], eax
    	int c = Add2(1, 2);
    
    	return 0;
    }
    

函数模板

  • 定义

    • 函数模板是一种通用函数的定义,可以用于处理多种类型的参数。
    • 函数模板通过在函数声明或定义中使用占位符类型参数来表示参数类型。
  • 使用

    • 函数模板可以用于全局函数和成员函数。
    • 函数模板的定义通常放在头文件中,以便在多个文件中共享。
  • 解析

    • 函数模板可以进行特化,以处理特定类型的参数或特定情况。
    • 显式特化(Explicit Specialization)是指为特定的类型提供具体的函数实现。
    • 隐式特化(Implicit Specialization)是指编译器根据参数类型自动选择最匹配的函数实现。
  • 特性

    • 当调用函数模板时,编译器根据参数类型推断出函数模板的实际类型,并生成对应的函数实例。
    • 函数模板的实例化是在编译时完成的。
    • 函数模板可以根据需要进行多次实例化,以适应不同的参数类型。
    • 函数模板的定义通常放在头文件中,以便在多个文件中共享。
    • 函数模板的定义通常包含在类定义或命名空间中。
    • 函数模板可以有多个类型参数,以适应多个参数类型的情况。
  • 示例

    #include <iostream>
    
    template <typename CC>
    CC Compare(CC a, CC b)
    {
    	return a > b ? a : b;
    }
    
    template <>
    const char* Compare<const char*>(const char* str1, const char* str2)
    {
    	return strlen(str1) > strlen(str2) ? str1 : str2;
    }
    
    int main()
    {
    	std::cout << Compare(1, 2) << std::endl;
    	std::cout << Compare(3, 2) << std::endl;
    	std::cout << Compare(3.15f, 2.5f) << std::endl;
    	std::cout << Compare("CCCCCCCC", "Heeloooooooo") << std::endl;
    
    	return 0;
    }
    

递归函数

  • 定义

    • 递归函数是在函数的定义中调用自身的函数。
    • 递归函数通常用于解决可以通过将问题分解为更小的子问题来解决的问题。
  • 使用

    • 递归函数可以用于全局函数和成员函数。
    • 递归函数的定义通常放在函数声明的后面。
  • 终止

    • 递归函数必须具有基本情况,也称为终止条件(Termination Condition)。
    • 终止条件定义了递归函数何时结束递归调用。
  • 递归

    • 递归函数在其定义中调用自身,通常使用不同的参数值。
    • 递归调用会将问题分解为更小的子问题,并逐步解决这些子问题。
  • 特性

    • 递归函数必须具有正确的终止条件,以避免无限递归。
    • 递归函数的性能可能较低,因为每次递归调用都需要保存函数的状态。
    • 递归函数的栈帧可能会占用大量的内存空间,特别是在递归层数较深时。
  • 示例

    #include <iostream>
    
    int Sum(int n) 
    {
    	if (n == 0)return 0;
    	return n + Sum(n - 1);
    }
    
    int main()
    {
    	int sum = 0;
    	for (int i = 0; i <= 10; i++)
    	{
    		sum += i;
    	}
    
    	Sum(10);
    
    	return 0;
    }
    

回调函数

  • 函数指针

    • 函数指针是指向函数的指针变量。
    • 函数指针可以用于回调函数,即在程序执行期间将函数作为参数传递给其他函数,并在需要时调用该函数。
  • 函数回调

    • 函数回调可以通过将函数指针、函数对象或Lambda表达式作为参数传递给其他函数来实现。
    • 回调函数可以在需要时被调用,可以传递参数并返回结果。
  • 示例

    #include <iostream>
    
    // 示例1: 函数指针的函数回调
    void PrintMessage(const char* message) 
    {
        std::cout << "Message: " << message << std::endl;
    }
    
    void PerformCallback(void (*callback)(const char*)) 
    {
        callback("Hello, world!");
    }
    
    // 示例2: 函数对象的函数回调
    struct Callback 
    {
        void operator()(const char* message) 
    {
            std::cout << "Message: " << message << std::endl;
        }
    };
    
    void PerformCallback(const Callback& callback) 
    {
        callback("Hello, world!");
    }
    
    // 示例3: Lambda表达式的函数回调
    void PerformCallback(const std::function<void(const char*)>& callback) 
    {
        callback("Hello, world!");
    }
    
    int main() {
        // 示例1: 函数指针的函数回调
        PerformCallback(PrintMessage);
    
        // 示例2: 函数对象的函数回调
        Callback callbackObj;
        PerformCallback(callbackObj);
    
        // 示例3: Lambda表达式的函数回调
        PerformCallback([](const char* message) 
    	{
            std::cout << "Message: " << message << std::endl;
        });
    
        return 0;
    }
    

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RDMA技术赋能:构建高速网络基础设施,加速大型模型高效训练

深入剖析RDMA在高速网络环境中的应用价值与实现方式 远程直接内存访问&#xff08;RDMA&#xff09;作为超高速网络内存访问技术的领军者&#xff0c;彻底颠覆了传统程序对远程计算节点内存资源的访问模式。其卓越性能的核心在于巧妙地绕过了操作系统内核层&#xff08;如套接…

npm v10.4.0 is known not to run on Node.js v14.21.3

问题起因 vue项目在打包的时候突然报如下错误&#xff0c;项目原来打包的时候是没问题的。 request to https://registry.npm.taobao.org/acorn failed, reason: certificate然后找到了一篇帖子&#xff0c;淘宝npm镜像地址https证书到期了&#xff0c;发现确实是这个问题。在…

Redis客户端之Redisson(三)Redisson分布式锁

一、背景&#xff1a; 高效的分布式锁设计应该包含以下几个要点&#xff1a; 1、互斥&#xff1a; 在分布式高并发的条件下&#xff0c;我们最需要保证&#xff0c;同一时刻只能有一个线程获得锁&#xff0c;这是最基本的一点 2、防止死锁&#xff1a; 在分布式高并发的条…

骑砍战团MOD开发(41)-LOD渲染技术

一.LOD技术 LOD技术&#xff0c;即Level Of Details&#xff0c;是一种在3D图形渲染中常用的技术&#xff0c;主要用于优化渲染性能。 通过在建模时添加LOD模型(低模模型,面数较少),游戏引擎通过计算模型的远近和光照等情况选择性加载原模型(高模)/LOD模型(低模),实现游戏…

D3485——+5V工作电压,内置失效保护电路等功能高达10Mbps的传输速率,可应用在智能电表,安防监控等产品上

D3485 是一款 5V 供电、半双工的 RS-485 收发器&#xff0c;芯片内部包含一路驱动器和 一路接收器。D3485 使用限摆率驱动器&#xff0c;能显著减小 EMI 和由于不恰当的终端匹 配电缆所引起的反射&#xff0c;并实现高达10Mbps 的无差错数据传输。 D3485 内置失效保 护电路&…

小红树上染色

记忆化深搜 #include <iostream> #include <string> #include <stack> #include <vector> #include <queue> #include <deque> #include <set> #include <map> #include <unordered_map> #include <unordered_set&g…

详解OpenHarmony各部分文件在XR806上的编译顺序

大家好&#xff0c;今天我们来谈一谈编程时一个很有趣的话题——编译顺序。我知道&#xff0c;一提到编译可能大家会感到有点儿头疼&#xff0c;但请放心&#xff0c;我不会让大家头疼的。我们要明白&#xff0c;在开始写代码之前&#xff0c;了解整个程序的编译路径是十分有必…

【MySQL】补充和navicat的一些简单使用

文章目录 前言在这里插入图片描述 事情起因因为这个articlecount的c是小写了&#xff0c;我想改成大写 一、修改二、navicat的使用步骤1.连接2.建库&#xff0c;建表 三.填写数据总结 前言 事情起因因为这个articlecount的c是小写了&#xff0c;我想改成大写 提示&#xff1a;…

C语言数据结构(4)——线性表其三(双向链表)

欢迎来到博主的专栏——C语言数据结构 博主ID&#xff1a;代码小豪 文章目录 链表的种类头结点循环链表双向链表带头双向循环链表带头双向循环链表的定义与初始化 空链表尾插法打印双向链表头插法查找指定数据项的节点在指定位置之后插入节点指定位置的删除双向链表的销毁 顺序…

东北老铁带你总结《Java IO 模型》

东北老铁带你总结《Java IO 模型》 文章目录 东北老铁带你总结《Java IO 模型》前言I/O何为 I/O?有哪些常见的 IO 模型? Java 中 3 种常见 IO 模型BIO (Blocking I/O)NIO (Non-blocking/New I/O)AIO (Asynchronous I/O) IO 模型这块确实挺难理解的&#xff0c;需要太多计算机…

漏洞原理linux操作系统的SqlMap工具的使用

漏洞原理linux操作系统的SqlMap工具的使用 Linux操作系统基础操作链接: 1024一篇通俗易懂的liunx命令操作总结(第十课)-CSDN博客 kali的IP地址:192.168.56.1 实操 # kali中使用sqlmap http://192.168.56.1/ sqlmap -u http://192.168.56.1/news/show.php?id46 sqlmap -u …

IT界含金量高的证书,除了软考证书,还有这15种

文章目录 计算机技术与软件专业技术资格考试全国计算机信息高新技术考试思科认证微软认证&#xff1a;华为认证IBM认证国家信息安全水平考试注册信息安全专业人员注册信息安全渗透测试工程师项目管理专业人士资格认证Red Hat认证CompTIA 认证CISSP认证Oracle认证Sun认证AWS认证…

sqli.labs靶场(8-17关)

8、第八关&#xff08;布尔盲注&#xff09; id1显示You are in...........&#xff0c;id1单引号不显示&#xff0c;id1 --显示正常 这个应该是单引号闭合&#xff0c;接下来就和第七关差不多上脚本 爆库名长度&#xff1a;id1%27%20and%20length(database()){i}%20-- 爆库…

xcode安装visionOS Simulator模拟器报错解决方法手动安装方法

手动安装方法&#xff1a; 手动下载visionOS Simulator模拟器地址&#xff1a; https://developer.apple.com/download/all/ 选择 Xcode 版本 sudo xcode-select -s /Applications/Xcode.app # 用 Xcode-beta 的话是&#xff1a; # xcode-select -s /Applications/Xcode-beta…

如何将DDD应用到基础设施设计?

前段时间在面试的时候&#xff0c;面试官问到&#xff1a;你是如何将DDD&#xff08;领域驱动设计&#xff09;应用到基础设施的&#xff1f; 我很惊讶&#xff0c;终于有人问我这个问题了。 在过去从事基础设施&#xff08;DevOps、SRE、运维&#xff09;的5年里&#xff0c;我…

爬虫基础-前端基础

Html是骨骼、css是皮肤、js是肌肉&#xff0c;三者之间的关系可以简单理解为m(html)-v(css)-c(js) 浏览器的加载过程 构建dom树 子资源加载-加载外部的css、图片、js等外部资源 样式渲染-css执行 DOM树 ajax、json、xml AJAX 是一种在无需重新加载整个网页的情况下&#xf…

基于springboot校园台球厅人员与设备管理系统源码和论文

在Internet高速发展的今天&#xff0c;我们生活的各个领域都涉及到计算机的应用&#xff0c;其中包括校园台球厅人员与设备管理系统的网络应用&#xff0c;在外国管理系统已经是很普遍的方式&#xff0c;不过国内的管理网站可能还处于起步阶段。校园台球厅人员与设备管理系统具…

Unity中使用Ultraleap的InteractionButton组件

本节在上一节基础上进行&#xff0c;上一小结参考如下&#xff1a; Unity中创建Ultraleap 3Di交互项目 本节工程文件如下&#xff1a; Unity中使用Ultraleap的InteractionButton组件 本节结构有所更改&#xff0c;主要是参考官方示例结构进行重新调整&#xff0c;和上一小节相…

STM32与FPGA实现以太网功能--ping

方案&#xff1a; ①stm32与88E6320的一个RMII接口连接&#xff0c;实现网管功能。 ②FPGA与88E6320的另一个RMII接口连接&#xff0c;使用UDP实现业务数据传输。 ③stm32与FPGA中MAC地址不同&#xff0c;但是IP使用相同 结果&#xff1a; 1、在局域网点对点通信正常。 2…

【C语言/数据结构】排序(快速排序及多种优化|递归及非递归版本)

&#x1f308;个人主页&#xff1a;秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343&#x1f525; 系列专栏&#xff1a;《数据结构》https://blog.csdn.net/qinjh_/category_12536791.html?spm1001.2014.3001.5482 ​​​​ 目录 交换排序 快速排序 hoare版代…