什么名称查找规则适用于静态 const 数据成员定义中的名称

Posted

技术标签:

【中文标题】什么名称查找规则适用于静态 const 数据成员定义中的名称【英文标题】:What name lookup rule apply to the name in the definition of static const data member 【发布时间】:2014-05-30 04:30:22 【问题描述】:

在数据成员的 quialified-id 之后,有一个引用描述的名称查找应用于 const 静态数据成员的数据成员:

秒。 3.4.1/13:

用于定义类 X 的静态数据成员的名称 (9.4.2) (在静态成员的限定 ID 之后)被查找为 如果该名称在 X 的成员函数中使用。

但是我们可以定义类内的静态常量数据成员:

class A

    static const int i = x;//x is a name defined an arbitrary const int
;

从秒的规则。 3.4.1/13 不适用于名称x 查找。 实际会应用什么规则?请参考标准中的相应条款。

例如,下面的代码是有效的:

#include <stdio.h>

const int a=5;
class A

public:
    static const int b=a;//b is unqualified-id of this data-member
;

int main() printf("%d\n",A::b);  //5

以下代码也有效:

#include <stdio.h>

class A

public:
    static const int a=7;
    static const int b=a;
;

int main() printf("%d\n",A::b);  //7

但以下无效:

#include <stdio.h>

class A

public:
    static const int b=a; //error: a was not declare in this scope.
    static const int a=7;
;

int main() printf("%d\n",A::b); 

不清楚哪些规则适用于查找a

【问题讨论】:

x 在您的案例中定义在哪里?显然它不能只是任何地方 我不明白这个问题;您引用的文字是说查找与 void member() x; 的查找相同。您是在问如何在成员函数中查找名称? @Praetorian x 在某处定义。我想了解范围的后续查找名称x。 @MattMcNabb No. 引用说此查找与 quailified-id 相同。但是使用静态 const 数据成员的非限定 id 查找呢? 您将术语合格和不合格查找与 qualified-id 混为一谈。后者在此引用中谈论的是静态数据成员标识符 (i),当您提供定义时需要使用类名(和命名空间名称)进行限定 - 例如,const int NS::A::i; - 因此短语 qualified-id。 §3.4.1/13 是说 §3.4.1/8 下列出的规则将用于查找x 【参考方案1】:

静态数据成员的类内声明不是定义,即使它包含初始化程序。因此 §3.4.1/13 不适用于您的示例。

类范围内的名称查找由哪些范围到达类范围的规则定义。 §3.3.7/1.1:

    在类中声明的名称的潜在范围不仅包括名称声明点之后的声明区域, 还有所有函数体,默认参数, 异常规范和大括号或等式初始化器 该类中的非静态数据成员(包括嵌套中的此类内容 类)。

    在类 S 中使用的名称 N 应在其上下文中引用相同的声明,并且在 S 的完整范围内重新评估时。否 违反此规则需要进行诊断。

    如果对类中的成员声明重新排序会在 (1) 和 (2) 下产生一个替代的有效程序,则该程序是非良构的,不会 需要诊断。

这些规则的目的是允许成员函数访问稍后在类中声明的成员变量。因为规则没有提到静态数据成员的初始化器,所以从静态数据成员中查找名称默认为 3.4.1/7:

在成员之外的类 X 的定义中使用的名称 函数体、默认参数、异常规范、 非静态数据成员的大括号或相等初始化器,或嵌套 类定义应以下列方式之一声明:

该列表基本上归结为“名称必须是同一类的成员,或者在封闭范围内声明。”在您的第一个示例中,a 在封闭的命名空间中声明,因此可以找到它。在第二个示例中,a 在使用前声明。

但在第三个示例中,它在被声明为非法之前使用——如果在封闭的命名空间中有一些 a 的声明,由于 3.3.7/1.2,这将是未定义的行为。

【讨论】:

那么什么规则将应用于我的示例?我不明白。 谢谢!我理解你。【参考方案2】:
#include <stdio.h>

const int a=5;
class A

  public:
    static const int b=a; // The quote corresponds to the lookup for a.
                          // It says that the lookup logic for a is the same
                          // as the lookup for a name in a member function of A
;

如果你有成员函数,让我们把它设为static 以便于比较,让我们看看函数中名称的查找是什么样的。

class A

  public:
    static void fun()
    
       b = a;
       // The lookup for a:
       // 1. A local variable in the function.
       // 2. A `static` member of the class.
       // 3. A variable in the enclosing namespace.
    

    static const int b;
;

当你使用

    static const int b = a;

a 的查找将来自函数 foo 的 (2) 和 (3),因为 a 不能是局部变量。

【讨论】:

以上是关于什么名称查找规则适用于静态 const 数据成员定义中的名称的主要内容,如果未能解决你的问题,请参考以下文章

statuc和const

如何使 const 适用于作为共享指针的 C++ 类成员

static方法 和 const方法

在非限定 id 之后的静态数据成员定义中使用的名称

C++面向对象-static、const

const成员函数总结