如何正确实现接收可变参数函数作为参数的C++函数?
解决C++中接受可变参数函数作为参数的函数实现问题
我来帮你搞定这个问题!你现在的func函数出错,核心是两个问题:一是返回类型不匹配——你声明返回int,却直接返回了一个函数指针;二是你根本没调用传入的可变参数函数,只是把指针返回了,这显然不是你想要的效果。
先看最直接的修正:固定参数调用
如果你只是想让func调用传入的add并传递固定参数,那修改起来很简单:
int func(int (*func_arg)(int, ...)) { // 调用传入的可变参数函数,传递参数:参数数量2,以及两个int值1、2 return func_arg(2, 1, 2); }
这样修改后,main里调用func(add)就能得到3,和add(2,1,2)的结果完全一致,编译器也不会报错了。
更灵活的方案:转发任意可变参数
但上面的写法不够通用,如果想让func能转发任意数量的参数给传入的可变参数函数,就得借助va_list,同时建议给你的可变参数函数写一个va_list版本(就像标准库中printf对应vprintf那样),这样才能方便地转发参数。
完整的可运行代码如下:
#include <iostream> #include <cstdarg> using namespace std; // 先实现va_list版本的加法,作为核心逻辑 int vadd(int args, va_list ap) { int res = 0; for(int i=0; i < args; ++i) res += va_arg(ap, int); return res; } // 原来的可变参数add函数,基于vadd实现 int add(int args, ...) { va_list ap; va_start(ap, args); int res = vadd(args, ap); va_end(ap); return res; } // 通用包装函数:接受va_list版本的函数指针,以及要传递的参数 int func(int (*vfunc_arg)(int, va_list), int arg_count, ...) { va_list ap; va_start(ap, arg_count); // 转发参数给va_list版本的函数 int res = vfunc_arg(arg_count, ap); va_end(ap); return res; } int main() { cout << add(2, 1, 2) << endl; // 输出3 // 调用func,传入vadd和3个参数 cout << func(vadd, 3, 10, 20, 30) << endl; // 输出60 return 0; }
为什么需要va_list版本?
C/C++里没有直接的语法能把一个函数的可变参数直接转发给另一个函数,所以标准做法是给可变参数函数配套一个v前缀的版本,让包装函数可以通过va_list来传递参数,实现灵活的转发。
现代C的替代方案(C11及以上)
如果你的项目使用C++11或更高版本,更推荐用可变参数模板来实现,它比C风格的可变参数更安全、灵活,还不需要手动管理va_list:
#include <iostream> #include <utility> // 用于std::forward using namespace std; // 可变参数模板实现的加法(C++17折叠表达式简化写法) template<typename... Args> int add(Args... args) { return (args + ...); } // 通用包装模板,接受任意函数和参数并转发 template<typename Func, typename... Args> auto func(Func&& f, Args&&... args) -> decltype(f(forward<Args>(args)...)) { return forward<Func>(f)(forward<Args>(args)...); } int main() { cout << add(1, 2) << endl; // 输出3 cout << func(add, 10, 20, 30) << endl; // 输出60 // 甚至可以支持不同类型(只要支持加法) cout << func(add, 1.5, 2.5, 3) << endl; // 输出7.0 return 0; }
这种写法类型检查更严格,还支持不同类型的参数,是现代C++的最佳实践。
内容的提问来源于stack exchange,提问作者Przemek Sulecki
相关产品推荐
相关产品推荐

