【问题标题】:Avoid warning 'Unreferenced Formal Parameter'避免警告“未引用的形式参数”
【发布时间】:2010-06-11 06:19:18
【问题描述】:

我有一个这样的超类:

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

void Parent::Function(int param)
{
    std::cout << param << std::endl;
}

..还有一个像这样的子类:

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

void Child::Function(int param)
{
    ;//Do nothing
}

当我编译子类 .cpp 文件时,我得到了这个错误

warning C4100: 'param' : unreferenced formal parameter

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

谢谢。

【问题讨论】:

标签: c++ compiler-warnings suppress-warnings


【解决方案1】:

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

void Child::Function(int)
{
    //Do nothing
}

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

【讨论】:

  • @Charles..如果函数是内联的,这样做是否合法? class Child : public Parent { public: void Function(int /*param*/ = 0, int param2 = 0) { std::cout &lt;&lt; param2 &lt;&lt; std::endl; } };
  • 你的意思是有一个默认值的无名参数。我不是 100% 确定,但我认为这是合法的。我不知道为什么不这样做。
  • @bdhar:请注意,在层次结构的不同级别提供默认参数是危险的,除非您的默认值一致。您可能会遇到的问题是,从两个上下文调用相同的函数最终可能会调用具有不同默认值的相同最终覆盖器:struct base { virtual void f( int i = 0); }; struct derived : base { virtual void f( int i = 5 ); }; int main() { derived d; base &amp; b = d; d.f() /* D::f(5) */; b.f(); /* D::f(0) */ }
  • +1 因为现在我终于知道了一个可以省略名称的场景。
  • 谢谢,大卫.. 让我处理一下条件 :)
【解决方案2】:

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

不熟悉代码的人(或者6个月后的我)很容易错过注释掉参数名称的方法。

但是,这是一个风格问题,就生成的代码、性能或健壮性而言,这两种方法都不是“更好”或更优化的。对我来说,决定性因素是通过标准化系统将我的意图告知其他人。省略参数名称并添加注释同样有效:

void CFooBar::OnLvnItemchanged(NMHDR *pNMHDR, LRESULT *pResult)
{
    UNREFERENCED_PARAMETER(pNMHDR);

或者:

void CFooBar::OnLvnItemchanged(NMHDR* /* pNMHDR */, LRESULT *pResult)
{
    // Not using: pNMHDR

我会说最糟糕的解决方案是抑制警告信息;这将影响您的整个文件或项目,并且您将失去可能错过某些内容的知识。至少通过添加宏或注释掉参数名称,您已经告诉其他人您已经有意识地决定不使用此参数并且这不是一个错误。

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”并找到您希望使用参数但没有使用的任何实例。通过采用一致的风格并习惯性地使用它,您以后会为他人和您自己提供更轻松的体验。

【讨论】:

  • 注释参数名在我看来绝对是最好的做法,也是最易读的。
  • @DavidKirby 你不能使用注释掉的名字,如果你有 ifdef 在函数内部,根据定义使用或不使用参数。
  • 注释掉的参数应该是 NMHDR* /* pNMHDR / 不是 NMHDR / pNMHDR */ 如上,这是一个改变函数签名的错误。更一般地说,不要在类型和星号之间放置空格:NMHDR pNMHDR
【解决方案3】:

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

void Child::Function(int param)
{
    (void)param;   //Do nothing
}

【讨论】:

  • 对于像 int 这样的内置类型没问题,但是如果参数是对不完整类型的引用,则将其强制转换为 void 需要在没有此类的情况下查看类型的完整定义需求可能以前就存在过。
  • 这是 C 语言的解决方案,非常有用。
  • Qt 的 Q_UNUSED 宏是一个稍微花哨的版本。
【解决方案4】:

正如@Charles Bailey 所说,您可以跳过参数名称。

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

#define UNREFERENCED_PARAMETER(x) x

请注意,@R Samuel Klatchko 发布的简单演员表也有效,但我个人认为,如果代码明确表明这是一个未引用的参数,而不是像这样的简单未解释演员表,它更易读。

【讨论】:

  • 隐藏在宏后面是个好主意(你说得对,它比我的例子更清楚)。也就是说,您可能应该将强制转换添加到您的宏中,否则您可能会收到警告(在 g++ 4.2.1 上,我收到 warning: statement has no effect
  • 您可以使用 (void)param 为非调试构建定义 ASSERT(param)。您的 UNREFERENCED_PARAMETER 表明根本没有被引用。但是可以引用 -- 在 ASSERT 中。
【解决方案5】:

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

#pragma warning(disable: 4100)

如果您只想减轻一段代码的警告,请将其包围:

#pragma warning(push)
#pragma warning(disable: 4100)
void SomeCallbackOrOverride(int x, float y) { }
#pragma warning(pop)

省略参数名称的做法在调试器中有一个缺点,即您无法轻松地按名称检查或将其添加到监视中(如果您有多个未引用的参数,则会感到困惑),而特定的实现的方法可能不使用参数,知道它的值可以帮助您确定您处于进程的哪个阶段,尤其是当您没有整个调用堆栈时。

【讨论】:

    【解决方案6】:

    我会使用宏来抑制未引用的形参警告:

    #define UNUSED( x ) ( &reinterpret_cast< const int& >( x ) )
    

    这样有以下优点:

    • 与 #define UNUSED( x ) ( void )x 不同,它不需要在以前可能不存在此类需要的情况下查看参数类型的完整定义。
    • 与 #define UNUSED( x ) &x 不同,它可以安全地与类型重载一元 & 运算符的参数一起使用。

    【讨论】:

      【解决方案7】:

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

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

      【讨论】:

        【解决方案8】:

        如果只是在评论中添加参考:

        void Child::Function(int param)
        {
            param; //silence unreferenced warning
        }
        

        这里也有人建议:https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-4-c4100?view=vs-2019

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-02-27
          • 2010-09-10
          • 2018-10-20
          • 1970-01-01
          • 2012-02-15
          • 1970-01-01
          • 1970-01-01
          • 2019-04-16
          相关资源
          最近更新 更多