关于如何调用可变参数函数的问题

starytx 2017-04-19 02:26:40
加精
问题描述:
程序中需要不确定个数类型的函数,所以搞了一个变参函数,如下声明
BOOL proc(LPCSTR szFormat,...)
函数功能已实现,测试正常,现在的问题是,人工测试时知道如何传参来调用这个函数,比如proc(L"xxxx")或者proc(L"fdsfds",123,33.78),那如果在程序中有一个参数列表,有不同数量和类型的参数,该如何调用这个函数呢?
...全文
6763 64 打赏 收藏 转发到动态 举报
写回复
用AI写文章
64 条回复
切换为时间正序
请发表友善的回复…
发表回复
zilaishuichina 2018-01-12
  • 打赏
  • 举报
回复
在你的BOOL proc(LPCSTR szFormat,...) 中实现对vector<T>类型的解析, 然后给vector<T>,list<T>, set<T>类型分别对应的格式控制符比如 %vd,%lstd,%setd之类的, 比如%vd表示vector<int>,%vf表示vector<float>,%lstf表示list<float>,%setf表示set<float>, 这样你就可以在 直接调用 proc("%vd", vector<int>(10));
TerryHHl 2018-01-12
  • 打赏
  • 举报
回复
当初在弄默认参数的时候想到这个情况 ... 有这么个东西 三个小数点
toofunny 2017-06-22
  • 打赏
  • 举报
回复
printf就是最好的例子,第一个参数指定后面的参数类型列表。
weixin_37910246 2017-06-18
  • 打赏
  • 举报
回复
引用 4 楼 实娃星哥的回复:
[quote=引用 3 楼 vnvlyp 的回复:] [quote=引用 2 楼 starytx 的回复:] [quote=引用 1 楼 hnwyllmm 的回复:] 看不太懂楼主的意思。 那如果在程序中有一个参数列表,有不同数量和类型的参数,该如何调用这个函数呢? printf(format, ...)不就是有不同数量和类型的参数吗? 参数的数量和类型都是根据第一个参数format中的内容来判断的。
我的意思是:比如现在有一个其他地方传来的参数(可以理解为一个列表)list,list.size()就是参数个数,list[0]...就是各个参数。我如何来调用我这个变参函数呢? if (list.size() ==1) proc("xx",list[0]) else if(list.size()==2) proc("xx" ,list[0],list[1]) 上边这种是行不通的[/quote] 为什么这种行不通? 而且既然你的参数可以放在一个list里面,为什么当初设计函数的时候不直接接受一个list?不是方便得多么。。[/quote]你能列举完所有的情况吗?因为不管如何,调用proc的时候都需要一一列出每一个参数。 至于你问的第二个问题,是这样的,我这个proc是数据库操作类中的一个函数,用来执行某个存储过程,参数不定,所以我做成了变参函数,而传给我参数的是另外一个第三方的库,这个库里的东西不方便引入这个数据库操作类中。[/quote] c++函数重载就可以了,到时候参数类型,压入参数的数量都可以改变
Chandler_Z 2017-05-18
  • 打赏
  • 举报
回复
学习了,感觉很不错
weixin_37810640 2017-05-09
  • 打赏
  • 举报
回复
看看[i]
引用
[/i]
zhujinqiang 2017-05-09
  • 打赏
  • 举报
回复
Java语言的反射确实是神来之笔。
FD_2013 2017-05-09
  • 打赏
  • 举报
回复
引用 9 楼 starytx 的回复:
[quote=引用 7 楼 zhao4zhong1 的回复:] [quote=引用 5 楼 starytx 的回复:] @zhao4zhong1 呼唤赵老师来攻坚
偶用map作为函数参数。[/quote]map里边只能保存同类型的东西啊,现在降低点要求,我就三种数据类型,字符串,整型,浮点。不要告诉我都当字符串来处理啊,那样的话我就没必要搞变参函数了[/quote] 有种东西叫通用类型: boost::any类型,可接收任意类型的变量,或者自定义个通用类型类
zxphxh 2017-05-07
  • 打赏
  • 举报
回复
关注此贴。。。。。
ForestDB 2017-05-05
  • 打赏
  • 举报
回复
没有反射是C++的软肋。
FD_2013 2017-04-28
  • 打赏
  • 举报
回复
http://blog.csdn.net/zhu_0416/article/details/53582719 虽然业务可能不太一样,希望能有启发
FD_2013 2017-04-28
  • 打赏
  • 举报
