Thread: pointers to functions

  1. #1
    Registered User
    Join Date
    Apr 2011
    Posts
    62

    pointers to functions

    hey,

    I´ve been trying to use pointers to functions to alter the effect of a class function and I've apparently been using the syntax incorrectly. I've tried a few different ways and check one ref book but came out empty. If anyone could correct me I'd appreciate it:

    Code:
    class example2{
    private:
        double afterswitch(){
            cout<<"do something-02"<<endl;
            return 0.0;
        }
        double beforeswitch(){
            cout<<"do something else-02"<<endl;
            return 0.0;
        }
        double (*pf)();
    public:
        example2():pf(beforeswitch){}   //error:cannot convert from double (example::)() to double (*)()
        double workfunc(){
            return pf();
        }
        void controlfunc(){
            pf=afterswitch;             //error:cannot convert from double (example::)() to double (*)()
        }
    };
    as I side note: I was trying to do this because I (baselessly) think that a using a pointer would be more efficient regarding processing speed that having a simple if/else in the workfunc. would this be more efficient?

    Code:
    class example1{
    private:
        bool control;
    public:
        example1():control(false){}
        double workfunc(){
            if (control)
                cout<<"do something-01"<<endl;
            else
                cout<<"do something else-01"<<endl;
            return 0.0;
        }
        void controlfunc(){
            control=true;
        }
    };

  2. #2
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    You need pointers to member functions, not just pointers to functions.
    (Look the syntax up..)
    How about some C++11 syntax?
    Code:
    #include<functional>
    #include<iostream>
    
    class Foo
    {
    public:
        Foo()
        {
            foo=[]()
            {
                std::cout<<"FOO";
                return 0;
            };
        }
        void toggle()
        {
            foo=[]()
            {
                std::cout<<"BAR";
                return 1;
            };
        }
        
        std::function<double()> foo;
        
    };
    
    int main()
    {
        Foo x;
        std::cout<<x.foo()<<std::endl;
        
        x.toggle();
        
        std::cout<<x.foo();
    }
    Of course, this is all premature optimization.
    If-else should work fine here.

  3. #3
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    You don't need pointers to functions for this at all. You need either polymorphism or template specialisation.

    Okay - I'll take pity and explain why your example2 code doesn't work, and then go through better approaches.

    The reason the first example doesn't work is that what it needs is a pointer to member function, which is something distinct from a pointer to a function.

    This is a version that will do what you intend
    Code:
    class example2{
    private:
        double afterswitch(){
            cout<<"do something-02"<<endl;
            return 0.0;
        }
        double beforeswitch(){
            cout<<"do something else-02"<<endl;
            return 0.0;
        }
        double (example2::*pf)();                //   pf is a pointer to a member function not a pointer to a function
    public:
        example2():pf(&example2::beforeswitch){}    //   pf is initialised as the address of a member function
        double workfunc(){
            return (this->*pf)();                  //  call syntax for pointer to member
        }
        void controlfunc(){
            pf=&example2::afterswitch;             //   note how pf is reassigned
        }
    };
    The thing you're not understanding is that a non-static member function needs to be called in context of an object: some_object.member_function(). Since a member function is a different beast from a non-member function, a pointer to a member function and a pointer to a function are distinct types.

    The mechanism for initialising such pointers is different (you need to use the full name example2::beforeswitch, rather than the unqualified name beforeswitch) and the ampersand is also necessary (whereas it is implied when converting a normal function name into a pointer to function).

    Lastly, the calling syntax is different. If pf has been initialised to &example2::beforeswitch, then calling it via "(some_pointer_to_object->*pf)()" has the same effect as "some_pointer_to_object->beforeswitch()". The reason for the brackets around (this->*pf) is related to rules of operator precedence.



    However, all that said, pointers to member functions have their uses (which I won't go into) but polymorphism and template specialisation are both better (less error prone) alternatives.

    Polymorphism could be utilised thus;
    Code:
    class Base
    {
         public:
             Base() {};
             virtual double do_something() = 0;
             virtual ~Base();
    };
    
    class Before: public Base
    {
         public:
             Before() : Base() {};
     
             double do_something();
    };
    
    double Before::do_something()
    {
        std::cout << "Before\n";
        return 0.0
    }
    
    class After: public Base
    {
         public:
             After() : Base() {};
     
             double do_something();
    };
    
    double After::do_something()
    {
        std::cout << "After\n";
        return 0.0
    }
    
    int main()
    {
         Base *x = new Before();
         x->do_something();
         Base *y = new After();
         y->do_something();
    
         delete x;      // clean up.    Note that Base's destructor must be virtual for this to work.
         delete y;
    }
    Note that there is no "if()" statement in sight.

    The advantage of the inheritance approach is that you can have any number of different classes derived from Base. And the compiler takes care of working out which function to call. In fact, the only decision you have to make is which type of object to create - the act of creating an object automatically associates that object with the correct function to call (Before::do_something() or After::do_something() respectively).

    Base, in the above, is described as a "polymorphic base class".

    The efficiency gain in this, if any, is not related to using a pointer. It is related to the fact that, for both objects x and y, the decision about what function to call is typically determined when the object is created, not when your code attempts to call the function.


    If you want to have the decision made at compile time, then use template specialisation. For example;
    Code:
    template<int n> struct Example;
    
    template<> struct Example<1>
    {
         double do_something() {std::cout << "Example 1\n"; return 0.0;};
    };
    
    template<> struct Example<2>
    {
         double do_something() {std::cout << "Example 2\n"; return 0.0;};
    };
    
    int main()
    {
        Example<1> x;
        x.do_something();     // will call the first version of do_something() above
    
        Example<2> y;
        y.do_something();     // will call the second version of do_something() above
    
        Example<3> z;          //   will result in compilation error since Example<3> has not been defined.
        z.do_something();     //
    
        return 0;   
    }
    In this case, the decision about which function is determined when creating the object. The decision about what object to create is fixed at compile time.
    Last edited by grumpy; 09-12-2013 at 06:45 AM.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  4. #4
    Registered User
    Join Date
    Apr 2011
    Posts
    62
    thaks for the help

    I actually need the function to change operations after the object is declared...i.e.:
    the object is declared... the function does one thing every time its called until the control function is called, and then it starts doing something else.

    so both polymorfism and templates are unable to do what I want if I understood correctly. however, since I'm not used to either concept I apreeciate you showing me how it works and thank you for taking the time.

  5. #5
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by killme View Post
    I actually need the function to change operations after the object is declared...i.e.:
    the object is declared... the function does one thing every time its called until the control function is called, and then it starts doing something else.
    You're definitely thinking at the wrong level of abstraction.

    It is not difficult to create a new object with required behaviour, copy any relevant state across from old object to new object, and release the old object (which has the behaviour no longer needed).

    That would achieve a change of mode much more easily than playing with pointers to members.

    Polymorphism is a brilliant enabler of that.

    Consider, for example;
    Code:
        Car *car = new GogoMobile;
    
        car->drive();      // a unexciting drive
    
        Car * new_car = new Ferrari(car->owners_personal_items());
        delete car;
        car = new_car;
    
        car->drive();      // an exciting drive
    I'm reasonably confident that the two calls of car->drive() would produce different visible behaviours.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  6. #6
    Registered User
    Join Date
    Apr 2011
    Posts
    62
    I'm still pretty unexperienced with object oriented programing but I'm taking a look at inheritance in C++ Primer and I'll see what I can do. Thanks for the help

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    If statements certainly aren't slow. In fact, function pointers (and std::function which goes through hoops of hurdles) are most likely slower than if statements because the compiler can often not inline such function calls.
    But again, this is premature optimization. As a rule of thumb, use algorithmic complexity in mind when building your program, but beside that, avoid making "optimized assumptions" until you actually profile the code.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Quote Originally Posted by killme View Post
    thaks for the help

    I actually need the function to change operations after the object is declared...i.e.:
    the object is declared... the function does one thing every time its called until the control function is called, and then it starts doing something else.

    so both polymorfism and templates are unable to do what I want if I understood correctly. however, since I'm not used to either concept I apreeciate you showing me how it works and thank you for taking the time.
    I would do this with composition (read up on Composition over Inheritance and the Strategy Pattern).

    I.e. what I would do is encapsulate the changing code as different implementations of a behavior interface, and your object holds a pointer to a behavior. Switching behavior at runtime is as easy as freeing the old behavior and creating a new one.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Functions and pointers
    By vidioholic in forum C Programming
    Replies: 1
    Last Post: 10-25-2007, 07:46 PM
  2. Functions and pointers
    By DOMINIC in forum C++ Programming
    Replies: 2
    Last Post: 04-01-2005, 03:05 PM
  3. Functions and pointers.
    By Hulag in forum C++ Programming
    Replies: 10
    Last Post: 03-28-2005, 08:46 PM
  4. Replies: 1
    Last Post: 01-20-2002, 11:50 AM
  5. Pointers to functions
    By Leeman_s in forum C++ Programming
    Replies: 1
    Last Post: 12-24-2001, 09:27 PM