C++ 为什么否定静态成员变量会产生链接器错误? 请考虑下面的小例子 // CFoo.hpp class CFoo{ private: static const double VPI = 0.5; public: double getVpi(); }; // CFoo.cpp #include "CFoo.hpp" double CFoo::getVpi(){ double x = -VPI; return x; } // main.cpp #include "CFoo.hpp" int main(){ CFoo aFoo(); return 0; }

C++ 为什么否定静态成员变量会产生链接器错误? 请考虑下面的小例子 // CFoo.hpp class CFoo{ private: static const double VPI = 0.5; public: double getVpi(); }; // CFoo.cpp #include "CFoo.hpp" double CFoo::getVpi(){ double x = -VPI; return x; } // main.cpp #include "CFoo.hpp" int main(){ CFoo aFoo(); return 0; },c++,C++,将程序与gcc版本4.5.1对齐会产生错误CFoo.cpp:CFoo::VPI的未定义引用。如果出现以下情况,则不会出现错误剂量 VPI没有被否定 求反写为double x=-1*VPI 类CFoo的声明和定义发生在同一个文件中 您知道此错误的原因吗?您的代码存在多个问题。基本上,这是无效的C++03: class CFoo{ private: static const double VPI = 0.5; // ... }; 静态数据成员的声明可以指定常量初始值设定项,当且

将程序与gcc版本4.5.1对齐会产生错误
CFoo.cpp:CFoo::VPI的未定义引用
。如果出现以下情况,则不会出现错误剂量

  • VPI没有被否定
  • 求反写为
    double x=-1*VPI
  • 类CFoo的声明和定义发生在同一个文件中

您知道此错误的原因吗?

您的代码存在多个问题。基本上,这是无效的C++03:

class CFoo{
private:
    static const double VPI = 0.5;    
// ...
};
静态数据成员的声明可以指定常量初始值设定项,当且仅当该初始值设定项是
const
integral或
const
枚举类型时<代码>0.5 <代码>既不是,也就是说,您的代码不是有效的C++。strong>9.4.2静态数据成员
包括以下内容:

2/静态数据成员在其类定义中的声明为 非定义[…]静态数据成员的定义应 出现在包含成员类定义的命名空间范围中。 [……]

4/如果静态数据成员是常量整数或常量枚举 类型,则其在类定义中的声明可以指定 常数初始值设定项,应为积分常数表达式 (5.19)

要初始化
VPI
,必须在CPP文件中执行此操作:

标题: cpp: 另一个不相关的问题是:

int main(){
    CFoo aFoo(); // NOT OK
    return 0;
表达式
CFoo aFoo()不会做你认为它会做的事情。您认为它声明了类型为
CFoo
的对象
aFoo
,并使用
CFoo
的默认构造函数初始化它。但它实际上是声明一个名为
aFoo
的函数,不带任何参数,按值返回一个
CFoo
。这就是我们所知道的。为了完成所需操作,请省略括号:

CFoo aFoo;

这是无效的C++。不能内联初始化非整数、非constexpr静态类成员。确保启用并注意所有编译器警告和遵从性功能。使用clang编译会给出:
警告:类型为“const double”的静态数据成员的类内初始值设定项是GNU扩展
@KerrekSB我知道这为什么无效,但这是一个问答网站,那么,如果你知道的话,为什么不回答OP问题呢?@KerrekSB很公平。我的坏。@user93353:在C++11中,任意
静态constexpr
类成员也可以内联初始化。但它们必须是
constexpr
(我相信初始值设定项也是如此)。感谢您详细而有用的回答。我仍然不明白链接器为什么会这样,但我原来的问题已经解决了。Deve:在神秘的未定义行为世界中,人们永远无法知道会发生什么。@Deve:编译器接受了声明中的初始值设定项(未能诊断,可能是由于部分支持C++11),但这仍然使成员未定义。当您对一个非常量表达式的变量求反(并且
double
s不能是常量表达式)时,该变量就是该变量的用法(在C++11中使用odr),并且链接器需要该定义,这使得它抱怨您没有提供该定义。
int main(){
    CFoo aFoo(); // NOT OK
    return 0;
CFoo aFoo;