回复
你还别说,这个问题我还真捣鼓过,我那时的思路应该是这样的: 三个变量,起始变量,中间变量,最终变量 每次截取拼接,并记录位置, 将处理好的数据放到中间变量里,然后中间变量变成起始变量,再循环处理下一个参数
zerozerg2006 2017-04-28
  • 打赏
  • 举报
回复
扫了一遍回复,感觉楼上提到过的json挺靠谱的。 其次,如果你传的只是int,string和浮点,你自己也写到了,使用vector套一个struct就可以 如果你要传一些复杂的类,这么写代码不太好维护吧
zhujinqiang 2017-04-27
  • 打赏
  • 举报
回复
关注了,学习中。
qq_35003152 2017-04-26
  • 打赏
  • 举报
回复
学习了。。。。。。。
www_adintr_com 2017-04-25
  • 打赏
  • 举报
回复
感觉和这个差不多, 是可以实现的: http://bbs.csdn.net/topics/392016143
很土 2017-04-24
  • 打赏
  • 举报
回复
若是要通用去调用函数指针,这必须使用汇编来写,若不是 x64 则可以内嵌汇编,否则需要写一个汇编代码文件 *.asm,而且编译器也必须安装汇编编译器。 你可以试着使用我的KYLib,不管在Windows或Linux下都支持调用不定参数的函数指针。 KYLib下载地址: http://pan.baidu.com/s/1dDu7nvN
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/* 常量及类型定义 */

// 参数类型
enum TKYParamType {ptPointer,          // Pointer
                   ptByte,             // Byte
                   ptWord,             // Word
                   ptLongword,         // Longword
                   ptInteger,          // Integer
                   ptShortint,         // Shortint
                   ptSmallint,         // Smallint
                   ptLongint,          // Longint
                   ptInt64,            // Int64
                   ptBoolean,          // Boolean
                   ptSingle,           // Single
                   ptDouble,           // Double
                   ptCurrency,         // Currency: __int64 类型存储
                   ptStruct};          // Struct: sizeof(Struct) -> RecSize

// 参数项
#pragma pack(push, 1)
typedef struct
{
   char           Type;                // 参数类型 (TKYParamType)
   bool           IsRef;               // 是否引用传递(若为true则IsReal,IsAddr忽略)
   bool           IsReal;              // 是否为浮点数
   bool           IsAddr;              // ptStruct 尺寸不为: 1, 2, 4, 8
   int            RecSize;             // ptStruct 类型尺寸
   union
   {
      __int64     VInt64;              // __int64  类型值
      double      VDouble;             // double   类型值
      float       VSingle;             // float    类型值
      void*       VPointer;            // void*    类型值
      char        Buffer[8];           // 值的缓冲区
   };
} TKYParamItem, *PKYParamItem;
#pragma pack(pop)

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/* 调用函数 */

// 注:
//    1. 若函数无返回值, 则 AResult 传为 NULL
//    2. AFunc 函数指针不允许为空
//    3. 若 ACount != 0 时, AParams 不允许为空

// 调用函数指针
bool CallFunc(void* AFunc, TKYParamItem* AParams,
                           TKYParamItem* AResult, unsigned ACount);
很土 2017-04-24
  • 打赏
  • 举报
