Skip to main content
gamedev.net
🔒 Locked

Function Pointers

Started by blizz107 Jan 20, 2005 at 5:57 AM 3 replies 500+ views
Original Post
blizz107
blizz107
Hi, I want to call a function pointer, and define to which funtion it goes by a char instead of just writing the function name down. Hard to explain, but the code below speaks for itself Function to be called
void AILevelOne(Monster *monster)
{
	monster->SetX(500);
}
I have this function which takes a function pointer
void Monster::Update(void(*AIUpdate)(Monster*))
{	
	AIUpdate(this);					
}
Later on, i have this which calls the function pointer
Monster::Update(AILevelOne)     // That works
But i want this
Monster::Update(monster_properties.ai_func)   // ai_func is a char with  
                                                    // "AILevelOne" And that doesnt work
Is there a way to do this? [Edit: Made the post pretty - Oluseyi] [Edited by - Oluseyi on January 20, 2005 7:02:21 AM]
paulecoyote
paulecoyote
That might work if you used reflection because you can use a string to get a class from a class loader by its' name. But the name of the function is very different from a function pointer.

It would be easier if you typedef'ed your function prototype and stored a pointer to a function in your monster_properties class instead of the string.

Take care to use a static function for your callback too, unless you can be really sure the object whose function you are calling is going to be alive.

If you want different monsters to have different AI associated, it might be worth while creating an AI class that supports a particular interface and associate the monsters with that - or use inheritence and specialise AI for certain monsters.
Anything posted is personal opinion which does not in anyway reflect or represent my employer. Any code and opinion is expressed “as is” and used at your own risk – it does not constitute a legal relationship of any kind.
desertcube
desertcube
Why can't you make monster_properties.ai_func a function pointer? That would be the easiest/cleanest solution.

If you really do want to call a function by a string, my best guess would be to use a map, like so:
typedef void(*function_ptr)(Monster*);std::map<std::string, function_ptr> functions;

You would then need to fill the map up with all the possible fuctions name + adresses, so things could get messy! But you could then call them like this:
functions["AILevelOne"];

HTH
snk_kid
snk_kid
Quote:
Original post by blizz107
Is there a way to do this?


yes lots of ways of doing it, first i would download and change to using boost::function, then your not just restricted to using plain pointer to functions, you can use pointer member functions, functors anything that conforms to the signature you've set for instances of boost::function.

i would change this:

void Monster::Update(void(*AIUpdate)(Monster*)) { /* ... */ }


to a template member function:

template < typename UnaryFunction >void Monster::Update(UnaryFunction updator) { updator(*this); }


then you can use anything invokable not just plain pointer functions which is restricting.

In-order to invoke a function via a string using the same "Update" method, as already mentioned a map of string to callable entity is one way (pointer to free/member function, functor etc), you just need to overload the member function Update to take a string, i'd suggest if your compiler supports it use hash_map instead of map (hash_map is not currently part of the c++ standard its an STL extension) of std::string to boost::function (so you can store any callable entity that supports the signature, not just pointer to free-function), with all this in mind:

#include <boost\function.hpp>#include <string>#include <map>struct monster {	typedef boost::function< void (monster&) > updator;	typedef std::map< std::string, updator > func_map;		typedef func_map::iterator iterator;	typedef func_map::const_iterator const_iterator;	typedef std::pair< iterator, bool > result_pair;	typedef func_map::value_type value_type;private:	func_map func;public:	void setX(int i) {}	result_pair set_updator(const std::string& name, const updator& up) {		return func.insert(std::make_pair(name, up));	}	void update(const char* const s) {		func[s](*this);	}	void update(const std::string& s) {		func[s](*this);	}	template < typename UnaryFunc >	void update(UnaryFunc updater) {		updater(*this);	}};void AILevelOne(monster& m) {   m.setX(500);}int main() {   monster m;   m.set_updator("AILevelOne", AILevelOne);   m.update("AILevelOne"); //by string   m.update(AILevelOne); //by reference to function i.e. void (&)(monster&);}


You might also want to look into the observer design pattern (and its variants) as another alternative.

note: prefer references over pointers, only use pointers when necessary.
blizz107
blizz107
Thanks you all for the help :)

I’m going to look into each solution, An AI class could be a good idea and I’m going to take a look into std::map.
Also I’ll consider if its an option to make monster_properties.ai_func a function pointer.

Third: snk_kid, I’m going to look the code you wrote all over. Thanks for putting so much thought into this :) I’m not too experienced yet, so I’m going to take my time and lookup some things you guys wrote which i haven't used before. I’ll let you know how it goes .

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.