C++ calling a class function inside another function

15,765

The more general approach is to drop these 1970s function pointers and use technology from this millennium:

#include <functional>

double integrate (double a, double b, int steps, std::function<double(double)> f)
{
    // ...
}

class A
{
    double calculate_parameter(double t);

    double get_result(double x)
    {
        using std::placeholders::_1;

        double sum = 0;
        for (int i = 0; i < data_size; i++) {
            sum = sum + integrate(
                to_data[i],
                from_data[i],
                1,
                std::bind(&A::calculate_parameter, this, _1)
            );
        }

        return sum;
    }
};

This provides a simple and easy way to bind to essentially any kind of function, and to "bake in" the this pointer for member functions to the functor itself, without requiring any magic at the eventual callsite (i.e. within integrate, which literally just has to call f!).


An even more "modern" way to do this is to wrap the call to calculate_parameter in a lambda:

template <typename Callable>
double integrate (double a, double b, int steps, Callable f)
{
    // ...
}

class A
{
    double calculate_parameter(double t);

    double get_result(double x)
    {
        double sum = 0;
        for (int i = 0; i < data_size; i++) {
            sum = sum + integrate(
                to_data[i],
                from_data[i],
                1,
                [this](double x) { return this->calculate_parameter(x); }
            );
        }

        return sum;
    }
};

Notice that I've replaced std::function<double(double)> with a deduced template argument Callable; you don't have to do this, but it's conventional not to force a lambda-to-std::function conversion when you don't have to. (Personally I quite like being able to mandate that f will take a double and return a double, without having to rely on its usage to check this.)

Share:
15,765
AnotherCodingEnthusiast
Author by

AnotherCodingEnthusiast

Updated on June 04, 2022

Comments

  • AnotherCodingEnthusiast
    AnotherCodingEnthusiast almost 2 years

    I am trying to call an outside function (that takes functions as inputs) inside the class by giving class member functions as it's parameters. My code is as follows:

    using namespace std;
    // This is my external function
    double integrate (double a, double b, int steps, double (*func)(double)){
        // code for integration using function pointer
    };
    
    Class A
    {
        protected:
            vector<double> to_data, from_data;
            int data_size;
    
        public:
            A (); // constructor
    
            double calculate_parameter(double t){
                // some class member function that makes use of other class members
            };
    
            double get_result(double x){
                double sum = 0;
            for (int i=0;i<data_size;i++){
               // this is basically what causes the error
                sum = sum + integrate(to_data[i],from_data[i],1,calculate_parameter);
            }
     };
    
    }
    

    However, it shows me error that the function calculate_parameter cannot be converted. I figured out a way to solve this would be to modify the external function such that it takes a class object as well. Is there a way to do this without instantiating a new class object? Thanks in advance!

  • Lightness Races in Orbit
    Lightness Races in Orbit over 9 years
    @nurettin: "Self-gratification"?? What?? Try not to be so rude, thanks.
  • Ali Kazmi
    Ali Kazmi over 9 years
    quite precise and best answer
  • Puppy
    Puppy over 9 years
    This millenium technology is a lambda, not that archaic bind stuff.
  • Lightness Races in Orbit
    Lightness Races in Orbit over 9 years
    @Puppy: Yeah, true. Though std::bind was added to the language in 2011, which was only three years ago.
  • nurettin
    nurettin over 9 years
    @LightnessRacesinOrbit Sorry if my correction comment was rude. But I still think this answer itself is rude for what it's worth, and the edit was justified (and has more info/keywords than plain sarcasm)
  • Puppy
    Puppy over 9 years
    @LightnessRacesinOrbit: Yet more evidence that the Committee is nuts. Also, you don't need to refer to this explicitly in the lambda- a lambda capturing this is effectively a member lambda as far as things like name lookup goes.
  • Lightness Races in Orbit
    Lightness Races in Orbit over 9 years
    @nurettin: What's "rude" about a plain statement of fact that directly addresses the things the OP has said? Perhaps you would prefer that I sprinkle the answer with smiley faces and hashtags?
  • nurettin
    nurettin over 9 years
    @LightnessRacesinOrbit In this answer and apparently many others before this, you mock coding styles almost daily on stackoverflow as some sort of twisted repetitive ritualistic behavior. Getting a "+1" does not justify this action. We will never come to an understanding as civilized people so long as you do not acknowledge the difference between fact and mockery.
  • Lightness Races in Orbit
    Lightness Races in Orbit over 9 years
    @nurettin: Perhaps you need to learn the difference between fact and mockery: it is a fact that function pointers were used in the 1970s, and it is a fact that std::bind and lambdas are both pieces of technology added to C++ in this millennium. I don't know why you've got such a problem with identifying those facts but I'll ask you to drop the ridiculous attacks: what do upvotes have to do with it? Why am I "twisted"? Where does this "almost daily" come from? (I'd love to see your data and evidence for that allegation).
  • nurettin
    nurettin over 9 years
    @LightnessRacesinOrbit So if I use facts to mock people, that makes it OK. Well, thanks for the lesson. I will drop all accusations and apologize for any indecent behavior.
  • Lightness Races in Orbit
    Lightness Races in Orbit over 9 years
    @nurettin I'm not "mocking" anyone. By contrast you are being really quite rude to me...