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

starytx 2017-04-19 02:26:40
加精
问题描述:
程序中需要不确定个数类型的函数,所以搞了一个变参函数,如下声明
BOOL proc(LPCSTR szFormat,...)
函数功能已实现,测试正常,现在的问题是,人工测试时知道如何传参来调用这个函数,比如proc(L"xxxx")或者proc(L"fdsfds",123,33.78),那如果在程序中有一个参数列表,有不同数量和类型的参数,该如何调用这个函数呢?
...全文
6760 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)

64,639

社区成员

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

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