+ Reply to Thread
Page 1 of 2
1 2 LastLast
Results 1 to 10 of 19

Thread: Function Pointers

  1. #1
    Code Warrior marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89's Avatar
    Join Date
    Jul 2008
    Location
    Somewhere that is shorter to write than "In the gloomy shadows of my personal namespace"
    Posts
    10,741
    Blog Entries
    2

    Lightbulb Function Pointers

    C++ Function Pointers

    Now, as C++ programmers, we love writing messy, unreadable and advanced-looking code that will leave beginners head-scratching for hours. Function pointers happens to be a great tool for achieving maximum confusion and frustration. Did I mention that they are actually useful too?

    So, what on earth is a function pointer? Function pointers are simply pointers that point to functions, or to be more specific, function addresses. Let us take a few seconds and just think about that. Done? Then we will move on. Function pointers can be very useful, and very elegant, as we will see, but their syntax is quite awkward and messy. Let us take a look at one simple function pointer right here:

    Code:
    int (*pMyFuncPointer) (char, int);
    pMyFuncPointer is our function pointer. Kind of like normal pointers - who point to a specific datatype - function pointers point to specific function signatures. In this case, we have a pointer which is able to point to any function taking a char and an int as arguments, and returns an int.

    Let's see our pointer in action, shall we?

    Code:
    #include <iostream>
    
    int Foo(char, int); // First we need a function with matching signature
    int (*pMyFuncPointer) (char, int) = &Foo; // We declare our function pointer, and initializes it to point at Foo. 
                                              // The reference operator can usually be omitted, but to write portable code, 
                                              // leave it there. It's also a bit clearer, IMO
    
    int main()
    {
    	(*pMyFuncPointer)('d', 9); // Calls Foo.
    	pMyFuncPointer('d', 9); // Also calls Foo
    		
    	system("PAUSE");	
    	return 0;
    }
    
    int Foo(char c, int i)
    {
    	std::cout << "I'm Foo. It's a funny name" << 
           "\nVariable c: " << c << "\nVariable i: " << i << std::endl;
    	return 0;
    }
    This program uses the function pointer pMyFuncPointer to call the function Foo, which prints some text together with its arguments. Are you still with me?

    Ok, so function pointers can be used to call functions. There is a lot more to it, but before we go any further, I would like to show you a few other types of function pointers. The previous example would work in C, except from the std::cout part, but the example below includes classes, and is limited to C++ programmers:

    Code:
    #include <iostream>
    
    class FooClass
    {
    public:
           void Foo1(int i) {std::cout << "Foo1's integer: " << i << std::endl;} 
           void FooConst(int i) const {std::cout << "FooConst's integer: " << i << std::endl;}
    };
    
    int main()
    {
        /* ASSIGNING TO CLASS MEMBER FUNCTIONS */
        void (FooClass::*pFoo)(int) = NULL;
        void (FooClass::*pFooConst)(int) const = NULL;        
        
        pFoo = &FooClass::Foo1;             
        pFooConst = &FooClass::FooConst;    
            
        /* CALLING CLASS MEMBER FUNCTIONS */
        FooClass instance1;       
        (instance1.*pFoo)(67);        
        (instance1.*pFooConst)(57);
           
        FooClass* instance2 = new FooClass;  
        (instance2->*pFoo)(47);       
        (instance2->*pFooConst)(37);               
        delete instance2;	
        
        system("PAUSE");	
        return 0;
    }
    The example basically shows how to assign a pointer to a class member function, here in two steps (initializing to NULL, then assigning), and how to call these functions.

    It is time to move on a bit. To begin with, function pointers can be compared, like other variables. Have a look at this:

    Code:
    #include <iostream>
    
    void (*pFoo)(void) = NULL;
    
    void Foo(void)
    {
        pFoo = &Foo;    
    }
    
    int main()
    {
        Foo();
        
        if(pFoo == &Foo) // Comparison of a function pointer and a function address
            std::cout << "You bastard, you changed my variable!" << std::endl;    
            
        system("PAUSE");	
        return 0;
    }
    You can also do comparisons like

    Code:
    if(pFoo != NULL)
    	// ...
    Now we will look at how one can pass function pointers as arguments to a function. Here is a classic example:

    Code:
    #include <iostream>
    
    float Divide(float num1, float num2) {return num1 / num2;}
    float Multiply(float num1, float num2) {return num1 * num2;}
    float Minus(float num1, float num2) {return num1 - num2;}
    float Plus(float num1, float num2) {return num1 + num2;}
    
    float Calc(float num1, float num2, float (*pCalcMethod)(float, float))
    {
        return pCalcMethod(num1, num2);
    }
    
    int main()
    {
        float result = Calc(50, 25, &Plus);
        //float result = Calc(50, 25, &Minus);
        //float result = Calc(50, 2, &Multiply);
        //float result = Calc(50, 2, &Divide);
    
        std::cout << "Result: " << result << std::endl;
        system("PAUSE");	
        return 0;
    }
    When we call Calc, we specify (using function pointers) what kind of operation we want to perform on the numbers. Notice how one declares a function pointer as an argument (not very surprising, really).

    Code:
    float Calc(float num1, float num2, float (*pCalcMethod)(float, float))
     // ...
    The function Calc accepts two floats, and a pointer to a function which accepts two floats, and returns a float.

    We keep moving, this time to returning function pointers from functions. And this is a true mess. Check it out:

    Code:
    #include <iostream>
    
    float Multiply(float num1, float num2) {return num1 * num2;} 
    float (*GetFPointer(void))(float, float) {return &Multiply;}
    
    int main()
    {
        float (*pMultFunc)(float, float) = GetFPointer();
        
        float result = pMultFunc(2, 5);
        
        std::cout << "Result: " << result << std::endl;
    	
        system("PAUSE");	
        return 0;
    }
    This is the tough one, right?

    Code:
    float (*GetFPointer(void))(float, float)
     // ...
    It means that GetFPointer is a function which takes a void (i.e. nothing), and returns a pointer to a function which takes two floats and returns a float. Because of the messy syntax, this is usually simplified through an innocent typedef.

    Code:
    #include <iostream>
    
    typedef float(*pFunc)(float, float);
    
    float Multiply(float num1, float num2) {return num1 * num2;} 
    pFunc GetFPointer(void) {return &Multiply;}
    
    int main()
    {
        float (*pMultFunc)(float, float) = GetFPointer();
        
        float result = pMultFunc(2, 5);
        
        std::cout << "Result: " << result << std::endl;
    	
        system("PAUSE");	
        return 0;
    }
    Because of this typedef:

    Code:
    typedef float(*pFunc)(float, float);
    There is now a type (pFunc) which declares a pointer to a function that takes two floats and returns a float. Exactly what we need. We can even use it to declare our function pointer in main:

    Instead of:

    Code:
    float (*pMultFunc)(float, float) = GetFPointer();
    We can write:

    Code:
    pFunc pMultFunc = GetFPointer();
    Not as messy, fun and confusing, but it does the job.

    Now, to another subject: Arrays of function pointers. These were really useful in C. While our fancy C++ classes were not around, old C-structs could still contain arrays of function pointers. Don't laugh. These arrays are very useful, or at least cool.

    Code:
    #include <iostream>
    
    float Plus(float num1, float num2) {return num1 + num2;}
    float Minus(float num1, float num2) {return num1 - num2;}
    float Multiply(float num1, float num2) {return num1 * num2;}
    float Divide(float num1, float num2) {return num1 / num2;}
    
    float Calc(float num1, float num2, float (*pCalcMethod)(float, float))
    {
        return pCalcMethod(num1, num2);
    }
    
    int main()
    {
        float (*pFoo[])(float, float) = {&Plus, &Minus, &Multiply, &Divide};    
        
        float result;
        
        for(int i = 0; i < 4; ++i)
        {
            result = Calc(10, 2, pFoo[i]);
            std::cout << "Result: " << result << std::endl;
        }
    	
        system("PAUSE");	
        return 0;
    }
    The above program illustrates the concept. Actually, it just modifies our calc-program from earlier. Now, we run through the different calculations using an array of function pointers:

    Code:
    float (*pFoo[])(float, float) = {...};
    The braces after *pFoo tells us: "Hey! It's an array!" The size is determined from the number of initializing elements in the following curly braces "{...}", just like a normal array. We can also write e.g.

    Code:
    float (*pFoo[10])(float, float);
    Thus declaring an array of 10 function pointers.

    Array declarations like this are - by the way - often made simpler by the use of a typedef:

    Code:
    #include <iostream>
    
    typedef float(*pFooType)(float, float);
    
    float Plus(float num1, float num2) {return num1 + num2;}
    float Minus(float num1, float num2) {return num1 - num2;}
    float Multiply(float num1, float num2) {return num1 * num2;}
    float Divide(float num1, float num2) {return num1 / num2;}
    
    float Calc(float num1, float num2, float (*pCalcMethod)(float, float))
    {
        return pCalcMethod(num1, num2);
    }
    
    int main()
    {
        pFooType pFoo[] = {&Plus, &Minus, &Multiply, &Divide}; // Made simpler using typedef
        
        float result;
        
        for(int i = 0; i < 4; ++i)
        {
            result = Calc(10, 2, pFoo[i]);
            std::cout << "Result: " << result << std::endl;
        }
    	
        system("PAUSE");	
        return 0;
    }
    Now, guys, this is the last thing I want to show you. It is pretty close to a C++ syntax nightmare (I did that on purpose), but it should sum up what we have been through so far. The source file for this program (the one below) can be downloaded below.

    Code:
    /* 
        
        Program:        FunctionPointersTestStuff
        Program type:   Useless
        Copyright:      marwex89 - www.codecall.net
        
        This program defines a class which uses a vector to store function pointers. 
        The program adds function pointers to this vector through the use of function pointers,
        and later retrieves them (using function pointers) and calls the functions they point to.
        
    */
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    
    // Useless function for adding two characters into a string, and add the number 2
    const std::string AddToStr_1(char a, char b) 
    {
        std::ostringstream oss;
        oss << a << b << 1;
        return oss.str();     
    }
    
    // Useless function for adding two characters into a string, and add the number 2
    const std::string AddToStr_2(char a, char b) 
    {
        std::ostringstream oss;
        oss << a << b << 2;
        return oss.str();
    }
    
    // Useless function for adding two characters into a string, and add the number 3
    const std::string AddToStr_3(char a, char b) 
    {
        std::ostringstream oss;
        oss << a << b << 3;
        return oss.str();
    }
    
    // Useless function for adding two characters into a string, and add the number 4
    const std::string AddToStr_4(char a, char b) 
    {
        std::ostringstream oss;
        oss << a << b << 4;
        return oss.str();
    }
    
    // Useless function for adding two characters into a string, and add the number 5
    const std::string AddToStr_5(char a, char b) 
    {
        std::ostringstream oss;
        oss << a << b << 5;
        return oss.str();
    }
    
    // Useless class for storing function pointers
    class CFuncPointerStorage
    {   
    private:
        
        std::vector<const std::string(*)(char, char)> vec;
            
    public:
            
        const std::string(*GetFunctionPointer(unsigned int index))(char, char) const
        {
            if(index <= vec.size())
                return vec[index];
            else
            {
                std::cerr << "Weird error occured, you need a new computer." << std::endl;
                return NULL;
            }
        } 
        
        void SetFunctionPointer(const std::string(*pFunctionPointer)(char, char), unsigned int index)
        {
            if(index < vec.size())
                vec[index] = pFunctionPointer;
            else
                vec.push_back(pFunctionPointer);
        }           
    };
    
    // Using the stuff
    int main()
    {
        CFuncPointerStorage* fpStorage = new CFuncPointerStorage;
        
        // Put function pointers into storage object
        const std::string(*fpArray[])(char, char) = {&AddToStr_1, &AddToStr_2, &AddToStr_3, &AddToStr_4, &AddToStr_5};    
        for(int i = 0; i < 5; ++i)
            fpStorage->SetFunctionPointer(fpArray[i], i);
        
        // Get them back and perform calls
        for(int i = 0; i < 5; ++i) 
            std::cout << (*(fpStorage->GetFunctionPointer(i)))('I', 'T') << std::endl;
        
        delete fpStorage;
        	
        system("PAUSE");	
        return 0;
    }
    Well, my friends, that was it. I have attached the code for the last program (the one above). Hopefully you found this tutorial helpful - feel free to comment and +rep - I appreciate it. See you later

    main.cpp
    Hey! Check out my new Toyota keyboaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

  2. #2
    Super Moderator WingedPanther has much to be proud of WingedPanther has much to be proud of WingedPanther has much to be proud of WingedPanther has much to be proud of WingedPanther has much to be proud of WingedPanther has much to be proud of WingedPanther has much to be proud of WingedPanther has much to be proud of WingedPanther has much to be proud of WingedPanther's Avatar
    Join Date
    Jul 2006
    Age
    37
    Posts
    13,155
    Blog Entries
    59

    Re: Function Pointers

    A nice a thorough job. +rep
    CodeCall Blog | CodeCall Wiki
    Programming is a branch of mathematics.
    My CodeCall Blog | My Personal Blog

  3. #3
    Code Warrior marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89's Avatar
    Join Date
    Jul 2008
    Location
    Somewhere that is shorter to write than "In the gloomy shadows of my personal namespace"
    Posts
    10,741
    Blog Entries
    2

    Re: Function Pointers

    Thank you winged.

    Posted via CodeCall Mobile

  4. #4
    Administrator Jordan is a name known to all Jordan is a name known to all Jordan is a name known to all Jordan is a name known to all Jordan is a name known to all Jordan is a name known to all Jordan's Avatar
    Join Date
    Nov 2005
    Location
    Hendersonville, NC
    Posts
    24,750
    Blog Entries
    97

    Re: Function Pointers

    Very nice tutorial! I liked the introduction, .

    +rep

  5. #5
    Guru ArekBulski is just really nice ArekBulski is just really nice ArekBulski is just really nice ArekBulski is just really nice ArekBulski is just really nice ArekBulski's Avatar
    Join Date
    Mar 2009
    Posts
    1,379

    Re: Function Pointers

    I enjoyed reading your tutorial. I have this feeling that says functions and function pointers in C++ are somewhat close to delegates and events in C#, but they are not exactly the same. Will surely +rep you.

  6. #6
    Code Warrior marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89's Avatar
    Join Date
    Jul 2008
    Location
    Somewhere that is shorter to write than "In the gloomy shadows of my personal namespace"
    Posts
    10,741
    Blog Entries
    2

    Re: Function Pointers

    Thank you guys

    Posted via CodeCall Mobile

  7. #7
    Guru MathX has a spectacular aura about MathX has a spectacular aura about MathX's Avatar
    Join Date
    Oct 2008
    Location
    Kosovo
    Age
    19
    Posts
    4,007

    Re: Function Pointers

    +Rep 4 this little bitch!

  8. #8
    Code Warrior marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89's Avatar
    Join Date
    Jul 2008
    Location
    Somewhere that is shorter to write than "In the gloomy shadows of my personal namespace"
    Posts
    10,741
    Blog Entries
    2

    Re: Function Pointers

    Thank you MathXpert I appreciate it
    Hey! Check out my new Toyota keyboaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

  9. #9
    Code Warrior
    /////////|||||\\\\\\\\\
    amrosama is a splendid one to behold amrosama is a splendid one to behold amrosama is a splendid one to behold amrosama is a splendid one to behold amrosama is a splendid one to behold amrosama is a splendid one to behold amrosama is a splendid one to behold amrosama's Avatar
    Join Date
    Aug 2007
    Location
    Pyramids, Egypt
    Age
    21
    Posts
    8,635
    Blog Entries
    12

    Re: Function Pointers

    wow!
    thats a big one, nice read ++rep
    yo homie i heard you like one-line codes so i put a one line code that evals a decrypted one line code that prints "i love one line codes"
    Code:
    eval(base64_decode("cHJpbnQgJ2kgbG92ZSBvbmUtbGluZSBjb2Rlcyc7"));

  10. #10
    Code Warrior marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89 is a glorious beacon of light marwex89's Avatar
    Join Date
    Jul 2008
    Location
    Somewhere that is shorter to write than "In the gloomy shadows of my personal namespace"
    Posts
    10,741
    Blog Entries
    2

    Re: Function Pointers

    Thank you amr Funny rep comment
    Hey! Check out my new Toyota keyboaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

+ Reply to Thread
Page 1 of 2
1 2 LastLast

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

     

Similar Threads

  1. XML Result from PHP?
    By Ricardo-san in forum PHP Forum
    Replies: 14
    Last Post: 04-09-2009, 08:03 PM
  2. function pointers
    By porno.shome in forum Pascal/Delphi
    Replies: 5
    Last Post: 07-25-2008, 11:42 PM
  3. C++ - function pointers as a static data member.
    By G_Morgan in forum C and C++
    Replies: 3
    Last Post: 07-07-2008, 06:36 PM
  4. using Template function
    By Chinmoy in forum C Tutorials
    Replies: 4
    Last Post: 04-03-2008, 01:16 AM
  5. Derived Classes Can't Set Function Pointers
    By dargueta in forum C and C++
    Replies: 11
    Last Post: 11-05-2007, 07:04 PM