C++ function pointers
Hi,
i have written a quake-like console that associates a console command with a function. But i'm not sure how to use a function pointer to an objects function.
eg
void function (void)
{
// do stuff here
}
cConsole.addCommand(function,"command");
^ This works perfectly, but when i try to add a class method i get errors, eg;
cConsole.addCommand(cSomeObject.itsFunction,"command");
i hope i have explained that ok, basically i want the addCommand function to accept a function pointer from an object as well, does anyone know how to do this?
Muncher
Member functions have a different calling convention (because of the implicit this parameter). That is why it doesn't work. However, you can pass static member functions.
class method function pointers are a special case function pointer. because a class method operates on an instance of a class (unless it is a static member) they require an instance of the class.
i will try figure out a simple callback implementation that you can use and i will post back here in about 10 mins.
-Danu
class SomeClass { std::string sig;public: SomeClass( std::string _sig ) : sig(_sig) {} void foo(int a) { std::cout << sig.c_str() << " : " << a << std::endl; }};typedef void (SomeClass::*MFNPTR)(int a);int main() { SomeClass myObjA("Booom!"); SomeClass myObjB("KaPow!"); MFNPTR p = &SomeClass::foo; (myObjA.*p)(12); (myObjB.*p)(24); return 0;}
what you need to do is create your console to support objects that can be passed by pointer or reference, so that you complete the function-call signature.i will try figure out a simple callback implementation that you can use and i will post back here in about 10 mins.
-Danu
thanks :) so its not just a case of creating another function with a different calling convention :(
ok, heres a class type free implementation, its a bit advanced with the pointers, inheritence and templates, if you need anything explained post back.
NOTE: i'm not sure about the safety of this method, i devised it just now and it seems to work well enough BUT take it with a 'grain of salt'.
the type-free console
test it out!
the main problems with my simple implementation are that:
1 - there is no type checking to see if any of the cast's are valid!
2 - you need to be carefull that EACH class has a DIFFERENT console command associated with its type.
3 - pointers can get messy, use with caution!
-Cheers
Dan
PS. that was a fun problem to solve, mite use it myself!!
NOTE: i'm not sure about the safety of this method, i devised it just now and it seems to work well enough BUT take it with a 'grain of salt'.
the type-free console
// command storage base classstruct CommandBase { std::string name;};// stores a class-specific function pointertemplate< typename T >struct CommandSpecific : CommandBase { CommandSpecific( std::string _name, void (T::*_fnp)(int a) ) { name = _name; fnp = _fnp; } // declare the function-pointer storage variable 'fnp' void (T::*fnp)(int a);};class Console {private: std::vector< CommandBase* > cmdlist;public: // adds a command and stores its pointer template< typename T > void addCommand( void (T::*fnp)(int a), std::string cmd ) { CommandBase *cb = new CommandSpecific< T >( cmd, fnp ); cmdlist.push_back( cb ); } // attempt to call a command template< typename T > void attemptCommand( T& inst, std::string cmd ) { std::vector<CommandBase*>::iterator i = cmdlist.begin(); // look for the command to see if its listed for(; i!=cmdlist.end(); i++ ) { if( (*i)->name == cmd ) { // now we know the command calls match, // cast the stored pointer to retreive the class-specific function pointer CommandSpecific<T> *cp = static_cast< CommandSpecific<T>* > ( (*i) ); // do the funtion call, supply some random number for fun :) (inst.*(cp->fnp))( rand() % 100 ); } } } virtual ~Console() { // cleanup fn ptrs std::vector<CommandBase*>::iterator i = cmdlist.begin(); for( ; i != cmdlist.end(); i++ ) { delete (*i); *i = NULL; } cmdlist.clear(); }};
test it out!
// our test classesclass SomeClass { std::string sig;public: SomeClass( std::string _sig ) : sig(_sig) {} void foo(int a) { std::cout << "SomeClass: " << sig.c_str() << " : " << a << std::endl; }};// our test classesclass SomeOtherClass { std::string sig;public: SomeOtherClass( std::string _sig ) : sig(_sig) {} void foobar(int a) { std::cout << "SomeOtherClass: " << sig.c_str() << " : " << a << std::endl; }};int main() { SomeClass myObjA("Booom!"); SomeOtherClass myObjB("KaPow!"); Console con; con.addCommand< SomeClass >( &SomeClass::foo, "SomeClass_foo" ); con.addCommand< SomeOtherClass >( &SomeOtherClass::foobar, "SomeOtherClass_foobar" ); con.attemptCommand< SomeClass >( myObjA, "SomeClass_foo" ); con.attemptCommand< SomeOtherClass >( myObjB, "SomeOtherClass_foobar" ); return 0;}
the main problems with my simple implementation are that:
1 - there is no type checking to see if any of the cast's are valid!
2 - you need to be carefull that EACH class has a DIFFERENT console command associated with its type.
3 - pointers can get messy, use with caution!
-Cheers
Dan
PS. that was a fun problem to solve, mite use it myself!!
oh god, ive been reading through that, and there is like 3 lines of code i understand. You have completely nooberised me :)
what exactly do you not understand?
ps. maybe its a wee bit too advanced, you might be able to simplyfy the idea a bit more...
have you considered using global callbacks?
very simple idea, the main drawback would be that you need to create a callback for every possible object type, and/or need to specificaly handle each type.
here's some simple code
for somemore usefull reading about function pointers and callbacks: http://www.function-pointer.org
ps. maybe its a wee bit too advanced, you might be able to simplyfy the idea a bit more...
have you considered using global callbacks?
very simple idea, the main drawback would be that you need to create a callback for every possible object type, and/or need to specificaly handle each type.
here's some simple code
// DIRECTLY FROM FUNCTION-POINTER.ORG, COPYRIGHT (C) 2004-2005 class TClassA { public: void Display(const char* text) { cout << text << endl; }; static void Wrapper_To_Call_Display(void* pt2Object, char* text); /* more of TClassA */ }; // static wrapper-function to be able to callback the member function Display() void TClassA::Wrapper_To_Call_Display(void* pt2Object, char* string) { // explicitly cast to a pointer to TClassA TClassA* mySelf = (TClassA*) pt2Object; // call member mySelf->Display(string); } // function does something which implies a callback // note: of course this function can also be a member function void DoItA(void* pt2Object, void (*pt2Function)(void* pt2Object, char* text)) { /* do something */ pt2Function(pt2Object, "hi, i'm calling back using a argument ;-)"); // make callback } // execute example code void Callback_Using_Argument() { // 1. instantiate object of TClassA TClassA objA; // 2. call 'DoItA' for <objA> DoItA((void*) &objA, TClassA::Wrapper_To_Call_Display); }
for somemore usefull reading about function pointers and callbacks: http://www.function-pointer.org
Instead of using function pointers, take a long, hard look at Boost.Function & Boost.Bind. Both libraries make manipulating functions much simpler. Versions of both libraries are also likely to be part of the C++ standard library in the future.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement