【问题标题】:Why is :: (scope) used with empty left-hand operand? [duplicate]为什么 :: (scope) 与空的左操作数一起使用? [复制]
【发布时间】:2012-01-30 13:20:39
【问题描述】:

我已经看过几次了,我一直在摸不着头脑想知道为什么......

例如:(http://www.codeguru.com/forum/showthread.php?t=377394)

void LeftClick ( )
{  
  INPUT    Input={0};
  // left down 
  Input.type      = INPUT_MOUSE;
  Input.mi.dwFlags  = MOUSEEVENTF_LEFTDOWN;
  ::SendInput(1,&Input,sizeof(INPUT));

  // left up
  ::ZeroMemory(&Input,sizeof(INPUT));
  Input.type      = INPUT_MOUSE;
  Input.mi.dwFlags  = MOUSEEVENTF_LEFTUP;
  ::SendInput(1,&Input,sizeof(INPUT));
}

这个例子在没有 ::(范围)操作符的情况下也能工作,那么为什么它们还在那里呢?

【问题讨论】:

  • 如果 // left down 被删除,它也可以工作。那么它为什么会存在呢?为了清楚起见。
  • 假设 OP 是正确的,即使没有 ::,它也能“工作”,那么是的,真的。但我知道还有更多内容,这就是我没有发布答案的原因。
  • 常用在Windows中,MFC类往往有与全局API函数同名的成员函数。使用 :: 告诉我们您确实打算调用 API 函数。
  • 是吗?我从来没有在 Windows 中进行过太多编程。在我看来,另一件事我可以忘记并搞砸一些事情:-)
  • 由于我无法编辑之前对 tenfour 的评论,我的意图是通过添加无用的::,您的代码会变得更加混乱,而不是更加清晰。

标签: c++ scope operator-keyword


【解决方案1】:

这基本上意味着“获取 GLOBAL 范围的函数,而不是当前可见的函数”。

void SendInput() { /* (1) */
}

namespace derp {
    void SendInput() { /* (2) */
    }

    void LeftClick() {
        ...
        ::SendInput(); /* matches (1) */
        SendInput();  /* matches (2) */
    }
}

【讨论】:

  • 在这种情况下(它意味着全局)。它实际上意味着使用“绝对命名空间路径”而不是“相对命名空间路径”。在这种情况下,它恰好是一条短路径,因此在全局命名空间中。
  • @LokiAstari 你能详细说明区别吗?它与将文件称为/path/to/file.txt 而不是./path/to/file.txt 基本相同吗?一个是相对于当前位置,另一个是相对于特定位置? (在本例中为根文件夹)
  • @QPaysTaxes:一个很好的类比。但是您还需要应用 PATH 变量来使模拟效果更好。将在路径中的每个目录中搜索相对路径(而绝对路径不会)。在 C++ 情况下,PATH 由当前位置的每个嵌套范围表示。请参阅gist.github.com/Loki-Astari/bddbdc98e8c8b9da5edc 这使得实际路径容易受到添加到父命名空间中的新代码的影响。
  • 与类一起使用时效果一样吗? class Test : public ::OtherClass
  • 是@Winter(一些字符)
【解决方案2】:

假设您有以下内容:

void bar()
{
}

struct Foo
{
    void bar();
};

如果您想从成员函数Foo::bar 调用全局函数bar,请使用左侧为空的语法:

void Foo::bar()
{
    // Call the global bar function, not recursively call myself
    ::bar();
}

【讨论】:

    【解决方案3】:

    它强制进行绝对名称解析。
    如果没有它,则搜索相对于类/函数命名空间路径的名称解析。

    所以假设 LeftClick() 在命名空间层次结构中:

    namespace Level1
    {
        namespace Level2
        {
            namespace Level3
            {
                LeftClick()
                {
                     ::SendInput();   // Absolute path only. SendInput in global namespace
                     SendInput();     // Relative path (Note resolved at compile time)
                                      //
                                      // Looks for the function here (in this order)
                                      //    ::Level1::Level2::Level3::SendInput()
                                      //    ::Level1::Level2::SendInput()
                                      //    ::Level1::SendInput()
                                      //    ::SendInput()
                }
            }
        }
    }
    

    如果你有一个嵌套的名字会变得更有趣:

    namespace Level1
    {
        namespace Level2
        {
            namespace Level3
            {
                LeftClick()
                {
                     ::Test::Action();  // Absolute Path: Function Action() 
                                        //                in namespace Test 
                                        //                in global namespace
    
                     Test::Action();    // Relative Path: Function Action()
                                        //                in namespace Test
                                        //                in current namespace path.
                                        //
                         // It will Look for Test (in this order)
                         // ::Level1::Level2::Level3::Test
                         // ::Level1::Level2::Test
                         // ::Level1::Test
                         // ::Test
                         //
                         // In the first Test (and only the first) it finds it will 
                         // try and resolve the Action() function. If it is not there
                         // it is a compile time error.
                }
            }
        }
    }
    

    【讨论】:

      【解决方案4】:

      强制符号在全局范围内查找。

      void foo() {} // 1
      
      namespace A
      {
          void foo() {} // 2
      
          void bar()
          {
              foo(); // 2
              ::foo(); // 1
          }
      }
      

      【讨论】:

        【解决方案5】:

        以这种方式使用范围运算符意味着您指的是全局范围。

        为了节省我宝贵的时间和击键次数,请查看scope resolution operator without a scope

        【讨论】:

          【解决方案6】:

          :: 用于直接从对象外部访问对象。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-10-01
            • 1970-01-01
            • 2017-07-03
            • 2019-04-08
            • 1970-01-01
            • 1970-01-01
            • 2016-04-05
            相关资源
            最近更新 更多