传递既没有虚拟继承也没有模板的非静态成员函数[重复]

问题描述 投票:0回答:2

如何将对象

eval
的非静态成员函数
Problem1 obj
传递给对象
Solver solver

#include<iostream>
#include<functional>

// non-templated class
struct Solver{
    std::function<void(double&, double&)>* f;
    double solve(){
        double y,x=1;
        for(long int i=0;i<10000;++i){
            (*f)(y,x); (*f)(x,y);
        }
        return y;
    }
};

// non-static class; unknown at implementation time of Solver
struct Problem1{
    double p;
    void eval(double& y, double& x){
        y = x*x - p;
    }
};

int main(){
    Problem1    obj;
    Solver      solver;
    solver.f = &(obj.eval); // pass non-static member function
    solver.solve();
}

由于应使用一个求解器来解决各种问题类的许多不同实例,因此我不想使用模板。由于解决一个问题对象可能需要多次调用

eval
,由于 C++ 中虚拟类的开销和缓慢的声誉,我不敢使用
VirtualProblem
类的虚拟继承。这在这里重要吗?我该怎么办?

c++ templates function-pointers pointer-to-member virtual-inheritance
2个回答
1
投票

这不是

std::function
的工作原理。

首先它不应该是一个指针。您不能将指向非静态成员函数的指针分配给它(尤其是它的指针)。而且你不能那样使用非静态成员函数。

为了解决您的问题,首先让

f
成为一个非指针对象:

struct Solver{
    std::function<void(double&, double&)> f;
    double solve(){
        double y,x=1;
        for(long int i=0;i<10000;++i){
            f(y,x); f(x,y);
        }
        return y;
    }
};

然后我们可以使用 lambda 在正确的对象上调用正确的函数:

solver.f = [&obj](double& a, double& b)
{
    obj.eval(a, b);
};

您还可以使用

std::bind
将函数与其对象及其参数绑定:

solver.f = std::bind(obj, &Problem1::eval, std::placeholders::_1, std::placeholders::_2); // pass non-static member function

但请注意,lambda 变体是通常推荐的方式。


另一方面,如果你想从函数返回一个值,实际上是

return
一个值。


0
投票

我想,你可以使用'std::bind'

© www.soinside.com 2019 - 2024. All rights reserved.