为什么没有参数标识符的函数在C ++中有效?

时间:2017-11-10 20:22:15

标签: c++ function syntax

给定C ++中的函数,其参数只是类型且没有标识符,

 void foo1(int, int, int){cout << "called foo1";}

我可以这样称呼它:

int main()
{
    foo1(10, 10, 10);
}

为什么这是C ++中的有效构造?这只是C ++的特质,还是这种声明实际上有一些目的?我们可以实际访问以某种方式传递的参数吗? (这种方法声明在Java中不起作用。)

5 个答案:

答案 0 :(得分:41)

考虑一种情况,您需要提供符合以下原型的功能

void dostuff(int x, int y, int z);

并说您在2D空间中操作,并且不在您的实现中使用z。你可以

void dostuff(int x, int y, int z)
{
    // use x and y
}

并忽略z,但编译器可能会发现您已定义但未使用z,并警告您可能会犯错误。相反,你可以

void dostuff(int x, int y, int )
{
    // use x and y
}

并忽略z的定义。编译器将接受并静默地丢弃第三个参数,因为它知道你不想要它。

你不想因为像这样的错误而单纯关闭警告

void dostuff(int x, int y, int z)
{
    for (int z = 0; z < MAX; z++)
    {
        // use x and y and z, the local z. 
    }
}

如果命名不佳的循环索引会影响参数z。调用者的输入现在被忽略,这可能会产生不良后果。标记1眼球通常很难发现此错误,特别是如果本地z被埋在复杂函数深处的某个地方。

编译器可以随时挑选代码中的可能错误。这对你来说意味着更少的工作。

答案 1 :(得分:16)

这样的宣言
void foo1(int, int, int){cout << "called foo1";}

在声明中清楚地表明,您希望满足您的功能要求 - 例如覆盖基类或接口中的特定函数,例如,可以在那里宣布为

virtual void foo1(int something, int another, int andAnother) = 0;

但您不打算使用移交给您的参数。

另一个例子是,如果你想把这个功能移交给,例如一个函数指向一个带有三个int参数的void函数的函数指针。

void giveMeFoo( void (*fn)(int, int, int) ) { ... }

此外,如果声明参数,则更高的警告级别会发出警告,但不会在函数体中进行评估。您可以通过保留参数名称来避免这种情况。

然后,在函数体中确实无法访问没有名称的参数 - 故意。 user4581301很好地描述了,为什么。

由于上述用法,允许声明一个没有参数名称的独立函数,如上例所示,但在大多数情况下显然没有意义。它确实有意义的一个例子是在评论部分。没有参数名称的独立函数的另一个例子可能是,如果您正在编写库并且想要保持向后兼容性(您的库函数不再需要参数,但您不想破坏公共头声明)或者您想保留一个参数以备将来使用。

答案 2 :(得分:11)

即可。它在C ++中是合法的。

C ++ 11 n3337标准8.4.1(p6)函数定义:

  

注意:无需命名未使用的参数。例如,

void print(int a, int) {
    std::printf("a = %d\n", a);
}

C ++ 14标准:

  

[8.3.5.11] 可以选择提供标识符作为参数名称;如果存在于函数定义中,则为参数命名   (有时称为“形式论证”)。 [注:特别是参数   名称在函数定义和名称中也是可选的   不同声明中的参数和函数的定义   不必相同。]

答案 3 :(得分:8)

这是合法的,如果您想知道原因:

  

通常,未命名的参数来自简化代码或   从提前规划扩展。在这两种情况下,离开   虽然未使用,但适当的参数可确保调用者不会   受到变化的影响。

摘录自:Bjarne Stroustrup。 “C ++编程语言,第四版。”

答案 4 :(得分:1)

这个想法是你可能想要改变这个功能 定义以后使用占位符,而不更改所有 调用函数的代码。

函数声明中的参数可以不用声明 身份标识。当这些与默认参数一起使用时,它可以看起来 有点好笑。你最终可以:

void f(int x, int = 0, float = 1.1);

在C ++中,您不需要在函数定义中使用标识符:

void f(int x, int, float flt) { /* ... */ }

在函数体中,可以引用x和flt,但不能引用 中间论点,因为它没有名字。函数调用仍然必须 但是,为占位符提供值:f(1)f(1,2,3.0)。这个 语法允许您将参数作为占位符放入 使用它。