正在调用基础 class 虚拟方法,而不是子项的重写实现
Base class virutal method is being called, instead of child's override implementation
我正在用 BOOST::ODEINT 编写 ODE 积分器。它要求具有逻辑的 class 具有使用此签名 "void operator()(const std::vector &x, std::vector &dxdt, double t)".
重载的 operator()
我假装写了一个抽象class,封装了通用模型逻辑和集成器逻辑,base child会实现一些具体的方面(比如ODEINT需要的系统)。
我发现自己无法作为抽象实现class,因为代码没有编译,因为无法编写集成器的模板。所以我删除了所有纯虚函数,然后代码编译得很好,但我总是调用基本 class 方法而不是子方法的实现。
#include <vector>
#include <iostream>
#include <boost/numeric/odeint.hpp>
class BaseClass {
public:
virtual void ode(const std::vector<double> &x, std::vector<double> &dxdt, double t) {
std::cout << "Not expected." << std::endl;
};
void operator() (const std::vector<double> &x, std::vector<double> &dxdt, double t) {
std::cout << "BaseClass" << std::endl;
this->ode(x, dxdt, t);
};
void integrate() {
double t = 0, dt = 0.5;
std::vector<double> state(2, 0.0);
boost::numeric::odeint::runge_kutta4<std::vector<double>> stepper;
stepper.do_step(*this, state, t, dt);
};
};
class DerivedClass : public BaseClass {
public:
virtual void ode(const std::vector<double> &x, std::vector<double> &dxdt, double t) {
std::cout << "Expected." << std::endl;
};
};
void main() {
DerivedClass d;
d.integrate();
}
这会产生
Base Class
Not expected
我也试过制作虚拟 de 方法 operator(),但产生相同的输出。
在我写这篇文章的时候,我想我要把积分器的逻辑从模型中分离出来,但我想知道这是怎么回事。
谢谢大家!
In odeint all system functions and observers are passed by value. For example, if you call a do_step
method of a particular stepper or the integration functions, your system and your stepper will be passed by value.
问题是 动态多态性 仅在您通过 pointers/references 调用虚函数时才起作用。为此,请按照评论中的建议将 *this
包装为 std::ref
(或按照原始文档的建议将 boost::ref
包装起来)。
请注意,这项工作是因为 std::reference_wrapper
定义了一个函数调用 operator()
,它为底层对象调用相同的函数。 (对于命名成员函数,这种方法行不通。)
比较这两种情况的示例性简单现场演示是 here。
我正在用 BOOST::ODEINT 编写 ODE 积分器。它要求具有逻辑的 class 具有使用此签名 "void operator()(const std::vector &x, std::vector &dxdt, double t)".
重载的 operator()我假装写了一个抽象class,封装了通用模型逻辑和集成器逻辑,base child会实现一些具体的方面(比如ODEINT需要的系统)。
我发现自己无法作为抽象实现class,因为代码没有编译,因为无法编写集成器的模板。所以我删除了所有纯虚函数,然后代码编译得很好,但我总是调用基本 class 方法而不是子方法的实现。
#include <vector>
#include <iostream>
#include <boost/numeric/odeint.hpp>
class BaseClass {
public:
virtual void ode(const std::vector<double> &x, std::vector<double> &dxdt, double t) {
std::cout << "Not expected." << std::endl;
};
void operator() (const std::vector<double> &x, std::vector<double> &dxdt, double t) {
std::cout << "BaseClass" << std::endl;
this->ode(x, dxdt, t);
};
void integrate() {
double t = 0, dt = 0.5;
std::vector<double> state(2, 0.0);
boost::numeric::odeint::runge_kutta4<std::vector<double>> stepper;
stepper.do_step(*this, state, t, dt);
};
};
class DerivedClass : public BaseClass {
public:
virtual void ode(const std::vector<double> &x, std::vector<double> &dxdt, double t) {
std::cout << "Expected." << std::endl;
};
};
void main() {
DerivedClass d;
d.integrate();
}
这会产生
Base Class
Not expected
我也试过制作虚拟 de 方法 operator(),但产生相同的输出。
在我写这篇文章的时候,我想我要把积分器的逻辑从模型中分离出来,但我想知道这是怎么回事。
谢谢大家!
In odeint all system functions and observers are passed by value. For example, if you call a
do_step
method of a particular stepper or the integration functions, your system and your stepper will be passed by value.
问题是 动态多态性 仅在您通过 pointers/references 调用虚函数时才起作用。为此,请按照评论中的建议将 *this
包装为 std::ref
(或按照原始文档的建议将 boost::ref
包装起来)。
请注意,这项工作是因为 std::reference_wrapper
定义了一个函数调用 operator()
,它为底层对象调用相同的函数。 (对于命名成员函数,这种方法行不通。)
比较这两种情况的示例性简单现场演示是 here。