我正在尝试研究这个Generic object-oriented differential equations integrators class的细节但是我在编译更简单的例子时遇到了一些问题。这个想法是定义一个主类的集成器,所有其他集成方法类都是通过继承派生的。这是实现Euler方法的代码。
//file integrator.hpp
#include <iostream>
#include <vector>
#include <math.h>
#include <complex>
#include <cmath>
template <class C /* a container */, class T> class Integrator{
protected:
C statevector;
T t, h;
// a pointer to the function to be integrated
void (*return_derivs)(const C& x, const T t, C& deriv);//OK, I understand that a pointer to ODEs system is neede.
Integrator (const C&, const T, const T,
void (*)(const C&, const T, C&)); //Question: why use void(*) in place of void (*return_derivs)?
public:
virtual ~Integrator() { }
virtual void step(void) = 0;
virtual void set_step_size(T new_h) {h = new_h;}
T current_time(void) const {return(t);}
void get_state(C&, T&) const;
};
template <class C, class T, class B /* base type of C */>
class Euler : public Integrator<C,T>
{
private:
C dxdt;
public:
Euler (const C &x0, const T t0, const T h_init,
void (*dxdt_calc)(const C&, const T, C&))
: Integrator <C,T> (x0, t0, h_init, dxdt_calc),
dxdt(x0) { }
void step(void);
};
template <class C, class T, class B>
void Euler<C,T,B>::step(void) // I guess, the resolution of the Integrator class variables id needed. Consequently I modify this part of the code.
{
Integrator<C,T>::return_derivs(Integrator<C,T>::statevector,Integrator<C,T>::t,dxdt);
Integrator<C,T>::statevector += B(Integrator<C,T>::h)*dxdt;
Integrator<C,T>::t += Integrator<C,T>::h;
}
实例化Euler积分器对象的主程序:
#include <complex>
#include <valarray>
#include "integrator.hpp"
using namespace std;
namespace discretization_data
{
const complex<double> i(0,1);
unsigned int nmesh = 10;
}
void discretized_odes(const valarray<complex<double> > &psi,
const double t, valarray<complex<double> > &dpsidt)
{
using namespace discretization_data;
dpsidt[0] = i*(psi[1]-2.0*psi[0]);
dpsidt[nmesh-1] = i*(psi[nmesh-2]-2.0*psi[nmesh-1]);
for (int loop=1; loop<nmesh-1; loop++)
dpsidt[loop] = i*(psi[loop+1] - 2.0*psi[loop]
+ psi[loop-1]);
}
int main()
{
using namespace discretization_data;
// Initial conditions
valarray<complex<double> >
psi(complex<double>(1.0/nmesh), nmesh);
Euler<valarray<complex<double> >, double, complex<double> >
dSchrodinger(psi, 0.0, 0.01, discretized_odes ); //I guess the problem is here.
while (dSchrodinger.current_time() < 50)
dSchrodinger.step();
//Some output statements would be added to a real program...
}
问题是,当我编译示例时,compiller无法找到对积分器对象的引用。但我不知道问题出在哪里?
要编译我使用命令:
g++ integrator.hpp main.cpp -o main.x -lm
获取错误信息:
/tmp/ccre01X7.o: In function `Euler<std::valarray<std::complex<double> >, double, std::complex<double> >::Euler(std::valarray<std::complex<double> > const&, double, double, void (*)(std::valarray<std::complex<double> > const&, double, std::valarray<std::complex<double> >&))':
main.cpp:(.text._ZN5EulerISt8valarrayISt7complexIdEEdS2_EC2ERKS3_ddPFvS6_dRS3_E[_ZN5EulerISt8valarrayISt7complexIdEEdS2_EC5ERKS3_ddPFvS6_dRS3_E]+0x46): undefined reference to `Integrator<std::valarray<std::complex<double> >, double>::Integrator(std::valarray<std::complex<double> > const&, double, double, void (*)(std::valarray<std::complex<double> > const&, double, std::valarray<std::complex<double> >&))'
collect2: error: ld returned 1 exit status
答案 0 :(得分:0)
假设您发布了完整的代码 - 没有实现:
Integrator (const C&, const T, const T,
void (*)(const C&, const T, C&)); //Question: why use void(*) in place of void (*return_derivs)?
在您提供的.hpp文件中。由于Integrator
是一个类模板,您必须:
Integrator
类,并在.cpp文件中为这些特定参数实现构造函数。我猜你想要第一个选择。
至于上面评论中发布的问题 - 不完全确定你在问什么。它是一个构造函数的声明,它接受一个指向函数的指针返回void并接受const C&
,const T&
和C&
作为参数。它似乎将用于初始化return_derivs。你想如何在一个应该设置它的构造函数中使用变量?
答案 1 :(得分:0)
男孩,那篇CUJ论文很久以前了! tsuki是对的,你错过了Integrator基类的实现。 CUJ很久以前就停止了发布,但是如果你想看到我们的完整代码ftp://ftp.drdobbs.com/sourcecode/cuj/,他们的代码档案仍然可以在Dobb博士的网站上找到。我们的文章发表在2003年11月的期刊上。我还将我们的代码放在我的研究网站上:http://people.uleth.ca/~roussel/data/。