讓編譯器的行爲說,我有兩個不同的版本相同的標題foo.hpp
的,第一個:與常量靜態非整體數據初始化,命名空間VS結構
// File foo.hpp
#ifndef FILE_FOO
#define FILE_FOO
namespace X
{
static const int i = 13;
static const double d = 17.0;
}
#endif
,第二個:
// File foo.hpp
#ifndef FILE_FOO
#define FILE_FOO
struct X
{
static const int i = 13;
static const double d = 17.0;
};
#endif
在後一種情況下,結構的使用是毫無意義的,但我的目的是突出我的問題。在這兩種情況下,我試圖建立以下源文件foo.cpp
:
// File foo.cpp
#include "foo.hpp"
#include <iostream>
int main()
{
std::cout << X::i << std::endl;
std::cout << X::d << std::endl;
return 0;
}
但只有後者,我得到了以下錯誤:
In file included from foo.cpp:2:
foo.hpp:7: error: floating-point literal cannot appear in a constant-expression
foo.hpp:7: error: ISO C++ forbids initialization of member constant ‘d’ of non-integral type ‘const double’
我使用g++
4.2.1(所以仍然有C++ 98標準)和-pedantic
,這個選項是嚴格要求得到上述錯誤。
正如我們討論的here,我可以看到只允許在類內部初始化靜態常量積分或枚舉類型,因爲我猜C++標準沒有指定在編譯時應如何實現浮點,並且它離開它到了處理器。但此時的命名空間的情況下是在誤導我...
最後,問題:
- 如何編譯器的行爲,並轉換源到目標代碼在上述兩種情況?
- 它爲什麼只給頭的第二個版本一個錯誤?
感謝您的幫助!
看到這種對翻譯單元的依賴性真的很有趣。只需一個單獨的翻譯單元,我就能得到我期望的確切輸出,例如:1.1。使用多個翻譯單元'printFromHeader'和靜態方法'printDouble'輸出** 1 **,而'printFromSource'則給出** 1.1 **。 作爲對我們所看到的附加確認,可以在cout中添加'&StaticNamespace :: d',我們將看到**不同的內存地址** –
上述行爲也適用於英特爾編譯器 –
連同鏈接到[棄用靜態關鍵字...沒有更多?](http://stackoverflow.com/questions/4726570/deprecation-of-the-static-keyword-no-more)你在另一個答案中提供,我認爲我們可以關閉這個問題 –