参数列表中间的默认参数是什么意思?

54

我在我们的代码中看到了一个函数声明,它长这样:

void error(char const *msg, bool showKind = true, bool exit);

一开始我认为这是个错误,因为在函数中间使用默认参数是不允许的,但编译器接受了这个声明。有人以前见过这种情况吗?我正在使用GCC4.5。这是GCC的扩展吗?

奇怪的是,如果我将其放入单独的文件中并尝试编译,GCC会拒绝它。我已经仔细检查了所有内容,包括使用的编译器选项。

2个回答

60

如果在函数的第一个声明中,最后一个参数有默认值,那么该代码将有效,就像这样:

//declaration
void error(char const *msg, bool showKind, bool exit = false);

然后在相同的作用域中,您可以通过后续声明来为其他参数(从右侧开始)提供默认值,如下所示:

void error(char const *msg, bool showKind = true, bool exit); //okay

//void error(char const *msg = 0 , bool showKind, bool exit); // error

可以称之为:

error("some error messsage");
error("some error messsage", false);
error("some error messsage", false, true);

在线演示:http://ideone.com/aFpUn

请注意,如果您为第一个参数(从左侧)提供默认值,而未为第二个参数提供默认值,则不会编译(如预期的那样):http://ideone.com/5hj46


§8.3.6/4说:

对于非模板函数,在同一作用域中的函数的后续声明中可以添加默认参数。

标准本身的示例:

void f(int, int);
void f(int, int = 7);

第二个声明添加了默认值!

另请参见§8.3.6/6。


18
没错,但这样仍然会让人感到困惑,因此不太好。 - James Kanze
你说得对。不过,你是在说另一个声明(参数在中间的那个)必须是定义吗? - Johannes Schaub - litb
14
天啊,这是一个可怕的C++缺陷。 - Alex B
7
这显然是邪恶的隐藏种子之一。顺便说一下,在修复这个问题并允许在函数调用时使用类似Python的参数赋值将会很有帮助。 - Klaim

9

答案可能在8.3.6中:

8.3.6 默认参数

6 Except for member functions of class templates, the default arguments in a member function definition that appears outside of the class definition are added to the set of default arguments provided by the member function declaration in the class definition. Default arguments for a member function of a class template shall be specified on the initial declaration of the member function within the class template.

Example:

class C {
void f(int i = 3);
void g(int i, int j = 99);
};
void C::f(int i = 3) // error: default argument already
{ } // specified in class scope
void C::g(int i = 88, int j) // in this translation unit,
{ } // C::g can be called with no argument
阅读完这篇文章后,我发现即使关闭编译器扩展,MSVC10仍然接受以下内容:
void error(char const* msg, bool showKind, bool exit = false);

void error(char const* msg, bool showKind = false, bool exit)
{
    msg;
    showKind;
    exit;
}

int main()
{
    error("hello");
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接