我不明白name used in...
的感觉。这是什么意思?例如(3.4.1 / 7):
在成员之外定义类X的名称 功能体......
考虑以下示例:
class A { static const int a = 4; }
int b = A::a;
在用于全局范围的嵌套名称说明符之后的名称a
还是用于类范围?
命名空间模拟在7.3.1 / 6中非常清楚地定义:
声明的封闭命名空间是其中的命名空间 声明词汇出现,除了重新声明 在其原始命名空间之外的命名空间成员(例如,定义 如7.3.1.2)中所述。
答案 0 :(得分:1)
免责声明:警告,语言答案。
通常,我会说范围被理解为{}
所包含的程序文本中除初始化括号之外的部分。 TC ++ PLv4 p157"声明将一个名称引入范围"。
在[basic.scope.declarative] / 1中,我们找到声明区域的定义:
程序文本的某些部分引入了每个名称,称为声明区域,这是该名称有效的程序的最大部分,即其中该名称可用作非限定名称以引用同一实体。
我认为我们可以看到"之后的部分"作为名称有效性的定义。
[basic.scope.declarative] / 1继续定义范围:
通常,每个特定名称仅在某些可能不连续的情况下有效 程序文本的一部分称为范围。
这只定义名称的范围。在全球范围内使用的短语""或者"在类"范围内使用,术语范围与特定名称无关。同样,[basic.scope.declarative] / 3
声明声明的名称被引入声明发生的范围,[...]除外。
此处,术语范围也用于第二种含义,与特定名称无关。
一些语言功能(如块语句,命名空间和类)引入了新的范围。例如。 [stmt.block] / 1
第二种含义中的复合语句定义块范围。
范围至少在三种不同的情境中使用:
示例:3.4.3 / 1
如果 qualified-id 的嵌套名称说明符指定了一个类,则在 nested-name-specifier 之后指定的名称除了下面列出的情况外,我们会在课程范围内查找。
class X
{
int m;
void foo() { int n; }
};
decltype(X::m) v; // legal
decltype(X::n) w; // illegal
在此上下文中,类X
的范围不会扩展到任何嵌套范围,例如成员函数或嵌套类。
示例:3.3.7 / 2
类成员的名称只能按如下方式使用:
- 在其类的范围内(如上所述)或从其类派生的类
- [...]
class X
{
int m;
void foo()
{
decltype(m) n;
}
static int o;
};
int X::o = decltype(m)();
此处,类X
的范围扩展到嵌套范围和程序的其他部分,例如类主体外部成员的定义。
请注意,静态数据成员,嵌套类和本地类的初始化程序在范围内显式定义为,只要声明了静态数据成员/类。对于成员函数,我只能找到非规范性的注释,例如9.3 / 5
类
f
的成员函数X
在全局范围内定义;表示法X::f
指定函数f
是类X
的成员,并且在类X
的范围内。
据我所知,这个"属于"对于成员函数和嵌套/本地类,表示那些新引入的作用域是嵌套作用域。
"用于X"在标准中不经常发生。有人可能会争辩说3.3.7 / 2应该扩展到嵌套范围,以便在"范围内使用。符合"在#34;。
的范围内查找示例:8.5 / 13
静态成员的初始化程序属于成员类的范围。
class X
{
static int m;
static int n;
};
int n;
int o;
int X::m = n; // X::n
int X::n = o; // ::o
非限定名称的名称查找按照每个相应类别中列出的顺序搜索范围(复数)"" [basic.lookup.unqual] / 1。对于两个静态数据成员的初始值设定项,首先搜索类X
的范围,然后搜索任何基类,然后搜索封闭范围(此处:全局范围),[basic.lookup.unqual] / 7。
&{34>的含义是X
"在我看来,对于不合格的查找,搜索的范围是搜索X
中使用的名称的范围,可能还有访问规则(静态数据成员的初始化程序可以访问私有成员等) 。如上所述,这有效地嵌套了成员函数的范围和在其封闭类之外定义的嵌套类。在那个封闭类的范围内的身体。
不包括"在#"范围内使用的奇怪扩展名。
3.3.3至3.3.9对各种名称范围进行分类。我们可以使用这些类别对可以声明名称的程序部分进行分类:程序的一部分,其中可以声明具有块作用域的名称是块作用域。程序的一部分,其中可以声明具有类范围的名称是类范围。我们仍然需要区分同类的不同范围:
void foo()
{ // begin scope A
int a; //
{ // begin scope B
int b; //
int c; //
} // end scope B
int d; //
} // end scope A
标准调用A
外部范围B
(在名称查找中)。但是,范围B
不是范围A
的一部分。也许" B
之类的内容属于A
,但B
内声明的名称不在A
"范围内。考虑:
class A
{
int m;
class B
{
int n;
};
};
这里,名称查找"在班级A
"的范围内无法通过不合格的查找找到嵌套类B
的成员。同样相关:匿名工会。
我认为执行此分离的最佳方法是查看可引入范围的各个语言功能。例如,[stmt.block] / 1"复合语句定义块范围。"然后我们可以查看程序的任何部分X,找到引入尚未结束的范围的最接近的先前语言特性(*),获取程序的所有区域,其中新声明的名称在同一范围内(**) ),并将其称为X 的封闭范围。
(*)尚未结束:表示块,块结束等(即,由语言功能指定)或者,尚未结束 =可能已声明的名称仍然有效
(**)在同一范围内:搜索,从这个新声明开始,引入尚未结束的范围的最接近的先前语言特征,应该找到程序的相同部分
这似乎符合[basic.scope.declarative] / 4中使用的声明区域的定义:
给定一个声明区域中的一组声明,每个声明都指定相同的非限定名称,它们都应引用同一个实体,或[... =函数重载],或[... =各种例外]。
据我所知,这与[basic.scope.declarative] / 1中的定义相矛盾:
int main()
{
int x;
{
int x;
}
}
这里,我们有两个声明指定相同的非限定名称。外部x
作为名称在内部{}
内也有效;然而,这是一个完全合法的C ++程序。我怀疑声明区域实际上不应该与单个名称相关联。
我认为可以使用终端{
和}
简化范围的定义。
答案 1 :(得分:0)
这句话
在成员之外定义类X的名称 功能体......
考虑在类的定义中使用的所有名称,这些名称从类头开始并在结束括号中结束,不包括成员函数中使用的名称(成员函数中使用的名称在其他段落中考虑)。
例如
class B : public A
{
int x;
int a[i];
C z;
//..
};
所以这些名字是A,x,a,i,C,z。
考虑到虽然在类中定义了名称x,a和z,但是它们的名称可以在类的其他成员定义中使用。
至于您的代码示例
class A { static const int a = 4; }
int b = A::a;
The name a after the nested-name-specifier used into the global scope or it used into the class scope?
然后在类A的类范围中搜索名称a,但在全局范围中使用它的限定名来初始化变量b。
考虑另一个例子,虽然它与您引用的短语没有任何共同之处但与您的代码有关系。
struct A
{
static int a;
static int b;
};
int A::a = 10;
int A::b = a;
这里使用名称a而没有嵌套的名称说明符。如何在类范围内搜索名称是另一个规则。