我怎么能写一个函数,接受可变数量的参数?这可能吗?怎么可能?
当前回答
在c++ 11中,有一种方法可以创建变量参数模板,从而以一种非常优雅且类型安全的方式来使用变量参数函数。Bjarne自己在c++ 11FAQ中给出了一个使用变量参数模板的printf的好例子。
就我个人而言,我认为这是如此优雅,以至于在编译器支持c++ 11变量参数模板之前,我甚至不会为c++中的变量参数函数而烦恼。
其他回答
如果不使用C风格的可变参数(…),就没有标准的c++方法可以做到这一点。
当然,根据上下文,有一些默认参数“看起来”像可变数量的参数:
void myfunc( int i = 0, int j = 1, int k = 2 );
// other code...
myfunc();
myfunc( 2 );
myfunc( 2, 1 );
myfunc( 2, 1, 0 );
这四个函数调用都使用不同数量的参数调用myfunc。如果没有给出参数,则使用默认参数。但是请注意,只能省略尾随参数。没有办法,例如省略i而只给出j。
唯一的方法是使用C样式变量参数,如下所述。请注意,这不是一个推荐的实践,因为它不类型安全且容易出错。
除了可变参数或重载,你可以考虑将参数聚合在std::vector或其他容器中(例如std::map)。就像这样:
template <typename T> void f(std::vector<T> const&);
std::vector<int> my_args;
my_args.push_back(1);
my_args.push_back(2);
f(my_args);
通过这种方式,您将获得类型安全,并且这些可变参数的逻辑含义将是显而易见的。
当然,这种方法可能会有性能问题,但您不必担心,除非您确定无法为此付出代价。它是c++的一种“Pythonic”方法…
可能你想重载或默认参数-用默认参数定义相同的函数:
void doStuff( int a, double termstator = 1.0, bool useFlag = true )
{
// stuff
}
void doStuff( double std_termstator )
{
// assume the user always wants '1' for the a param
return doStuff( 1, std_termstator );
}
这将允许你用四种不同的调用之一来调用该方法:
doStuff( 1 );
doStuff( 2, 2.5 );
doStuff( 1, 1.0, false );
doStuff( 6.72 );
…或者你可以从C中寻找v_args调用约定。
使用可变模板,示例重现console.log,如JavaScript所示:
Console console;
console.log("bunch", "of", "arguments");
console.warn("or some numbers:", 1, 2, 3);
console.error("just a prank", "bro");
文件名,例如js_console.h:
#include <iostream>
#include <utility>
class Console {
protected:
template <typename T>
void log_argument(T t) {
std::cout << t << " ";
}
public:
template <typename... Args>
void log(Args&&... args) {
int dummy[] = { 0, ((void) log_argument(std::forward<Args>(args)),0)... };
cout << endl;
}
template <typename... Args>
void warn(Args&&... args) {
cout << "WARNING: ";
int dummy[] = { 0, ((void) log_argument(std::forward<Args>(args)),0)... };
cout << endl;
}
template <typename... Args>
void error(Args&&... args) {
cout << "ERROR: ";
int dummy[] = { 0, ((void) log_argument(std::forward<Args>(args)),0)... };
cout << endl;
}
};
推荐文章
- 为什么这个结合赋值和相等检查的if语句返回true?
- cplusplus.com给出的错误、误解或坏建议是什么?
- 找出质数最快的算法是什么?
- c++枚举类可以有方法吗?
- 格式化IO函数(*printf / *scanf)中的转换说明符%i和%d之间的区别是什么?
- 将析构函数设为私有有什么用?
- main()中的Return语句vs exit()
- 为什么c#不提供c++风格的'friend'关键字?
- 在函数的签名中添加关键字
- 我如何在Visual Studio中预处理后看到C/ c++源文件?
- 为什么在标准容器中使用std::auto_ptr<>是错误的?
- 用比较double和0
- 保护可执行文件不受逆向工程的影响?
- 在c++中字符串前面的“L”是什么意思?
- 为什么std::map被实现为红黑树?