让编译器的行为说,我有两个不同的版本相同的标题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)你在另一个答案中提供,我认为我们可以关闭这个问题 –