簡體   English   中英

聲明與const變量和成員函數相同的標識符

[英]Declare the same identifier as const variable and member function

我寫了下面這段代碼

#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();
} 

上述代碼不能與GCC一起編譯:

<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;
           ^

從我在編譯時的觀點來看,數組被定義為一個包含五個整數的數組,N被定義為5.如何編譯器解析變量的名稱聲明?

在成員函數的范圍內(甚至是那些定義為內聯的函數),該類被認為是完整的1 因此,使用N必須使用成員枚舉器。 它的價值必須是3。

但是,在聲明類成員數據時並非如此。 此時(指定array ),不會將該類視為完整。 因此N只能參考之前看到的內容,這意味着它必須是全局常量。

Clang接受它,但是發出6sizeof(int) * 5 / 3 )。 GCC(8)沒有,但它並不是真正無效的代碼。 這只是容易出錯。 更好地定義的方法是在定義數組之前將枚舉器移動到

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

...或者如果我們不這樣做,那么我們可以使用范圍分辨率來指代“正確的N”

sizeof(array) / ::N

重新排列類定義會更好,因為它仍然不會出錯(我們可以忘記使用qualified ::N )。


1:來自最新的C ++標准草案

[class.mem] / 6

一個完整的類的上下文是一個

  • 函數體([dcl.fct.def.general]),
  • 默認參數([dcl.fct.default]),
  • noexcept說明符,
  • 合同條件([dcl.attr.contract]),或
  • 默認成員初始化程序

在類的成員規范內。

在線

int array[N];

N是全球N

在函數foo()內部, Nenum定義的N

foo()的定義中,類的定義用於解析名稱。 但是,在成員變量的聲明中,只有使用該行的聲明才能解析名稱。

如果你把班級改為

class X
{
   public:
      enum
      {
         N = 3    
      };

      int array[N];
      void foo()
      {
         std::cout << "array size:"<<sizeof(array)/N << std::endl;   
      }
};

然后,用於定義arrayN是在enum定義的array

PS這對於理解語言很有用,但是,請永遠不要在現實世界的應用程序中使用這種編碼風格。

問題來自聲明int array[N];

根據[basic.scope.class] / 2

在類S中使用的名稱N應在其上下文中引用相同的聲明,並在完成的S范圍內重新評估。違反此規則不需要診斷。

在聲明的上下文中, N被解析為引用::N ,但是在X的完成范圍內(所有成員現在都可見), N被解析為引用枚舉器X::N ,因此程序生病了-formed; 無需診斷。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM