在C++中使用作用域解析运算符::

84

我正在学习C++,有时候不知道何时需要使用::。我知道在coutcin前面需要使用std::。这是否意味着在iostream文件中,创建它的开发者制作了一个名为std的命名空间,并将函数cincout放入了名为std的命名空间中?当我创建一个不在与main()相同的文件中的新类时,出于某种原因我必须添加::

例如,如果我创建一个名为Aclass,为什么我需要在我创建的函数前面加上A::,即使我没有将它放入命名空间中?例如void A::printStuff(){}。如果我在main中创建一个函数,为什么我不需要写main::printStuff{}

我知道我的问题可能让人困惑,但有人能帮帮我吗?


3
一个好问题,但是有点太广泛了(依我看)。这被称为作用域解析运算符,你可以通过搜索“作用域”来进一步学习。所有这些名称(coutA类的成员函数)都在作用域中定义,你必须使用 :: 来解决作用域(也就是告诉编译器在哪里查找)。 - GManNickG
:: 前缀可以是命名空间或类。由于 main 不是它们中的任何一个(它是一个函数),因此 main::printStuff 是不正确的。 - Keith Thompson
:: 给出了所有权的概念,当一个定义是类或命名空间的一部分时,应该使用 :: 来访问它...不完全是这样,但这给你一种感觉。 - Stephane Rolland
6
coutcin不是函数,它们是对象。 - chris
5个回答

112

关于 coutcin,你基本上是正确的。它们是在 std 命名空间内定义的对象(而不是函数)。以下是它们根据 C++ 标准的声明:

头文件 <iostream> 概要说明

#include <ios>
#include <streambuf>
#include <istream>
#include <ostream>

namespace std {
  extern istream cin;
  extern ostream cout;
  extern ostream cerr;
  extern ostream clog;

  extern wistream wcin;
  extern wostream wcout;
  extern wostream wcerr;
  extern wostream wclog;
}
::被称为作用域限定符。名称coutcinstd中定义,因此我们必须使用std::来限定它们的名称。 类的行为有点像命名空间,因为在类内声明的名称属于该类。例如:
class foo
{
  public:
    foo();
    void bar();
};

名为 foo 的构造函数是名为 foo 的类的成员。它们的名称相同,因为它是构造函数。函数 bar 也是 foo 的成员。

由于它们是 foo 的成员,当从类外引用它们时,我们必须限定它们的名称。毕竟,它们属于那个类。因此,如果你要在类外定义构造函数和 bar,你需要这样做:

foo::foo()
{
  // Implement the constructor
}

void foo::bar()
{
  // Implement bar
}

这是因为它们被定义在类的外部。如果您没有在名称上加上foo::限定符,那么您将定义一些新函数在全局作用域中,而不是作为foo的成员。例如,以下是完全不同的bar

void bar()
{
  // Implement different bar
}

因为处于不同的作用域,foo 类中的函数可以与其名称相同。这个 bar 函数位于全局作用域,而另一个 bar 函数则属于 foo 类。


35

:: 用于解引用作用域。

const int x = 5;

namespace foo {
  const int x = 0;
}

int bar() {
  int x = 1;
  return x;
}

struct Meh {
  static const int x = 2;
}

int main() {
  std::cout << x; // => 5
  {
    int x = 4;
    std::cout << x; // => 4
    std::cout << ::x; // => 5, this one looks for x outside the current scope
  }
  std::cout << Meh::x; // => 2, use the definition of x inside the scope of Meh
  std::cout << foo::x; // => 0, use the definition of x inside foo
  std::cout << bar(); // => 1, use the definition of x inside bar (returned by bar)
}

无关的: cout和cin不是函数,而是流对象的实例。


31

4
链式调用也没问题:myNamespace::myClass::myMember 或者 ::std::cout - chris

11

“一元作用域解析运算符”或“双冒号运算符”的一个用途是选择相同名称的局部变量和全局变量:

    #include <iostream>
    using namespace std;
    
    int variable = 20;
    
    int main()
    {
    float variable = 30;
    
    cout << "This is local to the main function: " << variable << endl;
    cout << "This is global to the main function: " << ::variable << endl;
    
    return 0;
    }

输出结果将是:

这是主函数的局部变量: 30

这是主函数的全局变量: 20

其他用途可以包括:从类外定义函数以访问类内静态变量或使用多重继承。


-1

看这个是有信息的 [合格标识符]

合格的 id-expression 是一个未限定的 id-expression,前面加上作用域解析运算符 ::,并且可选地由枚举、(自 C++11 起)类或命名空间名称或 decltype 表达式(自 C++11 起)组成,它们之间由作用域解析运算符分隔。例如,表达式 std::string::npos 是一个表达式,它在命名空间 std 中的类 string 中命名了静态成员 npos。表达式 ::tolower 在全局命名空间中命名函数 tolower。表达式 ::std::cout 命名了命名空间 std 中的全局变量 cout,该命名空间是顶层命名空间。表达式 boost::signals2::connection 命名了在命名空间 signals2 中声明的类型 connection,该命名空间在命名空间 boost 中声明。

关键字 template 可以出现在合格的标识符中,以消除依赖模板名称的歧义]1


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接