代码之家  ›  专栏  ›  技术社区  ›  getsoubl

声明与常量变量和成员函数相同的标识符

  •  4
  • getsoubl  · 技术社区  · 7 年前

    我写了以下代码

    #include <iostream>
    const int N = 5;
    class X
    {
      public:
      int array[N];
      void foo()
      {
         std::cout << "array size:"<<sizeof(array)/N << std::endl;   
      }
      enum
     {
       N = 3    
      };
    };
    
    int main()
    {
      X x;
      x.foo();
    } 
    

    <source>:13:8: error: declaration of 'N' [-fpermissive]
        N = 3
            ^
    <source>:2:11: error: changes meaning of 'N' from 'const int N' [-fpermissive]
     const int N = 5;
               ^
    

    从我编译时的观点来看,数组被定义为一个由5个整数组成的数组,N被定义为5。编译器如何解析变量的名称声明?

    3 回复  |  直到 7 年前
        1
  •  1
  •   xskxzr    7 年前

    问题来自声明 int array[N]; .

    根据 [basic.scope.class]/2 :

    在类S中使用的名称N应在其上下文中指代相同的声明,并且当在S的完整作用域中重新计算时。违反此规则不需要诊断。

    在宣言中, N 决定参考 ::N ,但在 X (所有成员现在都可见), N个 X::N ,因此程序格式不正确;不需要诊断。

        2
  •  6
  •   Oliv    7 年前

    在成员函数(甚至是内联定义的函数)的范围内,类被认为是完整的 1个 N 必须使用成员枚举器。它的值必须是3。

    但是,在声明类成员数据时不是这样的。在那一点上(当指定 array ),该类不被认为是完整的。所以 N个 只能引用以前看到的内容,这意味着它必须是全局常量。

    叮当接受它,但发出 6 ( sizeof(int) * 5 / 3 ). GCC(8)没有,但它并不是真正的无效代码。只是容易出错。更好地定义的方法是在定义数组之前将枚举数移动到

    enum { N = 3 };
    int array[N];
    

    sizeof(array) / ::N
    

    重新排列类定义会更好,因为它不会仍然容易出错(我们可以忘记使用 ::N


    1:从最新的C++标准草案

    [class.mem]/6

    类的完整类上下文是

    • 函数体([dcl.fct.def.general]),
    • 默认参数([dcl.fct.default]),
    • noexcept说明符,
    • 合同条件([dcl.attr.contract]),或
    • 默认成员初始值设定项

        3
  •  2
  •   R Sahu    7 年前

    排队

    int array[N];
    

    N 是全球性的 .

    函数内部 foo() N个 定义在 enum .

    类的定义用于解析名称。但是,在成员变量的声明中,只有该行之前的声明用于解析名称。

    如果你把班改成

    class X
    {
       public:
          enum
          {
             N = 3    
          };
    
          int array[N];
          void foo()
          {
             std::cout << "array size:"<<sizeof(array)/N << std::endl;   
          }
    };
    

    那么 N个 array 是指 枚举 .

    这对理解语言很有用,但是,请不要在实际应用程序中使用这种编码风格。

    推荐文章