C++ 搞砸了:可选参数强制成为必需的

C++ messed up: optional argument forced to be mandatory

我想要一个带有可选参数的函数。但是,VC++ 抛出一个我无法理解的错误。代码简单如下:

#include <iostream>
#include <iomanip>
#include <string>
using namespace std;

void myFunction(string something, int w);

int main()
{
    myFunction("a string");

    int a = 1;
}

void myFunction(string something, int w = 5)
{
    cout << something << " - " << w << endl;
}

它抱怨:

'myFunction': function does not take 1 arguments

然而,如果我将 myFunction() 移动到 main() 之前,它不会给出错误。到底是怎么回事?请帮忙。谢谢。

此错误是因为您在调用函数时有可选变量,但在声明中没有。

这将创建一个包含两个变量的函数:

void myFunction(string something, int w);

但是,这会使第二个变量成为可选的:

void myFunction(string something, int w=5);

您需要使声明具有可选变量。

此外,令我惊讶的是您的编译器没有尝试吐出与重新定义相关的某种错误。 (这甚至可能是一个编译器错误!我将更新对此的研究。 更新: 看起来不像编译器错误,但绝对是一个我很想拥有的功能。即使它是一个错误,它也会与 linker 相关。)

一些术语:这个

void myFunction(string something, int w);

是一个声明。这个

void myFunction(string something, int w) {
    // note the function body
}

通常称为定义。但实际上两者兼而有之,定义声明。为简单起见,我将继续称其为定义。

您的问题是 顺序很重要,特别是您声明、定义和调用函数的顺序。main() 中的调用站点,唯一可见的声明myFunction 接受一个字符串和一个整数,并且没有默认参数。该定义此时不可见,因此它根本没有发挥作用。对于编译器,您似乎试图调用一个不存在的函数。

有两种解决方案:

  1. 将默认参数从定义移至声明。这是常用的方法。在大多数情况下,您在头文件中有声明(包括任何默认参数),在#includes 头文件中有匹配的定义(没有默认参数)。
  2. 删除声明并将定义移到 main() 上方。这是有效的,因为定义也是一个声明。

在这个简单的示例中,两者同样有效。

对于定义,默认参数是无关紧要的。如果你得到 5 并不重要,因为有人在调用站点明确地输入了它,或者编译器是否通过默认参数添加了它。这就是为什么当你有一个单独的声明和定义时,默认参数只是声明所必需的。您可以而且应该将其排除在定义之外。否则你无缘无故得在两个地方维护它。