gcc -Wshadow太严格了?

dim*_*mba 16 c++ gcc compilation

在以下示例中:

class A
{
  public:
    int len();
    void setLen(int len) { len_ = len; } // warning at this line
  private:
    int len_;
};
Run Code Online (Sandbox Code Playgroud)

gcc with -Wshadow发出警告:

main.cpp:4: warning: declaration of `len' shadows a member of `this'
Run Code Online (Sandbox Code Playgroud)

函数len和整数len是不同类型的.为什么警告?

更新

我看到"阴影"的含义是广泛的.从形式上看,编译器也完全符合它的含义.

不过恕我直言,这面旗帜并不实用.例如常用的setter/getter成语:

class A {
   void prop(int prop);  // setter
   int prop() const;     // getter

   int prop;
};
Run Code Online (Sandbox Code Playgroud)

如果有一个警告标志不会在这种情况下发出警告会很好,但会在"int a"隐藏"int a"的情况下发出警告.

添加-Wshadow对我的遗留代码发出大量警告,同时我不时发现由"阴影"问题引起的错误.

我不介意它会被称为"-Wmuch_more_practical_and_interesting_shadow"或"-Wfoooooo".

那么,是否有其他 gcc警告标志符合我的描述?

更新2

不仅我认为-Wshadow不知何故没有用的链接文本.我并不孤单:)不太严格的检查可能会更有用.

mMo*_*ntu 20

这似乎是在较新版本的GCC上解决的.

从版本4.8更改日志:

The option -Wshadow no longer warns if a declaration shadows a function declaration,
unless the former declares a function or pointer to function, because this is a common
and valid case in real-world code.
Run Code Online (Sandbox Code Playgroud)

它引用了Linus Torvalds关于这个主题的想法:https://lkml.org/lkml/2006/11/28/253

不幸的是,我目前正在使用的嵌入式系统的最新编译器仍然基于gcc 4.6.

  • 实际上,从GCC 4.8.2开始,-Wshadow的这个问题仍然存在.如果您仔细阅读了这个bugzilla问题:https://gcc.gnu.org/bugzilla/show_bug.cgi?id = 57709,确认_member_函数的名称与函数参数相同,如您的示例所示,仍然生成影子警告.从GCC 4.8开始,只有自由函数才能抑制此错误.看起来我们必须等到GCC 5.0以你期望的方式完成这项工作. (6认同)

Jam*_*lis 16

参数与成员函数具有不同类型的事实不会影响参数隐藏成员函数的事实.

为什么你不期望有关于此的警告呢?

  • @jalf:我会为一个带有-Winteresting标志的编译器付出很多钱,该标志只向我显示了我感兴趣的警告. (28认同)
  • 它可能不是很有趣,但它*是*影子.警告被称为-Wshadow,而非-Winteresting.所以我希望它能在一个名字隐藏另一个名字时发出警告,而不是在@idimba认为代码"有趣"时. (7认同)
  • @idimba:我不同意.函数指针可以存储在变量中.变量也可以为它定义一个`operator()`,因此可以像函数一样调用它. (5认同)

AnT*_*AnT 9

我不明白为什么你只坚持某些特定类型的阴影.阴影是阴影,即使类型不同,即使变量影响函数,它的危险也是相同的,就像你的情况一样.阴影的危险在于代码可能会做出与其作者想要做的不同的事情.

当变量影响函数时,这很容易发生,因为在C++中,两者之间的区别比第一眼看上去要薄得多.

例如,这里的变量会影响函数

struct L { 
  void operator ()(); 
};

struct A {
  void len();

  A(L len) {
    len();
    // Intended to call the member function. Instead got a call to the functor
  }
};
Run Code Online (Sandbox Code Playgroud)

而且我认为非常明显的是,由于阴影,代码可能会做一些作者不打算做的事情.


jal*_*alf 7

它完全符合它在盒子上的说法.它警告你阴影.

setLen函数内部,两个符号在范围内,它们具有相同的名称. len是函数参数的名称,也是函数的名称.

一个阴影对方的名字,所以当你编写引用代码len,你可能不会得到你想要的结果.由于您要求编译器警告您关于彼此的符号阴影,因此这是它警告您的内容.


小智 6

尽管这是一个相当老的问题,但在GCC >= 7中,现在存在三种变体,-Wshadow对程序员的理智产生不同的影响。来自 GCC 9.1.0 的手册页:

  • -Wshadow=global

默认为 -Wshadow。对任何(全局)阴影发出警告。

  • -Wshadow=local

当局部变量遮蔽另一个局部变量或参数时发出警告。此警告由 -Wshadow=global 启用。

  • -Wshadow=compatible-local

当局部变量遮蔽另一个局部变量或参数(其类型与遮蔽变量的类型兼容)时发出警告。在C++中,这里的类型兼容性是指影子变量的类型可以转换为影子变量的类型。创建此标志(除了-Wshadow=local)是基于这样的想法:当一个局部变量遮蔽另一个不兼容类型时,它很可能是故意的,而不是错误或拼写错误,如以下示例所示:

               for (SomeIterator i = SomeObj.begin(); i != SomeObj.end(); ++i)
               {
                 for (int i = 0; i < N; ++i)
                 {
                   ...
                 }
                 ...
               }
Run Code Online (Sandbox Code Playgroud)

i由于上例中的两个变量“ ”具有不兼容的类型,因此仅启用-Wshadow=compatible-local不会发出警告。由于它们的类型不兼容,如果程序员意外地使用其中一种类型代替另一种类型,类型检查将捕获该类型并发出错误或警告。因此,在这种情况下不发出警告(关于阴影)不会导致未检测到的错误。使用此标志-Wshadow=local可能会减少由故意隐藏触发的警告数量。

此警告由 启用-Wshadow=local