More info, Function Pointers

Started by
18 comments, last by GameDev.net 19 years, 9 months ago
Im currently porting my game engine from reglar C to a more Object oriented C++. The engine used to use structs and pointers to keep track of sprites which were stored in a linked list. The program would itterate thrugh the list and call each sprites DrawProc and MoveProc. These were function pointers. These are function pointers can be custome scripted by the user of the library. Thus I can make void MyDrawProc() { DrawItMyWay(); } sprite->DrawProc = MyDrawProc; This would call MyDrawProc() whenever the sprite was reached in the linked list. This was a beutiful system and it worked great. Howver, in C++ it is not this simple. Since Sprite is now a class, I can't seem to figure out a way to have a function pointer as a member mathod. How can I have it work similar to the example above? P.S. I read the recent fetured article, but it didn't help me very much :( Any help you guys could offer would be fantastic!
Advertisement
Check out the stuff in "functional" for binding member functions as functors ... things like "member_func" and "ptr_member_func" or something like that ...

they are C++ standard library items and "The C++ Standard Library Reference" by Josuttis is a great reference to use to learn them ... but any you have that's fairly modern should work.
You could force the user of the library to inherit from the Sprite class and supply his own draw() method.

That is, in your library:

class Sprite {public:  virtual void draw() { // default implementation }};


And then in the code that uses the library:
class MySprite : public Sprite {public:  void draw() { // my new implemetnation }};


And then in the source you maintain a list of sprite pointers and simply call their draw() methods. This is the standard way of doing things in C++.

If you want, you can also use member function pointers but I see no real reason to do that.

Edit: In many cases, virtual functions were introduced to replace the need for function pointers. If you really want to do this however, look into boost::bind and boost::mem_fun.

Regards,
Jeff
If I do it using a derived class, will the linked lists of Sprites be able to call its method?

i.e.

class cSprite
{
draw()
}

class cMyCSprite:: cSprite
{
draw()
}

Now, the linked list is a linked list of cSprites not cMyCSprites, so will it know what to call?

Im not sure Im makeing it clear... sorry.

If you understand what I mean, let me know :D !
Yes, it will, as long as your link list data is a cSprite*. This is what virtual function work in C++. For example,

cSprint* cs = linkList->GetElement(0);
cs->Draw();

C++ will dynamically bind function call to to cMyCSprite() in runtime.

I wish it helps!



Nachi Lau (In Christ, I never die)www.sky-dio.com/Nachi
I came from C, and am not up on inheritance [hence I've run into a bunch of the problems you're running into...]

From what I know, if you make a list of the base class, it will use the base function [unless you typecast? That might not even work...]

In C++, function pointers are 2 different things, class function pointers which point to a class function, and 'normal' function pointers that point to a non-class function. The two are not interchangable [to my knowledge...]. You can't assign a normal function pointer a class' function and vice versa.

I don't use class function pointers, but since I'm ignorant of inheritance and virtual function goodness, I use other function pointers a bit in my game.

To put them into a class:

class foo{private:public:    void    (*fp)(int,int);}*fooptr;fooptr=new foo;fooptr->fp=some_function;fooptr->fp(a,b);


so some_function cannot be a class function, but beyond that limitation, it should work like C.

Note that the 'normal' function also acts just like it would in C. It doesn't know anything about the class that calls it.

[And I'll warn you ahead of time, this leads to some nastiness that could probably be avoided by doing it the "right" way]
One of the big things you need to "grok" when you move from C to C++ is the idea of deriving classes and polymorphism.

For example. In your C code, you had lots of different sprite structures. Each usually had the same function pointer pointing to some default draw/move function. But for different types of enemies or such, I assume you had different draw/move set for each. Right?

Here is an classic example of polymorphism. You might say something like:
DumbGrunt IS A sprite
SmartSniper IS A sprite
UberBoss IS a sprite.

When you have a IS-A relationship like this, it's a good place to use polymorphism. Define a base sprite class. This will be the "default" sprite class, if you will. Now, for those functions that are supposed to vary between each type or class of enemy, you must virtualize them. Then you can derive from the base class, make a seperate class for each type of enemy. Then just override whatever functions need to be. You dont have to override them all.

Now all you must do is make sure that your list holds all the sprites using pointers. Then when you call each ->draw() function, it will automatically at runtime figure out what type the class is and dispatch the call to the correct function: DumbGrunt::Draw, SmartSniper::Draw, etc. Be warned: polymorphism only works with pointers to classes.

There you go! When you use function pointers to member functions, you must preset what type of class the member function belongs to. You will find that member function pointers are pretty weak and unuseful. You can use boost::bind and such to get the job done, but I recommend using polymorphism beacuse in this case it's what it's designed for.

HTH
you can do function pointers in C++

class CSprite{public:    static void MyDrawProc1(CSprite* pxThisSprite)    {        pxThisSprite->DrawItMyWay();    }    void DrawItMyWay()    {    }     void DrawItAnotherWay()    {    }   // that's the member variable, like in C.    void (*DrawProc)(CSprite* pxThisSprite);};void MyDrawProc2(CSprite* pxThisSprite){    pxThisSprite->DrawItAnotherWay();}//..//..//..pxSprite->DrawProc = CSprite::MyDrawProc1;pxSprite->DrawProc = MyDrawProc2;


it's just like in C really. The function as to be static to the class, not a member function.

Everything is better with Metal.

Original Poster: If you make the base class' function virtual then your code will "know which draw to call". That's the whole point of using inheritance and polymorphism.
Hey all,

Thanks a bunch for stearing me in the right direction! So that what polymorphisim was for ;)

hehe...

Ya, I have just recently been doing OOP stuff, so I'm not totaly up on all the techniques. The books I have show examples of inheritance that werent particularly usefull. Thus, it left me with a feeling of "Ok, so what?". But now that a pratical example of how to use it has surfaced I will surely employ it more offten!

My linked lists are stored using the STL List template, so it shouldn't be a problem with the whole pointer thing considering that the STL List takes pointers anyway. A porgrammer friend of mind suggested that I should be able to typecast my derived class into a linked list of the parent class.

Anyway, thank you all very much.

This topic is closed to new replies.

Advertisement