Using Function Pointers
This article describes how to use function pointers in various ways to increase the performance and/or the readability of your code. I will try to make this as easy to understand as possible for people just learning C or C++ or people that have not learned about function pointers yet. Functions pointers can be a little intimidating for people just learning programming. I remember when I was first learning C, just the concept of pointers was vague enough for me without having to worry about what the heck a pointer to a function was. For this reason I think most people skipped learning about them in order to preserve their sanity. However they are actually very useful. What are function pointers?Function pointers are variables that point to a function, and can be used to call that function. On the surface this may not seem that useful but I will describe a few things I have used them for. How to use themUsing function pointers is relatively simple easy, assuming you are familiar with pointers. The following code defines a pointer to the function that is declared. int set_number(int a, int *b); //The type in front matches the function return type, and the types in back //match the argument list. int (*funcpointer)(int, int *); //Assign the function to the pointer. funcpointer = set_number; //Now call the function int a = (*funcpointer)(5, &someint); There, that isn't so hard now is it? There are a few different ways you can do this, so if you see someone doing this a slightly different way don't worry. I use this way because it is most like the syntax necessary to use function pointers within a C++ class, which I will describe next. How to use function pointers within a classUsing function pointers within a class can greatly improve the usefulness and adaptability of a class. However it is a bit harder to get them working, especially if you are used to the shorthand version of the code that I used in the previous section. The following code defines a small class that includes a function and a pointer to that function. class CTurret { public: //This creates a function pointer named Draw void (CTurret::*Draw)(float); //The setup code in this class selects which version to draw, these //functions never get called directly in code. void DrawHiRes(float fAngle); void DrawLowRes(float fAngle); void setup() { //Depending on a setting in the code you can change where the //Draw variable points and easily change how the program flows //without going through the if statements every frame. if(HIGH_RES) Draw = DrawHiRes; else Draw = DrawLowRes; } }; ... //Calling the function (turret.*Draw)(angle); ... In this code an object (class) is created to manage a turret object. In a real game this class would hold data like position, hitpoints, and other various data that the game would need. In this sample I’ve only included things related to function pointers. The line: void (CTurret::*Draw)(float); creates a pointer to a CTurret member function that will be named Draw. The function it points to will take a single float as an argument. The lines: void DrawHiRes(float fAngle); void DrawLowRes(float fAngle); create two functions to render this object in either high or low resolution mode. If your game supported multiple detail modes you would normally have to use an if statement every frame to decide which of these functions to use when drawing. In the setup function the HIGH_RES variable is used to determine where Draw should point. HIGH_RES could be a global variable or something passed to the constructor or init function when this object was created. You can see that assigning a value to a function pointer is as easy as a normal pointer. Just pretend that the name of the function you want to point to is a variable name. And lastly you can see the syntax for calling the function using the function pointer. This is a simplified example but it does show all the steps you need to implement function pointers in any C++ object. How to use them for flow control in a state machineNow it's time to put the Fun in Function Pointer. For the longest time I didn't even think about functions pointers until I was looking at a state machine one day and wished that instead of having a switchboard of if statements that executed single functions based on the state of the program, the class would just automatically execute the function appropriate for the current state. I realized that I could accomplish this with function pointers. I will create a small example class with various member function and a state changing function that will switch the current execute function. This is a good example of how to use function pointers to control the flow of a program and eliminating the if statements that you hit every time you call that function (which can be once per frame or more). #define STATE_START 1 #define STATE_TITLE 2 #define STATE_MMENU 3 #define STATE_RUNGM 4 class CExample { int nState; public: int Startup(); int TitleScreen(); int MainMenu(); int RunGame(); int (CExample::*Execute)(); void SetState(int nNewState) { nState = nNewState; if(nState == STATE_START) Execute = Startup; else if(nState == STATE_TITLE) Execute = TitleScreen; else if(nState == STATE_MMENU) Execute = MainMenu; else if(nState == STATE_RUNGM) Execute = RunGame; } }; In this function all you have to do is call Execute() and it will call the function appropriate for the current state. This is a huge advantage because you have to call Execute every frame and this is eliminating the overhead of querying the game state. It may not seem like much, but sometimes every instruction counts. Using Function Pointers to handle optionsAnother use I have found for function pointers is using them to clean up some chunks of code where user selectable options may significantly alter what a function needs to do. For example, you may write your game to support various command line options or other kind of user selectable option. Normally there is a little give and take between giving options and maintaining code readability and speed of execution. However with function pointers you can overcome these problems quite easily and instead of having a slew of if statements to determine which cryptically named function to call you can set the simply named function pointer at the start of the program, or when your options are reset, and not have to worry about cryptic names or slews of if statements again. ConclusionAfter reading this you should have a pretty fair idea of how to incorporate function pointers into your code. I can't guarantee that you will increase your FPS but I think will be more readable and will make your classes much easier to use. If you have any questions or comments you can e-mail me at griffenjam at hot mail dot com. Discuss this article in the forums
See Also: © 1999-2011 Gamedev.net. All rights reserved. Terms of Use Privacy Policy
|