繁体   English   中英

范围解析运算符和const

[英]Scope resolution operator and const

让我们看下面的代码:

#include <string> // std::string    
using namespace std;
int main() {
  //const::int i = 42;       -> Error: "expected id-expression before 'int'"
  const::string str = "Foo"; // No error: why?
}

为什么要编译此代码? 仅当XXX是基本类型时,才会出现错误“ XXX之前的预期id表达式”。

const::char c = 1;   // error: expected id-expression before 'char'
const::double d = 2; // error: expected id-expression before 'double'
const::float f = 3;  // error: expected id-expression before 'float'
const::bool b = 4;   // error: expected id-expression before 'bool'

const::string被解析为const ::string ::string表示在全局名称空间中查找string ,并且由于您已将std注入全局名称空间,因此找到了std::string ,并且所有操作都变得很花哨。

int是内置类型,不在任何名称空间中,因此不存在::intstd::int的错误。

::something告诉编译器去寻找something在全局命名空间,但int是关键字(不说明什么),而string (相应std::string )是定义的类<string>这样的代码就相当于这一个

#include <string> // std::string    
using namespace std;
int main() {
  //const ::int i = 42;       -> Error: "expected id-expression before 'int'"
  const ::string str = "Foo";
}

它之所以编译是因为

using namespace std;

将整个std名称空间放入全局名称空间,因此::stringstd::string相同。 您所讨论的行实际上被解释为

const ::string str = "Foo";

但是, int是关键字(和基本类型),而不是驻留在任何名称空间中的用户定义名称。 所以::int没有意义。

您正在using namespace std; 有点红鲱鱼。 注意const::std::string str = "Foo"; 也可以编译。 之所以进行编译(以及您的const::string str = "Foo";编译的原因)是因为::是作用域解析运算符。 间距无关紧要。 就像a+b+ca + b + c之间没有区别一样, const::string strconst :: string str之间也没有区别(同样, const::std::string strconst :: std :: string str之间也没有区别) const :: std :: string str )。

::::std::std::都是嵌套名称说明符的所有示例,在c ++ n3290(C ++ 11标准的草案)的5.1.1¶8中进行了描述。 const是一个关键字,不能将其解释为nested-name-specifier的开头 这意味着const::string只能像您已经写过const ::string一样被解释。

using namespace std;的上下文中using namespace std; 在全局名称空间级别,使用::string没什么问题,因为前导::表示查找全局名称空间中的内容。 您已将所有名称空间std放入全局名称空间。 因此const::string str声明了str作为const -qualified类型的可变std::string

那么const::int i = 42; 在这种构造的标准中没有地方。 看7.1.6.2¶1(c ++ n3290),一个简单类型说明符

  • 类型名称 ,可以选择在其后加一个嵌套名称说明符
  • 嵌套名称说明符 模板 simple-template-id
  • 内置原始类型之一,
  • auto关键字,或
  • 十进制类型说明符

类型名称类名称枚举名称typedef名称simple-template-id 内置基本类型不属于type-name的类别。 这意味着以下将(并确实)进行编译:

#include <string> 
#include <iostream>

typedef int Int; // Now we can use ::Int because Int is a type-name.

using namespace std;
int main() {
  const::Int i = 42;         // No error.
  const::string str = "Foo"; // No error.
  cout << i << ' ' << str << '\n';
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM