在开始使用一些VS2005生成的MFC代码时,我注意到它覆盖了一个类似这样的方法:
void OnDraw(CDC* /*pDC*/)
{
...
// TODO: Add your code here
}
当然,一旦我添加了一些东西,我就意识到我需要取消注释pDC形式参数才能进行编译,但我对于如何/为什么C ++函数可以编译(没有警告)感到困惑当形式参数只有一个类型而不是一个名字时:
void foo(int)
{
int x = 3;
}
int main()
{
foo(5);
return 0;
}
这不应该产生至少一个警告(使用-Wall或/ W4)?它似乎没有。我错过了什么吗?有没有这种情况有用,或者只是因为编译器无法区分函数声明(只需要类型)和定义(完全指定)之间的区别,直到处理完行后?
答案 0 :(得分:51)
因为有时您有一个接口所需的参数但该函数不使用它。也许参数不再是必需的,只有在必须使用相同签名的其他函数中才需要(特别是它们可以通过指针调用)或者功能尚未实现。由于这个原因,拥有未使用的参数在生成的或框架代码中特别常见(这可能是MFC生成的代码已注释掉名称的原因)。
至于为什么没有警告 - 我想这是因为这是一个问题是一个主观的事情,其他人(特别是编译器实施者)不认为这是一个问题。一旦你真正去使用参数,如果你忘记取消注释名称,你就会让编译器抱怨,这样只有当你真正需要编译时才会让编译器抱怨(编译器版本的敏捷YAGNI:“You Aren” t Get Neet It“哲学”。
当您发出警告时,通常会出现相反的情况 - 未使用的命名参数会生成警告 - 这也许就是为什么生成的函数将名称注释掉了。
答案 1 :(得分:17)
我见过的最常见的原因是抑制编译器会抛出的未使用的变量警告:
#include <iostream>
void foo(int source)
{
std::cout << "foo()" << std::endl;
}
int main()
{
foo(5);
return 0;
}
gcc说:main.cc:3: warning: unused parameter 'source'
有两种常见的方法可以消除警告:注释变量名称或完全删除它:
void foo(int /*source*/)
{
std::cout << "foo()" << std::endl;
}
与
void foo(int)
{
std::cout << "foo()" << std::endl;
}
我强烈建议评论删除。否则,您的维护程序员必须找出该参数代表的其他方式。
Qt(可能还有其他框架)提供了一个宏来抑制警告而无需评论或删除变量名称:Q_UNUSED(<variable>)
:
void foo(int source)
{
Q_UNUSED(source); // Removed in version 4.2 due to locusts
std::cout << "foo()" << std::endl;
}
这使您可以在函数体中调用未使用该变量,并提供一个很好的位置来记录为什么不使用它。
答案 2 :(得分:5)
C ++ 11 N3337标准草案
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf说它在8.4.1 / 6是合法的 &#34;功能定义&gt;通常&#34;:
注意:无需命名未使用的参数。例如,
void print(int a, int) { std::printf("a = %d\n",a); }
更准确地说,8.4.1 / 1表示函数定义的语法是
function-definition:
attribute-specifier-seqopt decl-specifier-seqopt
declarator virt-specifier-seqopt function-body
然后,如果您遵循语法定义,例如在&#34;附件A语法摘要&#34;下,您将看到名称是可选的。
答案 3 :(得分:2)
它编译,因为语言标准明确说它必须编译。没有其他答案。这是使C ++与C不同的位之一。在C中,函数定义中的参数名必须存在,在C ++中它们是可选的。
我真的很想知道你为什么问你的“为什么”这个问题。你觉得这种行为有什么不自然,不寻常或不合逻辑吗?