A nice a thorough job. +rep
Thread: 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:
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.Code:int (*pMyFuncPointer) (char, int);
Let's see our pointer in action, shall we?
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?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; }
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:
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.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; }
It is time to move on a bit. To begin with, function pointers can be compared, like other variables. Have a look at this:
You can also do comparisons likeCode:#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; }
Now we will look at how one can pass function pointers as arguments to a function. Here is a classic example:Code:if(pFoo != NULL) // ...
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:#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; }
The function Calc accepts two floats, and a pointer to a function which accepts two floats, and returns a float.Code:float Calc(float num1, float num2, float (*pCalcMethod)(float, float)) // ...
We keep moving, this time to returning function pointers from functions. And this is a true mess. Check it out:
This is the tough one, right?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; }
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:float (*GetFPointer(void))(float, float) // ...
Because of this 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; }
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:Code:typedef float(*pFunc)(float, float);
Instead of:
We can write:Code:float (*pMultFunc)(float, float) = GetFPointer();
Not as messy, fun and confusing, but it does the job.Code:pFunc pMultFunc = GetFPointer();
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.
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:#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 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[])(float, float) = {...};
Thus declaring an array of 10 function pointers.Code:float (*pFoo[10])(float, float);
Array declarations like this are - by the way - often made simpler by the use of a typedef:
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:#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; }
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 laterCode:/* 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; }
main.cpp
Hey! Check out my new Toyota keyboaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
A nice a thorough job. +rep
CodeCall Blog | CodeCall Wiki
Programming is a branch of mathematics.
My CodeCall Blog | My Personal Blog
Thank you winged.
Posted via CodeCall Mobile
Very nice tutorial! I liked the introduction,.
+rep
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.![]()
proudly presenting my personal website and game website: F1Simulation. a thrilling Managed DirectX racing game... also my Ask Me
look at my tutorials about cropping images and Mono: bundling Mono with programs and lambda expressions
Thank you guys
Posted via CodeCall Mobile
+Rep 4 this little bitch!
Thank you MathXpertI appreciate it
![]()
Hey! Check out my new Toyota keyboaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

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"));
Thank you amrFunny rep comment
![]()
Hey! Check out my new Toyota keyboaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
There are currently 1 users browsing this thread. (0 members and 1 guests)