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

时间:2012-11-12 16:05:43

标签: 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;
}

使用gcc版本4.5.1填充程序会产生错误CFoo.cpp: undefined reference to CFoo::VPI。如果

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

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

1 个答案:

答案 0 :(得分:5)

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

class CFoo{
private:
    static const double VPI = 0.5;    
// ...
};

当且仅当该初始值设定项为const整数或const枚举类型时,静态数据成员的声明才能指定常量初始值设定项。 0.5不是这些,因此您的代码不是有效的C ++。 9.4.2静态数据成员涵盖了这一点:

  

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

     

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

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

头:

class CFoo{
private:
    static const double VPI;    
};

cpp:

const double CFoo::VPI = 0.5;

另一个无关的问题是:

int main(){
    CFoo aFoo(); // NOT OK
    return 0;

表达式CFoo aFoo();不符合您的想法。您认为它声明了aFoo类型的对象CFoo,并使用CFoo的默认构造函数对其进行初始化。但它实际上做的是声明一个名为aFoo的函数,不带参数,按值返回CFoo。这被称为most vexing parse。为了做你想做的事,简单地省略括号:

CFoo aFoo;