2016-07-07 3 views
3

Вот минимальный код:Неопределенная ссылка на статическую сопзЬ удвоится при использовании 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; перед каждым раз я хочу умножить его на комплексное число?

+0

Этот код не должен компилироваться. Удалите 'static'. –

+0

@HansPassant Да, он не компилируется, он дает неопределенные ссылки. Однако мне нужны статические константные переменные. – eimrek

+0

Нет, он не скомпилирован из-за ключевого слова 'static':' error: 'constexpr', необходимый для инициализации класса статических данных in-class 'const double Test :: dt' нецелого типа. Я могу воспроизвести неопределенная эталонная ошибка после исправления ошибки компиляции. Это действительно похоже на ошибку компилятора. –

ответ

2

...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...

Так статический член данных может быть инициализирован внутри определения класса, если это типа INT или перечисление и объявил Const, который ISN твой случай. (см. this answer для получения дополнительной информации)

Почему это, кажется, работает для первой линии? Ну, компиляция с лязгом я получил:

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

Так что инициализация типа поплавка расширение компилятора GCC, и это расширение, вероятно, не будет работать с функцией о том, что ожидает ссылочного типа аргумента (только предположение в настоящее время).

Также обратите внимание, что это относится к C++ 98 только (C++ 11 имеет constexpr ключевое слово, которое решает эту проблему)

+0

Хех, я пытался использовать 'static constexpr' вместо' static const' в коде в OP, но неопределенная ссылка все еще сохранялась. – eimrek

+0

о вашем последнем правлении: если вы перейдете 'const'->' constexpr', то он будет работать и почти точно, что я просил в исходном сообщении. – eimrek

2

Вы объявили Test::dt, но не определили его где-нибудь. Если вы решите определить вещи вне декларации класса - вы должны быть последовательными:

#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(); 
} 
+0

Это будет работать, но поскольку у меня много констант, более удобно и информативно сохранить инициализацию в заголовке. В настоящее время я по-прежнему предпочитаю решение временной переменной. – eimrek

+0

Может быть, простая 'enum' будет лучше в вашей ситуации? – Sergio

+0

Очевидно, что 'enum' также дает ошибку при умножении на комплексное число. – eimrek

1
#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(); 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^