当前位置: 首页 > news >正文

C++中不定参数函数的实现方法

目录

  • 一.前言
  • 二.代码解析
    • 1.模板方式
      • 第一种写法
      • 第二种写法
    • 2.va_list方式
  • 三.其他

一.前言

C++中实现不定参数函数可以采用多种方法,这篇文章讨论不定参数模板和va_list。

二.代码解析

1.模板方式

C++中采用模板来实现不定参数列表,可以有多种编码的方法,这里提供两种方法。

第一种写法

第一种采用递归的写法。

先看代码。

//demo.h#ifndef DEMO_H
#define DEMO_H#include <iostream>class Demo
{
public:Demo(void) = default;~Demo(void) noexcept = default;template<typename ...Args>void Func(Args... args);protected:private:template<typename T, typename ...Args>void FuncI(T t, Args... args);void FuncI(void);
};template<typename ...Args>
void Demo::Func(Args... args)
{FuncI(args...);
}template<typename T, typename ...Args>
void Demo::FuncI(T t, Args... args)
{std::cout << t << std::endl;FuncI(args...);
}void Demo::FuncI(void)
{std::cout << "null" << std::endl;
}#endif // !DEMO_H
//main.cpp#include "demo.h"int main(int argc, char* argv[])
{Demo demo;demo.Func(10, "str", 'c');return 0;
}

很简单的代码,就是打印所有参数。

然后对代码进行下解析。

1.这个是对外的接口,仅仅用来接收任务。

template<typename ...Args>
void Func(Args... args);

2.这个才是具体业务函数,可以看到这个函数内部会采用递归的方式将不定参数列表进行展开。

template<typename T, typename ...Args>
void FuncI(T t, Args... args);

3.这个函数就是递归出口。

void FuncI(void);

第二种写法

第二种写法借助列表初始化。

先看代码。

//demo.h#ifndef DEMO_H
#define DEMO_H#include <iostream>class Demo
{
public:Demo(void) = default;~Demo(void) noexcept = default;template<typename ...Args>void Func(Args... args);void Func(void);protected:private:template<typename T>int FuncI(T t);
};template<typename ...Args>
void Demo::Func(Args... args)
{int arr[] = { FuncI(args)... };
}void Demo::Func()
{std::cout << "null" << std::endl;
}template<typename T>
int Demo::FuncI(T t)
{std::cout << t << std::endl;return 0;
}#endif // !DEMO_H
//main.cpp#include "demo.h"int main(int argc, char* argv[])
{Demo demo;demo.Func(10, "str", 'c');return 0;
}

代码也是打印所有参数。

然后解析代码。

1.对外接口。

template<typename ...Args>
void Func(Args... args);

2.这个也是对外接口,解决空参问题。

void Func(void);

3.业务实现。

template<typename T>
int FuncI(T t);

2.va_list方式

先看代码。

//demo.h#ifndef DEMO_H
#define DEMO_H#include<iostream>
#include <stdarg.h>class Demo
{
public:Demo(void) = default;~Demo(void) noexcept = default;void Func(const char* format, ...);protected:private:};void Demo::Func(const char* format, ...)
{if (nullptr == format){return;}va_list vaList;va_start(vaList, format);char msg[1024];vsnprintf(msg, 1024, format, vaList);va_end(vaList);std::cout << msg << std::endl;
}#endif // !DEMO_H
//main.cpp#include "demo.h"int main(int argc, char* argv[])
{Demo demo;demo.Func("%d%f%c",10,1.2,'a');return 0;
}

可以看到这个代码和前面两个不一样,这个是对参数进行格式化并打印。为什么不一个个打印呢?

然后解析代码。

1.顾名思义,va_list变量列表。

va_list vaList;

2.可以理解为指定vaList的地址。

va_start(vaList, format);

3.清理vaList。

va_end(vaList);

4.解释一下为什么不一个个打印的问题,这个代码可以一个个的打印,可是有个问题,必须指定参数类型,而且va_arg不知道出口的标志,必须设置出口参数,所以就不适合。

int var = 0;while (0 != (var = va_arg(vaList, int)))
{std::cout << var << std::endl;
}

三.其他

1.sizeof…(args)可以获取当前参数包里参数数量。

2.其实也可以借助tuple来实现。

3.也可以借助initializer_list来实现。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • AI技术在巴黎奥运会中有哪些应用?
  • 汽车免拆诊断案例 | 2012 款大众速腾车发动机偶尔抖动
  • 【R语言速通】1.数据类型
  • 【Spring Boot 3】【Web】ProblemDetail
  • 前端开发学习Docker记录02容器操作
  • 不平衡分类的成本敏感学习
  • cuda,torch,paddle向下兼容
  • MicroNet关键代码解读(Micro-block与Dynamic Shift-Max的实现代码)
  • wordcloud兼figma的词云图片python生成
  • 摄像头的ISP和SOC的GPU有区别吗?
  • 鸿蒙HarmonyOS开发:如何灵活运用服务卡片提升用户体验
  • DMA简述与使用实例
  • [译] RAGFlow 使用说明
  • yield 详解
  • 基于Material Design风格开源的Avalonia UI控件库
  • ES6指北【2】—— 箭头函数
  • Asm.js的简单介绍
  • CAP理论的例子讲解
  •  D - 粉碎叛乱F - 其他起义
  • HashMap剖析之内部结构
  • HTTP中的ETag在移动客户端的应用
  • iOS 系统授权开发
  • JS数组方法汇总
  • linux安装openssl、swoole等扩展的具体步骤
  • PHP变量
  • Service Worker
  • Stream流与Lambda表达式(三) 静态工厂类Collectors
  • vuex 笔记整理
  • 关于for循环的简单归纳
  • 基于 Babel 的 npm 包最小化设置
  • 模型微调
  • 如何优雅地使用 Sublime Text
  • 设计模式 开闭原则
  • 数据库写操作弃用“SELECT ... FOR UPDATE”解决方案
  • 协程
  • 翻译 | The Principles of OOD 面向对象设计原则
  • 关于Kubernetes Dashboard漏洞CVE-2018-18264的修复公告
  • "无招胜有招"nbsp;史上最全的互…
  • #Datawhale X 李宏毅苹果书 AI夏令营#3.13.2局部极小值与鞍点批量和动量
  • (HAL库版)freeRTOS移植STMF103
  • (Redis使用系列) Springboot 实现Redis消息的订阅与分布 四
  • (TipsTricks)用客户端模板精简JavaScript代码
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (二十四)Flask之flask-session组件
  • (三)uboot源码分析
  • (四)【Jmeter】 JMeter的界面布局与组件概述
  • (五)IO流之ByteArrayInput/OutputStream
  • (转)chrome浏览器收藏夹(书签)的导出与导入
  • (转)Scala的“=”符号简介
  • .describe() python_Python-Win32com-Excel
  • .net core 微服务_.NET Core 3.0中用 Code-First 方式创建 gRPC 服务与客户端
  • .NET MAUI学习笔记——2.构建第一个程序_初级篇
  • .NET Standard、.NET Framework 、.NET Core三者的关系与区别?
  • .NET 中 GetHashCode 的哈希值有多大概率会相同(哈希碰撞)
  • .net和jar包windows服务部署