功能参数的默认值


130

1。

int Add (int a, int b = 3);
int Add (int a, int b)
{

}

2。

int Add (int a, int b);
int Add (int a, int b = 3)
{

}

两者都起作用;这是标准方法,为什么

Answers:


203

如果将声明放在头文件中,将定义放在单独的.cpp文件中,并将#include头放在其他.cpp文件中,则可以看到不同之处。

具体来说,假设:

int Add(int a, int b);

库文件

int Add(int a, int b = 3) {
   ...
}

测试文件

#include "lib.h"

int main() {
    Add(4);
}

的编译test.cpp将看不到默认参数声明,并且将失败并显示错误。

因此,通常在函数声明中指定默认参数定义:

int Add(int a, int b = 3);

然后b将被定义多次,一次为每个包含的编译单元lib.h,对吗?
httpinterpret

@httpinterpret:从某种意义上说,是的,b对于包含头文件的每个 .cpp文件,默认值一次定义。但这没关系,因为您只有一个Add函数声明。
格雷格·休吉尔

1
@httpinterpret当生成调用方代码时,编译器将通过默认参数添加未指定的参数。这就是为什么默认值必须出现在函数原型中,而不是出现在函数实现中的原因。参数没有定义在变量定义的意义,因为原型没有定义的变量。
哈珀2013年

1
之所以可以编辑此答案,是因为快速解析(仅查看代码,直到“因为这个原因”才开始)使我理解了您的意思相反。
加布里埃尔·德维勒

44

在C ++中,关于默认参数在参数列表中的位置的要求如下:

  1. 给定参数的默认参数必须指定一次。多次指定(即使具有相同的默认值)也是非法的。

  2. 具有默认参数的参数必须在参数列表的末尾形成一个连续的组。

现在,记住这一点,在C ++中,只要不断满足上述要求,就可以将具有默认参数的参数集“从”函数的一个声明扩展到下一个声明。

例如,您可以声明不带默认参数的函数

void foo(int a, int b);

为了在这样的声明之后调用该函数,您必须显式地指定两个参数。

稍后(进一步向下)在同一翻译单元中,您可以再次重新声明它,但是这次使用一个默认参数

void foo(int a, int b = 5);

从这一点开始,您可以仅使用一个显式参数来调用它。

再往下,您可以再次声明它,再添加一个默认参数

void foo(int a = 1, int b);

从现在开始,您可以不带任何显式参数调用它。

完整的示例可能如下所示

void foo(int a, int b);

int main()
{
  foo(2, 3);

  void foo(int a, int b = 5); // redeclare
  foo(8); // OK, calls `foo(8, 5)`

  void foo(int a = 1, int b); // redeclare again
  foo(); // OK, calls `foo(1, 5)`
}

void foo(int a, int b)
{
  // ...
}

至于您问题中的代码,两个变体都是完全有效的,但是它们的含义不同。第一个变量立即为第二个参数声明一个默认参数。第二个变量最初声明您的函数没有默认参数,然后为第二个参数添加一个。

这两个声明的最终效果(即第二个声明之后的代码看到它的方式)完全相同:该函数的第二个参数具有默认参数。但是,如果您设法在第一和第二个声明之间挤压一些代码,则这两个变体的行为将有所不同。在第二个变体中,函数在声明之间没有默认参数,因此您必须显式指定两个参数。


我认为您的代码定义的void foo(int a = 1,int b)不起作用。您需要在一个可选参数之后拥有所有可选参数。这是语法错误(至少在我的系统上使用g ++ 4.5.3)。
Nilesh

@Nilesh:正如我在上面明确指出的(这是本示例的重点),void foo(int a = 1, int b)要使其工作,必须在之后 声明void foo(int a, int b = 5)。是的,它将起作用。不,这不是语法错误。g ++ 4.5.3可以很好地进行编译。
2011年

好的,因此该函数从先前的声明中获取b的值。现在拿东西。谢谢:-)
Nilesh

1
@Nilesh:是的,默认参数声明累积在翻译单元中的所有先前声明中。
2011年

1
我喜欢写没有变量名的函数原型,例如int foo(int)。我发现我可以int foo(int=5)再次写,省去了参数名称。似乎没有人提到过。
Victor Eijkhout

5

第一种方法比第二种方法更可取。

这是因为头文件将显示该参数是可选的,以及其默认值是什么。此外,无论相应的.cpp文件如何实现,这都将确保默认值相同。

在第二种方式中,不能保证第二个参数的默认值。默认值可能会更改,具体取决于相应的.cpp文件的实现方式。


4

必须在函数名称的第一次出现时指定默认参数,通常是在函数原型中。如果由于函数定义也用作原型而省略了函数原型,则应在函数头中指定默认参数。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.