与 complex.h 一起使用时对 static const double 的未定义引用

Undefined reference to static const double when used with complex.h

这是最低代码:

#include <iostream>
#include <complex>

using namespace std;

class Test {
    static const double dt = 0.1;
public:
    void func();
};

void Test::func() {
    cout << dt << endl; // OK!
    cout << dt*complex<double>(1.0, 1.0) << endl; // Undefined reference
}

int main() {
    Test a;
    a.func();
}

注释行给出了 undefined reference to `Test::dt'。每次我想将复数与 dt 相乘时,我都可以创建一个临时变量,但这很不方便,因为我在代码中将许多静态常量成员与复数相乘。

我的猜测是,当 dt 与一个复数相乘时,出于某种原因,它需要 dt 的地址(即 &dt,这看起来很奇怪。

任何想法为什么会发生此错误以及如何使它比在每次我想将它与复数相乘之前做 double temp = dt; 更优雅地工作?

您已声明 Test::dt 但未在某处定义。如果您决定在 class 声明之外定义内容 - 您应该保持一致:

#include <iostream>
#include <complex>

using namespace std;

class Test {
    static const double dt;
    public:
    void func();
};

void Test::func() {
    cout << dt << endl; // OK!
    cout << dt*complex<double>(1.0, 1.0) << endl; // Undefined reference
}

const double Test::dt = 0.1;

int main() {
    Test a;
    a.func();
}

...how to make it work...?

#include <iostream>
#include <complex>

using namespace std;

class Test {
    static const double dt;
public:
    void func();

};

//move initialization outside of class
const double Test::dt = 0.1; 

void Test::func() {
    cout << dt << endl; // OK!
    cout << dt*complex<double>(1.0, 1.0) << endl; // Undefined reference

}

int main() {
    Test a;
    a.func();
}


或(参见 this question 的解释)

class Test {
        static const double dt = 0.1;
    public:
        void func();

};
const double Test::dt;


或(与上面的技巧相同,但使用 c++11 的 constexpr

class Test { 
         static constexpr double dt = 0.1;
    public:   
         void func();    

};                      
constexpr double Test::dt;


Any ideas why this error happens...?

来自 here:

If a static data member of integral or enumeration type is declared const (and not volatile), it can be initialized with a initializer in which every expression is a constant expression, right inside the class definition...

因此静态数据成员可以在 class 定义中初始化,如果它是 intenum 类型并声明const,这不是你的情况。 (有关详细信息,请参阅 this answer

为什么它似乎适用于第一行?好吧,用 clang 编译我得到:

warning: in-class initializer for static data member of type 'const double' is a GNU extension

所以这个浮点类型初始化是 gcc 编译器的扩展,这个扩展可能不适用于期望引用类型参数的函数(现在只是一个猜测)。

另请注意,这仅适用于 c++98(c++11 具有解决此问题的 constexpr 关键字)

#include <iostream>
#include <complex>

using namespace std;

class Test {
    static const double dt;
    public:
    void func();
};

void Test::func() {
    cout << dt << endl; // OK!
    cout << dt*complex<double>(1.0, 1.0) << endl; // Undefined reference
}

const double Test::dt = 0.1;

int main() {
    Test a;
    a.func();
}