回复
// 执行带参数的命令
long TRCCmdObj::ExecByParams(Longword ATimeout, ...) const
{
   // 取参数个数
   long intCount = ParamCount();
   if (intCount > 0)
   {
      // 初始化
      const void* pUnknow;

      // 清除参数
      RCKCmdParamClear(FCmdID);

      // 可变参数初始化
      va_list  arrArgs;
      va_start(arrArgs, ATimeout);

      // 加入参数
      for (long intNo = 0; intNo < intCount; intNo++)
         switch (ParamType(intNo))
         {
         case kdtString:
            RCKCmdParamByStr(FCmdID, intNo, va_arg(arrArgs, const char*), -1);
            break;

         case kdtInteger:
            RCKCmdParamByInt(FCmdID, intNo, va_arg(arrArgs, int));
            break;

         case kdtBoolean:
            RCKCmdParamByBool(FCmdID, intNo, va_arg(arrArgs, bool));
            break;

         case kdtDouble:
            RCKCmdParamByFloat(FCmdID, intNo, va_arg(arrArgs, double));
            break;

         case kdtStruct:
            RCKCmdParamByStruct(FCmdID, intNo, va_arg(arrArgs, void*));
            break;

         case kdtByte:
            RCKCmdParamByInt(FCmdID, intNo, va_arg(arrArgs, Byte));
            break;

         case kdtWord:
            RCKCmdParamByInt(FCmdID, intNo, va_arg(arrArgs, Word));
            break;

         case kdtSmallint:
            RCKCmdParamByInt(FCmdID, intNo, va_arg(arrArgs, Smallint));
            break;

         case kdtInt64:
            RCKCmdParamByInt64(FCmdID, intNo, va_arg(arrArgs, __int64));
            break;

         case kdtDateTime:
            RCKCmdParamByDate(FCmdID, intNo, va_arg(arrArgs, double));
            break;

         case kdtCurrency:
            RCKCmdParamByFloat(FCmdID, intNo, va_arg(arrArgs, double));
            break;

         default:
            pUnknow = va_arg(arrArgs, const void*);
         }

      // 可变参数释放
      va_end(arrArgs);
   }

   // 执行
   return RCKCmdExecute(FCmdID, ATimeout);
}
qq_38430178 2017-04-22
  • 打赏
  • 举报
回复
我觉得我一声不吭声乐理我一会曹格那啊
starytx 2017-04-21
  • 打赏
  • 举报
回复
引用 38 楼 super_admi 的回复:
另外,ENOVIA系统有一个变参的解决方案是这样的: String[] params = new String[] {"param1", "param2", "param3"}; MQLCommand.mqlCommand(context, "print $1 $2 $3", params); 但是,我始终认为你在这里使用变参,纯粹是设计有问题!
改成vector列表了,里边装的struct,struct里是一个枚举+shared_ptr就可以了
加载更多回复(44)
本课程采用了漫画+动手实操+练习讲授Python编程技能。课程简介:第6章 容器类型数据6.1 序列6.1.1 序列的索引操作6.1.2 加与乘操作6.1.3 切片操作6.1.4 成员测试6.2 列表6.2.1 创建列表6.2.2 追加元素6.2.3 插入元素6.2.4 替换元素6.2.5 删除元素6.3 元组6.3.1 创建元组6.3.2 元组拆包6.4 集合6.4.1 创建集合6.4.2 修改集合6.5 字典6.5.1 创建字典6.5.2 修改字典6.5.3 访问字典视图6.6 动动手 —— 遍历字典6.7 练一练第7章 字符串7.1 字符串的表示方式7.1.1 普通字符串7.1.2 原始字符串7.1.3 长字符串7.2 字符串与数字的相互转换7.2.1 将字符串转换为数字7.2.2 将数字转换为字符串7.3 格式化字符串7.3.1 使用占位符7.3.2 格式化控制符7.4 操作字符串7.4.1 字符串查找7.4.2 字符串替换7.4.3 字符串分割7.5 动动手 —— 统计英文文章中单词出现的频率7.6 练一练第8章 函数8.1 定义函数8.2 调用函数8.2.1 使用位置参数调用函数8.2.2 使用关键字参数调用函数8.3 参数的默认值8.4 可变参数8.4.1 基于元组的可变参数( *可变参数)8.4.2 基于字典的可变参数( **可变参数)8.5 函数中变量的作用域8.6 函数类型8.6.1 理解函数类型8.6.2 过滤函数filter()8.6.3 映射函数map()8.7 lambda()函数8.8 动动手 —— 使用更多的lambda()函数8.9 练一练第9章 类与对象9.1 面向对象9.2 定义类9.3 创建对象9.4 类的成员9.4.1 实例变量9.4.2 构造方法9.4.3 实例方法9.4.4 类变量19.5 封装9.5.1 私有变量9.5.2 私有方法9.5.3 使用属性9.6 继承性9.6.1 Python中的继承9.6.2 多继承9.6.3 重写方法9.7 多态性9.7.1 继承与多态9.7.2 鸭子类型测试与多态9.8 练一练第10章 异常处理9.8 练一练10.1 第一个异常 —— 除零异常10.2 捕获异常110.2.1 try-except语句10.2.2 多个except代码块10.2.3 多重异常捕获10.2.4 try-except语句嵌套10.3 使用finally代码块释放资源10.4 自定义异常类10.5 动动手 —— 手动引发异常10.6 练一练

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