0

I have a class and one of its member functions is actually a function pointer. That way the user can overwrite what does this function do. I unfortunately have some difficulties running this function. I use g++ to compile.

Below is the code:

    #include <iostream>

    using namespace std;

    double fcn_mod(const double &phit){
        return 1.2+phit;
    }

    class Object{
        public:
            Object() {
                fcn_ptr = (double (*)(const double &)) &Object::fcn_default;
            }
            double (*fcn_ptr)(const double &) = NULL;

        private:
            double fcn_default(const double &phit){
                return 3.2+phit;
            }
    };


    int main(){

        Object test1,test2;

        cout << (test1.*fcn_ptr)(2) << endl; // can not compile here

        test2.fcn_ptr = &fcn_mod;
        cout << (test2.*fcn_ptr)(2) << endl; // and here

        cout << "test" << endl;
    }

The error message is:

    erreur: ‘fcn_ptr’ was not declared in this scope

+++++ UPDATE 1 +++++

Taking into account the comments, here is a cleaner version:

    #include <iostream>

    using namespace std;

    double fcn_mod(const double &phit){
        return 1.2+phit;
    }

    double fcn_default(const double &phit){
        return 3.2+phit;
    }

    class Object{
        public:
            double (*fcn_ptr)(const double &) = NULL;
            Object() {
                fcn_ptr = &fcn_default;
            }

    };


    int main(){

        Object test1,test2;

        cout << (test1.*fcn_ptr)(2) << endl; // can not compile here

        test2.fcn_ptr = &fcn_mod;
        //cout << (test2.*fcn_ptr)(2) << endl; // and here

        cout << "test" << endl;
    }

This one is also a better approach:

    #include <iostream>

    using namespace std;

    double fcn_mod(const double &phit){
        return 1.2+phit;
    }

    class Object{
        public:
            Object() {
                fcn_ptr = &fcn_default;
            }
            double (*fcn_ptr)(const double &) = NULL;
        private :
            static double fcn_default(const double &phit){
                return 3.2+phit;
            }
    };

    int main(){
        Object test1,test2;
        cout << (test1.*fcn_ptr)(2) << endl; // can not compile here
        test2.fcn_ptr = &fcn_mod;
        cout << (test2.*fcn_ptr)(2) << endl; // and here
        cout << "test" << endl;
    }

+++++ UPDATE 2 +++++

What if I want to access members of the class through this function?

The simplest solution will not be able to give access to the class member (aa) from within fcn_mod.

#include <iostream>

using namespace std;

double fcn_mod(const double &phit){
    return 1.2 + phit + aa*0.001; // can not compile here
}

class Object{
    public:
        Object() {
            fcn_ptr = &Object::fcn_default;
            aa = 4;
        }
        double (*fcn_ptr)(const double &) = NULL;
        double aa;

    private:
        static double fcn_default(const double &phit){
            return 3.2 + phit + aa*0.001; // and here
        }
};

int main(){
    Object test1,test2;
    cout << (test1.fcn_ptr)(2) << endl;
    test2.fcn_ptr = &fcn_mod;
    cout << (test2.fcn_ptr)(2) << endl;
    cout << "test" << endl;
}

But the solution using std::bind and std::function does not either. Can I pass a kind of "static" parameter to the function pointer?

I added a gateway function.

#include <iostream>

using namespace std;

double fcn_mod(const double &phit){
    return 1.2 + phit;
}

class Object{
    public:
        Object() {
            fcn_ptr = &Object::fcn_default;
            aa = 4;
        }
        double do_something(const double &phit){
            return this->fcn_ptr(phit+aa*0.001);
        }
        double (*fcn_ptr)(const double &);
        double aa;

    private:
        static double fcn_default(const double &phit){
            return 3.2 + phit;
        }
};

int main(){
    Object test1,test2;
    cout << test1.do_something(2) << endl; // can not compile here
    test2.fcn_ptr = &fcn_mod;
    cout << test2.do_something(2) << endl; // and here
    cout << "test" << endl;
}
9
  • 7
    That's an interesting cast. "I don't care if anything makes sense, just cast the damn thing." Commented Jun 12, 2014 at 23:41
  • If I don't cast, I have a warning and it is just to allow me to point to a function that is not part of any class. How would you do it? Commented Jun 12, 2014 at 23:44
  • 5
    Learn the language to understand what warnings mean? Why, sir, I can just cast all those warnings into silence... Commented Jun 12, 2014 at 23:44
  • Tip: Does fcn_default require access to the object state? If not, what kind of member functions are there that aren't tied to any particular object's state? Commented Jun 12, 2014 at 23:45
  • OK, if I put fcn_default outside, I can avoid casting... Thanks! Commented Jun 12, 2014 at 23:48

2 Answers 2

5

What you're trying to do isn't going to work. A pointer to a non-static member function is not the same as a pointer to a free function, because unlike the latter, the former must be invoked on an instance of the object. So you cannot declare a variable of one type and assign a pointer to a function of the other type to it.

First, let's fix half your code:

Since fcn_ptr is a pointer to member function, it's definition needs to be:

double (Object::*fcn_ptr)(const double &) = NULL;

Then, the cast in your constructor is invalid. You're attempting to cast a pointer to a member function to a pointer to a free function. Get rid of the cast.

Object() : fcn_ptr(&Object::fcn_default)
{}

Finally, when you invoke fcn_ptr, you can't simply conjure it out of thin air. It is a data member of Object and so you need an instance of the class to access fcn_ptr. So call it as:

(test1.*(test1.fcn_ptr))(2)

Make all these changes, and half your code will compile and produce the correct result. Live demo


The other half, where you try to assign a pointer to a free function to fcn_ptr still won't work because of the reasons stated earlier. The way to fix this is to use std::function instead of a function pointer.

class Object{
    public:
        Object() : fcn_ptr(std::bind(&Object::fcn_default, this, std::placeholders::_1))
        {}
        std::function<double(double const&)> fcn_ptr;

    private:
        double fcn_default(const double &phit){
            return 3.2+phit;
        }
};

And then use it as:

cout << (test1.fcn_ptr)(2) << endl;

test2.fcn_ptr = &fcn_mod;
cout << (test2.fcn_ptr)(2) << endl;

Live demo

Sign up to request clarification or add additional context in comments.

Comments

0

You do not have a class with a "function which is a function pointer", but rather a class with a data member which is a function pointer. This is an important distinction as the function won't receive a this pointer, nor will it have access to protected or private members.

You've declared your function pointer correctly, but you need to use the .fcn_ptr rather than .*fcn_ptr. I believe this is sufficient to solve your problem.

Do note that you're using old C style function pointer syntax. You may want to learn the C++ function pointer alternatives including std::function.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.