正在调用基础 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(),但产生相同的输出。

在我写这篇文章的时候,我想我要把积分器的逻辑从模型中分离出来,但我想知道这是怎么回事。

谢谢大家!

引自relevant documentation

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