我们为什么要使用" ::"全局函数/对象的运算符?

时间:2014-03-24 20:51:37

标签: c++ syntax

我见过这种用法在各个地方。 C ++程序员经常在全局函数调用之前使用::运算符。

e.g

::glGenBuffers( 1, &id );

这是为什么?为什么不直接使用:

glGenBuffers( 1, &id );

6 个答案:

答案 0 :(得分:4)

避免意外的命名空间冲突。例如,如果您当前的命名空间有glGenBuffers,它会执行与" good"不同的操作。 glGenBuffers :: glGenBuffers您可以指定调用全局命名空间中的{{1}}。

答案 1 :(得分:2)

问题是1)内部作用域中的名称隐藏了外部作用域中的名称; 2)当使用using指令时,函数调用可能不明确。

例如(歧义)

#include <algorithm>

using namespace std;

void swap( int &x, int &y )
{
   int tmp = x;
   x = y;
   y = tmp;
}

int main()
{
   int x = 5, y = 10;

   //swap( x, y ); compiler error: what function to call?

   ::swap( x, y ); // the user defined function is called

   std::swap( x, y ); // the standard function is called.
}

隐藏姓名的另一个例子

#include <iostream>

void f() { std::cout << "::f()\n"; }

namespace MyNamespace
{
   void f() { std::cout << "MyNamespace::f()\n"; }

   void g() { f(); } // calls MyNamespace::f()

   void h() { ::f(); } // calls ::f()
}


int main()
{
   MyNamespace::g();
   MyNamespace::h();
}

答案 2 :(得分:1)

正如您在此处所见C++ Scope Resolution Operator ::

  

::(范围解析)运算符用于限定隐藏名称   你仍然可以使用它们。如果a,您可以使用一元范围运算符   命名空间范围或全局范围名称由显式隐藏   块或类中的同名声明。

答案 3 :(得分:1)

::glGenBuffers强制选择全局命名空间中的方法

void method()
{
    std::cout << "method in global namespace";
}

class Test {
    void method() 
    {
        std::cout << "method in Test class";
    }

    void test()
    {
        method(); // method in Test class
        ::method(); //method in global namespace
    }
}

答案 4 :(得分:1)

通过使用声明或参数相关查找,显式标记范围可以使您避免意外匹配。例如,请考虑以下事项:

namespace foo
{
  class X {};
  void bar(X*, int):
}

// ... much in between ...

foo::X some_object

// ... more in between ...

void bar(X*, long);

int main()
{
  bar(&some_object, 42); // calls foo::bar, because it is a better match
  ::bar(&some_object, 42); // calls ::bar, because it is explicitly told to
}

如果您不知道名称空间bar中有foo,或者some_object的名称空间为foo,则调用{{1}而不是foo::bar可能会让你感到意外。

答案 5 :(得分:0)

范围运算符(::)主要用于访问全局命名空间两次:

a)将全局方法/变量/ typedef(从全局命名空间)导入命名空间:

int fun()
    {
    return 1;
    }

namespace x
    {
    using ::fun; 
    // you cannot do `using fun`, as using requires a namespace after
    // in this case, we are `using` the global namespace
    }

int main()
    {
    std::cout << fun() + x::fun(); // prints 2
    }

修改:这是由一些STL实施完成的,例如:std::size_t

typedef unsigned int size_t;

namespace std
    {
    using ::size_t;
    }

size_t x = 1;
std::size_t y = 2;

b)避免冲突:

# include <algorithm>

using namespace std;

template<class T> inline
    void swap(T &left, T &right)
    {
    T tmp = left;
    left = right;
    right = tmp;
    }

int main()
    {
    int a = 1, b = 2;
    // swap(a, b) - error: which 'swap'?
    std::swap(a, b); // the one in <algorithm>
    ::swap(a, b); // the one i defined
    }
  • 注意:using namespace std;不是推荐的做法。

修改

MSVC编译器提供_CSTD宏(#define _CSTD ::),以便您可以根据需要使用using _CSTD fun;,e.t.c。