避免警告'未参考的正式参数'

bdh*_*har 47 c++ compiler-warnings suppress-warnings

我有一个像这样的超级课:

class Parent
{
public:
    virtual void Function(int param);
};

void Parent::Function(int param)
{
    std::cout << param << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

..和这样的子类:

class Child : public Parent
{
public:
    void Function(int param);
};

void Child::Function(int param)
{
    ;//Do nothing
}
Run Code Online (Sandbox Code Playgroud)

当我编译子类.cpp文件时,我收到此错误

warning C4100: 'param' : unreferenced formal parameter
Run Code Online (Sandbox Code Playgroud)

作为一种惯例,我们曾经将警告视为错误.如何避免上述警告?

谢谢.

CB *_*ley 88

在C++中,您不必提供不使用名称的参数,因此您可以这样做:

void Child::Function(int)
{
    //Do nothing
}
Run Code Online (Sandbox Code Playgroud)

但是,您可能希望通过文档将参数名称保留在头文件中的声明中.空语句(;)也是不必要的.

  • @bdhar:请注意,除非您的默认值重合,否则在层次结构的不同级别提供默认参数是危险的.你可以得到的问题是从两个上下文调用相同的函数可能最终调用具有不同默认值的相同的最终覆盖:`struct base {virtual void f(int i = 0); }; struct derived:base {virtual void f(int i = 5); }; int main(){derived d; base&b = d; df()/*D :: f(5)*/; BF();/*D :: f(0)*/}` (3认同)
  • +1因为现在我终于知道了省略名称的情况. (2认同)

Cha*_*ann 28

我更喜欢使用宏,因为它不仅告诉编译器我的意图,还告诉代码的其他维护者,以后可以搜索它.

不熟悉代码的人(或者我6个月之后)很容易忽略评论参数名称的方法.

然而,这是一个样式问题,在代码生成,性能或稳健性方面,这两种方法都不是"更好"或更优化.对我而言,决定性因素是通过标准化系统告知其他人我的意图.省略参数名称并放入注释也同样有效:

void CFooBar::OnLvnItemchanged(NMHDR *pNMHDR, LRESULT *pResult)
{
    UNREFERENCED_PARAMETER(pNMHDR);
Run Code Online (Sandbox Code Playgroud)

或者:

void CFooBar::OnLvnItemchanged(NMHDR* /* pNMHDR */, LRESULT *pResult)
{
    // Not using: pNMHDR
Run Code Online (Sandbox Code Playgroud)

我会说最糟糕的解决方案是抑制警告信息; 这将影响你的整个文件或项目,你将失去可能你错过了一些东西的知识.至少通过添加宏或注释掉的参数名称,你告诉别人你已经有意识地决定不使用这种说法,它是不是一个错误.

WinNT.h中的Windows SDK UNREFERENCED_PARAMETER()DBG_UNREFERENCED_PARAMETER()和一起定义DBG_UNREFERENCED_LOCAL_VARIABLE().它们都评估相同的东西,但区别在于,当您开始时使用DBG_UNREFERENCED_PARAMETER()并期望在代码更完整时使用该参数.如果您确定永远不会使用该参数,请使用UNREFERENCED_PARAMETER()版本.

Microsoft基础类(MFC)具有类似的约定,具有较短的宏UNUSED()UNUSED_ALWAYS()宏.

选择一种风格并坚持下去.这样,您可以DBG_UNREFERENCED_PARAMETER在代码中搜索" "并找到您希望使用参数的任何实例,但事实并非如此.通过采用一致的风格,并习惯性地使用它,您将在以后更容易为其他人和自己.


R S*_*hko 19

如果要保留参数名称,可以使用的另一种技术是转换为void:

void Child::Function(int param)
{
    (void)param;   //Do nothing
}
Run Code Online (Sandbox Code Playgroud)

  • Qt 的 Q_UNUSED 宏是一个稍微更奇特的版本。 (2认同)

Fra*_*nov 8

正如@Charles Bailey所提到的,您可以跳过参数名称.

但是,在某些情况下,您需要参数名称,因为在调试版本中,您正在调用ASSERT()它,但在零售版本中,它是一个nop.对于那些场景,有一个方便的宏(至少在VC++ :-))UNREFERENCED_PARAMETER(),其定义如下:

#define UNREFERENCED_PARAMETER(x) x
Run Code Online (Sandbox Code Playgroud)

请注意,简单的演员@R Samuel Klatchko发布也有效,但我个人认为如果代码明确表示这是一个未引用的参数而不是简单的无法解释的演员,那么它更具可读性.

  • 隐藏在宏后面是一个好主意(你是对的,它比我的例子更清晰)。也就是说,您可能应该将强制转换添加到宏中,否则您可能会收到警告(在 g++ 4.2.1 上,我收到“警告:语句无效”) (2认同)

mar*_*rsl 8

从 C++17 开始,您还可以使用[[maybe_unused]]以避免此类警告:

class Parent
{
public:
    virtual void Function([[maybe_unused]] int param);
};
Run Code Online (Sandbox Code Playgroud)


Dwa*_*son 5

Pragma的效果也很好,因为很明显您正在使用VS。鉴于未引用的参数在回调接口和派生方法中非常常见,因此此警告具有很高的噪声受益比。甚至使用W4的Microsoft Windows团队也已经厌倦了它的毫无意义(将更适合/ Wall),并简单地添加到了他们的项目中:

#pragma warning(disable: 4100)
Run Code Online (Sandbox Code Playgroud)

如果您只想缓解代码块中的警告,则将其包围在下面:

#pragma warning(push)
#pragma warning(disable: 4100)
void SomeCallbackOrOverride(int x, float y) { }
#pragma warning(pop)
Run Code Online (Sandbox Code Playgroud)

省略参数名称的做法在调试器中具有不利之处,即您无法轻松地通过名称进行检查,也无法将其添加到监视中(如果您有多个未引用的参数,则会感到困惑),并且该方法的特定实现可能不会使用该参数,知道它的值可以帮助您弄清楚您处于进程的哪个阶段,尤其是当您没有整个调用栈时。