71

我正在学习 C++,但我不知道什么时候需要使用::. 我知道我需要在andstd::前面使用。这是否意味着创建它的开发人员在文件内部创建了一个名为的命名空间并将函数放入名为的命名空间中?当我创建一个新类时,由于某种原因不在同一个文件中,我必须添加.coutciniostreamstdcincoutstdmain()::

例如,如果我创建了一个class被调用的函数A,为什么我需要将我创建A::的函数放在前面,即使我没有将它放入命名空间中?例如void A::printStuff(){}. 如果我在 中创建一个函数main,为什么我不必放入main::printStuf{}

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

4

5 回答 5

99

你是非常正确的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;
}

::被称为范围解析算子。名称coutcin是在 中定义的std,所以我们必须用 来限定它们的名称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该类。

于 2013-03-27T00:00:36.077 回答
30

::用于取消引用范围。

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 不是函数,而是流对象的实例。

编辑 已修复为Keine Lust建议

于 2013-03-27T00:04:13.363 回答
28

::称为范围解析运算符。可以这样使用:

:: 标识符
类名 :: 标识符
命名空间 :: 标识符

你可以在这里阅读它
https://docs.microsoft.com/en-us/cpp/cpp/scope-resolution-operator?view=vs-2017

于 2013-03-26T23:59:56.190 回答
9

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

    #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

其他用途可能是:从类外部定义函数、访问类中的静态变量或使用多重继承。

于 2018-07-05T10:02:46.770 回答
0

看看它是不是信息丰富的[合格的标识符

限定的 id-expression 是由作用域解析运算符 :: 前置的非限定 id-expression,以及可选的枚举序列、(C++11 起)类或命名空间名称或 decltype 表达式(C++11 起)分隔由范围解析运算符。例如,表达式 std::string::npos 是一个在命名空间 std 中的类字符串中命名静态成员 npos 的表达式。表达式 ::tolower 将函数命名为全局命名空间中的 tolower。表达式 ::std::cout 命名命名空间 std 中的全局变量 cout,这是一个顶级命名空间。表达式 boost::signals2::connection 命名了在命名空间 signals2 中声明的类型连接,它在命名空间 boost 中声明。

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

于 2018-04-20T08:47:45.670 回答