Initialize member functions via constructor

2019-09-15 07:34发布

问题:

Perhaps I am way out of left field with this question, but is it possible to define a member function via the constructor?

In my case, I am trying to write a class to perform robust model fitting (using RANSAC). I want this to be generalizable to different types of models. For example, I could use this to determine an estimate of a plane to a set of 3D points. Or, perhaps I could determine a transformation between two sets of points. In these two examples, there might need to be different error functions and different fitting functions. Instead of using a class, a static function call might look like

model = estimate(data, &fittingFunc, &errorFunc);

I'm wondering if I can have member instance for those modular functions?

Something like

class Estimator
{
    private:
        // estimation params

        double errorFunc(std::vector<dtype>, double threshold); // Leave this unimplemented
        double fittingFunc(std::vector<dtype>, Parameters p); // Leave this unimplemented

    public:
        Estimator(void (*fittingFunc(std::vector<dtype>, Parameters), void (*errorFunc(std::vector<dtype>, double));

        dtype estimate(data); // Estimates model of type dtype. Gets implemented

};

Estimator::Estimator(void (*fittingFunc(std::vector<dtype>, Parameters), void (*errorFunc(std::vector<dtype>, double))
{
    fittingFunc = fittingFunc;
    errorFunc = errorFunc;
}

I imagine I have bastardized the proper syntax in my example, but I hope the question is clear. Basically I am asking: Can the constructor accept function pointers as arguments and assign them to be the implementation of member functions?

Secondly, even if this is possible, is it considered bad form?

UPDATE: If it helps, here is MATLAB code for robust estimation that has this sort of generalizable structure I'm hoping to replicate in C++

回答1:

Can the constructor accept function pointers as arguments and assign them to be the implementation of member functions?

No. Not as member functions. But you can certainly have public member function pointers:

class Estimator
{
public:
    double (*errorFunc)(std::vector<dtype>, double threshold);
    double (*fittingFunc)(std::vector<dtype>, Parameters p);

public:
    Estimator(void (*fittingFunc(std::vector<dtype>, Parameters), void (*errorFunc(std::vector<dtype>, double))
    : errorFunc(errorFunc)
    , fittingFunc(fittingFunc)
    { }

    dtype estimate(data);    
};

For a nicer (or safer) interface, you can make the function pointers private and have a public member function which simply invokes them.


More generally, if you're okay with the overhead, you can have members of type std::function<double(std::vector<dtype>, double)> and std::function<double(std::vector<dtype>, Parameters)> and then you can use a wider variety of callables (function pointers, but also lambdas, bound member functions, etc.)



回答2:

Yes you can provide the algorithm for your fitting and error function. You could do it using pointer to function. And there is a better solution, in the standard header you will find the template std::function which can be constructed with pointer to function but also with functors or lambda expressions.

Your class would be something like this:

 #include <functional>
 class Estimator
 {
 private:
    // estimation params
    using error_func_type =   std::function<double(std::vector<dtype>,double)>;
    using fitting_func_type = std::function<double(std::vector<dtype>,Parameters p)>;
    fitting_func_type fittingFunc;
    error_func_type errorFunc;


public:
    Estimator(fitting_funct_type fit, error_funct_type err)
      :fittingFunc(fit),errorFunc(err){}

    dtype estimate(data); // Estimates model of type dtype. Gets implemented

 };