Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/152.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 带前缀的双冒号是什么意思&引用;?_C++_Syntax_Namespaces_Scope Resolution_Global Namespace - Fatal编程技术网

C++ 带前缀的双冒号是什么意思&引用;?

C++ 带前缀的双冒号是什么意思&引用;?,c++,syntax,namespaces,scope-resolution,global-namespace,C++,Syntax,Namespaces,Scope Resolution,Global Namespace,我在一个必须修改的类中发现了这行代码: ::Configuration * tmpCo = m_configurationDB;//pointer to current db 我不知道类名前面的双冒号到底是什么意思。没有这些,我会读到:tmpCo的声明作为类Configuration的对象的指针。。。但是前面的双冒号让我很困惑 我还发现: typedef ::config::set ConfigSet; :是定义命名空间的运算符 例如,如果您想使用cout而不提及使用名称空间std在代码中编

我在一个必须修改的类中发现了这行代码:

::Configuration * tmpCo = m_configurationDB;//pointer to current db
我不知道类名前面的双冒号到底是什么意思。没有这些,我会读到:
tmpCo的声明作为类
Configuration
的对象的指针。。。但是前面的双冒号让我很困惑

我还发现:

typedef ::config::set ConfigSet;

是定义命名空间的运算符

例如,如果您想使用cout而不提及
使用名称空间std在代码中编写以下内容:

std::cout << "test";

std::cout该
运算符被称为范围解析运算符,它就是这样解析范围的。因此,通过在类型名前面加上前缀,它告诉编译器在全局命名空间中查找该类型

例如:

int count = 0;

int main(void) {
  int count = 0;
  ::count = 1;  // set global count to 1
  count = 2;    // set local count to 2
  return 0;
}

这可以确保从全局名称空间进行解析,而不是从当前所在的名称空间开始。例如,如果您有两个不同的类,分别称为
Configuration

class Configuration; // class 1, in global namespace
namespace MyApp
{
    class Configuration; // class 2, different from class 1
    function blah()
    {
        // resolves to MyApp::Configuration, class 2
        Configuration::doStuff(...) 
        // resolves to top-level Configuration, class 1
        ::Configuration::doStuff(...)
    }
}

基本上,它允许您遍历到全局名称空间,因为您的名字可能会被另一个名称空间中的新定义撞到,在这种情况下,
MyApp
用于将某个东西(变量、函数、类、typedef等)链接到名称空间或类

如果在
::
之前没有左手边,那么它将强调您正在使用全局名称空间的事实

e、 g:


::doMyGlobalFunction()

已经有很多合理的答案了。我将插入一个可能对一些读者有所帮助的类比<代码>:
在搜索要运行的程序的路径时,其工作原理非常类似于文件系统目录分隔符“
/
”。考虑:

/path/to/executable
这是非常明确的-只有在文件系统树中的确切位置上的可执行文件才能匹配此规范,而不考虑有效的路径。同样地

::std::cout

…在C++命名空间“树”中同样显式。

与这些绝对路径相比,您可以配置好的UNIX shell(例如)来解析当前目录下的相对路径或
PATH
环境变量中的任何元素,因此如果
PATH=/usr/bin:/usr/local/bin
,并且您“在”
/tmp
,那么

X11/xterm
…如果找到,将愉快地运行
/tmp/X11/xterm
,否则
/usr/bin/X11/xterm
,否则
/usr/local/bin/X11/xterm
。类似地,假设您在一个名为
X
的名称空间中,并且实际上有一个“
使用名称空间Y
”,然后

std::cout
…可以在以下任意位置找到:
::X::std::cout
::std::cout
::Y::std::cout
,也可能由于(ADL,也称为Koenig查找)而在其他位置找到。因此,只有
::std::cout
真正明确了您所指的对象,但幸运的是,没有一个头脑正常的人会创建自己的名为“
std
”的类/结构或名称空间,也没有任何名为“
cout
”的东西,因此实际上只使用
std::cout
是可以的

值得注意的差异:

1)在路径> /COD>中,使用第一个匹配的顺序,而C++在你不明确时给出编译器错误。

< P > 2)在C++中,没有任何超前范围的名称可以在当前命名空间中匹配,而大多数UNIX shell只在“代码>路径 < < /P> >中放置<代码> .<代码>。

3)C++总是搜索全局命名空间(如<代码> /<代码>隐式地表示<代码>路径>代码> >

名称空间和符号明确性的一般讨论 使用绝对
::abc::def::…
“路径”有时有助于将您与正在使用的任何其他名称空间隔离开来,这些名称空间是您的库的一部分,但实际上无法控制其内容,甚至是库的客户机代码也使用的其他库。另一方面,它还将您与符号的现有“绝对”位置更紧密地结合在一起,并且您错过了名称空间中隐式匹配的优点:耦合更少,名称空间之间的代码更容易移动,以及更简洁、可读的源代码

与许多事情一样,这是一种平衡行为。C++标准在<>代码> STD::/Cuth[4]中放置了很多标识符,它们比 CUT少“独特”,程序员可能会使用代码中完全不同的代码。(例如,
合并
包括
填充
生成
交换
队列
上传
最大值
)两个不相关的非标准库使用相同的标识符的几率更高,因为作者通常不知道或不太了解彼此。库(包括C++标准库)随着时间的推移改变它们的符号。这些都可能在重新编译旧代码时产生歧义,特别是当我们有沉重的代码时。
使用名称空间
s:在这个空间中,最糟糕的事情是允许
在头中使用名称空间
s来转义头的作用域,这样任意大量的直接和间接客户端代码就无法自行决定使用哪个名称空间以及如何管理歧义


<> P> >,一个领先的<代码>::/COD>是C++程序员工具箱中的一个工具,它可以主动消除已知冲突,消除未来模糊性的可能性。

< P> <代码>::/>代码是范围解析运算符。它用于指定某个范围。

例如,
::
单独是全局作用域,位于所有其他名称空间之外

some::thing
可以用以下任一方式进行解释:

  • some
    名称空间(在全局范围内,或比当前范围更外部的范围内),而
    thing
    类型函数、对象或嵌套名称空间p
    int x;
    void f2()
    {
       int x = 1; // hide global x
       ::x = 2; // assign to global x
       x = 2; // assign to local x
       // ...
    }
    
    class A {
       void DoSomething() {
          m_counter=0;
          ...
          Twist(data); 
          ...
          Bend(data);
          ...
          if(m_counter>0) exit(0);
       }
       int m_couner;
       ...
    }