Sign in to follow this  
Erzengeldeslichtes

What's the point of Function Pointers?

Recommended Posts

In C++, what's the point of a function pointer? So a function pointer will allow me to point to different sections of code without a switch statement. For example, if I have different game states (Menu, In Game, End Game, for example), I can have a switch statement:
switch(g_CurrentGameState)
{
case GAMESTATE_MENU:
RunMenu();
break;
case GAMESTATE_INGAME:
RunGame();
break;
case GAMESTATE_ENDGAME:
RunEnd();
break;
default:
throw();
}
But instead of that I can do that with function pointers:
//Globals
void (*pGameState)();
pGameState g_GameState[3];
//Set up in main
g_GameState[GAMESTATE_MENU] = RunMenu;
g_GameState[GAMESTATE_INGAME] = RunGame;
g_GameState[GAMESTATE_ENDGAME] = RunEnd;
//In place of the switch above
g_GameStatePointers[g_CurrentGameState]();

Okay, I can see that. There are some huge limitations in this though: There's no type safety (what if I did a RunOther(int, char) and did g_GameState[0] = RunOther;?), and I can't use member data (because I can't point to non-static member functions). Why not instead use a class with a virtual function? For example:
//global
class GameState
{
public:
    virtual void Run()=0;
};
//main
GameCore TheCore(Bunch, of, Core, Options, Here);//Note this is in a function, not a global declaration.
GameState* AvailableGameStates[3];
GameState_Menu GS_Menu;
GameState_GameCore GS_Game(&TheCore);
GameState_EndGame GS_End;
AvailableGameStates[GAMESTATE_MENU] = &GS_Menu;
AvailableGameStates[GAMESTATE_INGAME] = &GS_Game;
AvailableGameStates[GAMESTATE_ENDGAME] = &GS_End;
//in place of switch
AvailableGameStates[g_CurrentGameState]->Run();


In this case I can now use any data I want. For example, say I have a GameCore object that I wanted to call the member function DoFrame() on with the function pointers. Well this works (while function pointers don't):
class GameState_GameCore : public GameState
{
protected:
    GameCore* TheCore;
    GameState_GameCore(const GameState_GameCore& rs){}
    GameState_GameCore& operator=(const GameState_GameCore& rs){ return *this; }
public:
    GameState_GameCore(GameCore* ToRun) : TheCore(ToRun){}
    virtual void Run() { TheCore->DoFrame(); }
};
In this case I've accessed a non-static member function. Note that combining the two sources you can see I'm also accessing an object that has no referance in the global namespace. I can't think of a way to do this using global functions. Now I'm a firm believer in "every tool has a job", and so I'm wondering... what's the job of a function pointer? The virtual-function-in-a-class seems to be better at doing (what I've been told is) the Function Pointer's job. The only place I can think to use function pointers is in dynamically linked DLLs (that is, LoadLibrary("DLLName"); rather than linking the lib) since I can't use classes across them. Also perhaps for a bit more speed than classes. Can anyone tell me what's the use of function pointers?

Share this post


Link to post
Share on other sites
Look up how qsort works. That's a pretty good example of good function pointer usage. Also there's a bunch of stuff in the windows api that uses function pointers for callbacks. Sure, they could've done it with inheritance and base classes and stuff, but 1) it would be overkill in most cases and 2) it wouldnt work in C.

Share this post


Link to post
Share on other sites
You can do function pointers to class members, the syntax is a bit weird though:

typedef void (CClassName::* FUNCTION_TYPE)( int, int, unsigned long );

I've used function pointers for a DC-like class to work on pixel data. Once the bitdepth is changed it will reassign the copy/draw function pointers to the appropriate functions for that particular depth or fallback to slower, but general functions.

I couldn't have done it with a base class and inherited classes for every pixel format available because i can change the format on the fly (can't change my own type, can i?).

Share this post


Link to post
Share on other sites
Here's an example of how I use function pointers. My game engine is a 2D engine, and almost every game object is either a Sprite or derived from a Sprite. However, there are times when I simply don't want to worry about creating a whole new class for some simple behavior. Maybe I want to have a bunch of balls bounce off the ground, or maybe clouds that move and grow and shrink to give them a little bit of activity. These are basic behaviors, so what I do in those cases is use a function pointer (it's in C#, so it's actually events, but similar concept).

I just simply create my functions for each type of behavior, and assign the Sprite's function pointer. Then my engine knows to look at every Sprite, see if it has a behavior assigned, and if so, it calls it.

So, function pointers are ways that the same function can give you different behaviors. They're not really necessary, and you could get around using them if you really wanted to, but sometimes they just make things easier.

--Vic--

Share this post


Link to post
Share on other sites
You really should try to see if your understanding of a particular concept is correct before you start complaining about how it's not useful or implemented in a useful manner.
In this case, for instance, none of your complaints about the shortcomings of function pointers are correct, and even a little searching should reveal that.
First of, there *is* type safety, as
void(*)()
and
void(*)(int)
are two different types that cannot be assigned to each other.
In other words, this will fail:

void foo();
void bar(int);

void(*pfn)(); // pfn is a pointer to a void function with no args

int main() {
pfn = foo; // ok, types match
pfn = bar; // will fail, type mismatch
}




Your other specific complaint was that it won't allow you to point to member functions, which is also incorrect:

class Test {
public:
void Foo();
};

void(Test::*pfn)(); // pfn is of type pointer to Test member func

int main() {
pfn = &Test::Foo; // Assign to Test::Foo
Test t;
(t.*pfn)(); // Call test.foo()
}




As for virtual member functions vs. function pointers they serve completely different needs.

But, after all, you asked for the point of a function pointer.
Consider a generic sorting sorting function (such as std::sort), that can operate on any given type of data. How will the function know how to compare the elements its given? It could simply suppose that operator< is suitably defined, of course, but that would severely limit the usefulness of sort. Consider this, for instance:

struct CD {
string title;
string artist;
int year_published;
/* other stuff */
};

bool compareTitle ( CD const& cd1, CD const& cd2 ) {
return cd1.title < cd2.title;
}
bool compareArtist ( CD const& cd1, CD const& cd2 ) {
return cd1.artist < cd2.artist;
}
bool compareYearPublished ( CD const& cd1, CD const& cd2 ) {
return cd1.year_published < cd2.year_published;
}

vector<CD> cdCollection;

int main() {
/* Assuming cdCollection is filled with CD's */

// Sort by title
sort ( cdCollection.begin(), cdCollection.end(), compareTitle );

// Sort by artist
sort ( cdCollection.begin(), cdCollection.end(), compareArtist );

// Sort by year
sort ( cdCollection.begin(), cdCollection.end(), compareYearPublished );
}



In cases like this function pointers (or functors) are invaluable, and the same results cannot be achieved elegantly in another fashion.

Hope that clears things up a little.

- Neophyte

EDIT: Tag typos
EDIT: Another typo

Share this post


Link to post
Share on other sites
What's the point of loop statements if we can just use an if statement and a goto?

Programming is little more than expressing your intentions in a manner that can be comprehended by both human and machine alike.

Share this post


Link to post
Share on other sites
lol with a System.Data.DataSet and a table with Key/Value lookups to various functions, you could have the completely generic object!

We are storing guids that are linked to code with the GuidAttribute, and essentially using our own function pointers for VB.NET/C#.

It really is working quite nicely, as we can allow the user to edit what behaviors an object has at runtime.

Share this post


Link to post
Share on other sites
Quote:
Original post by Neophyte
You really should try to see if your understanding of a particular concept is correct before you start complaining about how it's not useful or implemented in a useful manner.

That is the point of my post: to get a better understanding of the particular concept. I wasn't complaining about them, I asked what their use is. I did a lot of searches about function pointers and everything I found about function pointers says that you can't use it to point at non-static member functions, which seemed like a gigantic limitation to its usefulness.

Thank you all for your replies.

Share this post


Link to post
Share on other sites
Quote:
Original post by antareus
Look into functors. They let you treat class member pointers the same way as you would normal/static class member function pointers.

They're also type safe, capable of holding state, compatible with function pointers (with some amount of work) and have lots of other advantages. Take a look at boost libraries for built in support.

Share this post


Link to post
Share on other sites
Function pointers aren't type safe? I'm pretty sure they give errors on compile if you pass the wrong type... As for functors, they are ok generally but are much bulkier (in code) than function pointers.

I personally chose to use function pointers for my GUI system, and for interpolators I support pointers to variables, pointers to functions, pointers to members, and functors.

Share this post


Link to post
Share on other sites
Function pointers ARE type safe (well, as safe as any pointer in that you can cast them however you want but w/o casting they're safe), and mainly they're made for function tables (when you need to call one of many functions based on an index).

In C++, virtual functions can solve most of the same problems as function pointers with the added benefit that they can take advantage of member data. There are still situations where you might need raw function pointers, but from what I've heard boost wraps those cases rather well so if you're using boost you pretty much don't need them except where APIs require them.

Share this post


Link to post
Share on other sites
Function pointers were introduced in the C language, and like many C language features, they were extremely useful when you only had the C language. But now that there are other (and sometimes better) C++ ways of doing things, function pointers aren't needed as much as they used to be.

For instance with plain C, you could give a C struct a more object-oriented feel by having function pointer members within a struct. This gave you a 'class-like' struct containing data and functions to operate on that data. Nowadays in C++ you would just use a class!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this