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;
}
Rufus
  • 15
  • 2
  • 8
  • 7
    That's an interesting cast. "I don't care if anything makes sense, just cast the damn thing." – Kerrek SB Jun 12 '14 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? – Rufus Jun 12 '14 at 23:44
  • 5
    Learn the language to understand what warnings mean? Why, sir, I can just cast all those warnings into silence... – Kerrek SB Jun 12 '14 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? – Kerrek SB Jun 12 '14 at 23:45
  • OK, if I put fcn_default outside, I can avoid casting... Thanks! – Rufus Jun 12 '14 at 23:48
  • You need to declare your variable before you use it, so `double (*fcn_ptr)(const double &) = NULL;` should come before the assignment in the constructor. That said, I seriously doubt this will do what you are expecting with that monster of a cast. – IllusiveBrian Jun 12 '14 at 23:48
  • @Namfuak, Not for class members. – chris Jun 12 '14 at 23:50
  • @Rufus: Hm, I was thinking of a `static` member, but either is fine. – Kerrek SB Jun 12 '14 at 23:50
  • Better: `Object() : fcn_ptr(&Object::fcn_default) {}`. Better yet: `double (*fcn_ptr)(const double &) = &Object::fcn_default;` – Kerrek SB Jun 12 '14 at 23:59

2 Answers2

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

Praetorian
  • 106,671
  • 19
  • 240
  • 328
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.

Sophit
  • 491
  • 2
  • 8