[英]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接受它,但是發出6
( sizeof(int) * 5 / 3
)。 GCC(8)沒有,但它並不是真正無效的代碼。 這只是容易出錯。 更好地定義的方法是在定義數組之前將枚舉器移動到
enum { N = 3 };
int array[N];
...或者如果我們不這樣做,那么我們可以使用范圍分辨率來指代“正確的N”
sizeof(array) / ::N
重新排列類定義會更好,因為它仍然不會出錯(我們可以忘記使用qualified ::N
)。
1:來自最新的C ++標准草案
一個完整的類的上下文是一個
- 函數體([dcl.fct.def.general]),
- 默認參數([dcl.fct.default]),
- noexcept說明符,
- 合同條件([dcl.attr.contract]),或
- 默認成員初始化程序
在類的成員規范內。
在線
int array[N];
N
是全球N
在函數foo()
內部, N
是enum
定義的N
在foo()
的定義中,類的定義用於解析名稱。 但是,在成員變量的聲明中,只有使用該行的聲明才能解析名稱。
如果你把班級改為
class X
{
public:
enum
{
N = 3
};
int array[N];
void foo()
{
std::cout << "array size:"<<sizeof(array)/N << std::endl;
}
};
然后,用於定義array
的N
是在enum
定義的array
。
PS這對於理解語言很有用,但是,請永遠不要在現實世界的應用程序中使用這種編碼風格。
問題來自聲明int array[N];
。
在類S中使用的名稱N應在其上下文中引用相同的聲明,並在完成的S范圍內重新評估。違反此規則不需要診斷。
在聲明的上下文中, N
被解析為引用::N
,但是在X
的完成范圍內(所有成員現在都可見), N
被解析為引用枚舉器X::N
,因此程序生病了-formed; 無需診斷。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.