为什么否定静态成员变量会产生链接器错误?

Dev*_*eve 2 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;
}
Run Code Online (Sandbox Code Playgroud)

使用gcc版本4.5.1加载程序会产生错误CFoo.cpp: undefined reference to CFoo::VPI.如果错误剂量不会发生

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

你知道这个错误的原因吗?

Joh*_*ing 5

您的代码存在多个问题.首先,这不是有效的C++ 03:

class CFoo{
private:
    static const double VPI = 0.5;    
// ...
};
Run Code Online (Sandbox Code Playgroud)

当且仅当该初始化程序是const整数或const枚举类型时,静态数据成员的声明才能指定常量初始值设定项. 0.5既不是这些,因此你的代码不是有效的C++. 9.4.2静态数据成员包括:

2 /在其类定义中声明静态数据成员不是定义[...]静态数据成员的定义应出现在包含成员类定义的命名空间范围内.[...]

4 /如果静态数据成员是const整数或const枚举类型,则它在类定义中的声明可以指定一个常量初始化器,它应该是一个整型常量表达式(5.19).

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

标题:

class CFoo{
private:
    static const double VPI;    
};
Run Code Online (Sandbox Code Playgroud)

cpp:

const double CFoo::VPI = 0.5;
Run Code Online (Sandbox Code Playgroud)

另一个无关的问题是:

int main(){
    CFoo aFoo(); // NOT OK
    return 0;
Run Code Online (Sandbox Code Playgroud)

表达式CFoo aFoo();不符合您的想法.你认为它声明了一个aFoo类型的对象,CFoo并使用CFoo默认的构造函数初始化它.但它实际上做的是声明一个名为aFoo不带参数的函数,返回一个CFooby值.这被称为最令人烦恼的解析.为了做你想做的事,简单省略括号:

CFoo aFoo;
Run Code Online (Sandbox Code Playgroud)