C++ 我们为什么要使用“:”&引用;全局函数/对象上的运算符?

C++ 我们为什么要使用“:”&引用;全局函数/对象上的运算符?,c++,syntax,C++,Syntax,我在很多地方都见过这种方法。C++程序员通常会使用::在全局函数调用之前,操作员正确。 e、 g 为什么会这样?为什么不直接使用: glGenBuffers( 1, &id ); 以避免意外的命名空间冲突。例如,如果您当前的命名空间将具有glGenBuffers,它与使用:的“good”glGenBuffers不同:,您可以指定调用全局命名空间中的glGenBuffers。 ::(范围解析)运算符用于限定隐藏名称,以便 你仍然可以使用它们。如果 命名空间范围或全局范围名称由显式 块或类

我在很多地方都见过这种方法。C++程序员通常会使用::在全局函数调用之前,操作员正确。 e、 g

为什么会这样?为什么不直接使用:

glGenBuffers( 1, &id );

以避免意外的命名空间冲突。例如,如果您当前的命名空间将具有
glGenBuffers
,它与使用
的“good”
glGenBuffers
不同:,您可以指定调用全局命名空间中的
glGenBuffers

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


::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
    }
}
void方法()
{
std::cout问题是1)内部作用域中的名称隐藏外部作用域中的名称,2)使用USE指令时,函数调用可能存在歧义

例如(歧义)

#包括
使用名称空间std;
无效交换(整数和x、整数和y)
{
int tmp=x;
x=y;
y=tmp;
}
int main()
{
int x=5,y=10;
//交换(x,y);编译器错误:调用什么函数?
::swap(x,y);//调用用户定义的函数
std::swap(x,y);//调用标准函数。
}
另一个隐藏姓名的例子

#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();
}
#包括

空f*({STD::CUT

显式标记范围)可以通过使用声明或依赖于参数的查找来避免意外的匹配。例如,考虑以下内容:

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
}
如果您不知道命名空间
foo
中有一个
bar
,或者
某个对象的类型来自命名空间
foo
,那么调用
foo::bar
而不是
::bar
可能会让您大吃一惊。

范围操作符(
)用于在2种情况下访问全局命名空间,主要是:

a) 将全局方法/变量/类型定义(从全局命名空间)导入命名空间:

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
    }
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
    }
#包括
使用名称空间std;
模板内联
无效掉期(T&left、T&right)
{
T tmp=左;
左=右;
右=tmp;
}
int main()
{
INTA=1,b=2;
//交换(a,b)-错误:哪个“交换”?
std::swap(a,b);//在
::交换(a,b);//我定义的那个
}
  • 注意:
    使用命名空间std;
    不是推荐的做法
编辑


MSVC编译器提供了
\u CSTD
宏(
\define\u CSTD::
),这样您就可以使用
使用_cstdfun;
,e.t.c,如果您愿意的话。

就个人而言,我永远不会在我的代码中使用leading::。如果我有一个名称空间用重复的定义覆盖全局,那么我可能打算这么做。在不需要的时候使用::就像编写
this->variable
,而不是
vari启用类内函数
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
    }
typedef unsigned int size_t;

namespace std
    {
    using ::size_t;
    }

size_t x = 1;
std::size_t y = 2;
# 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
    }