View Full Version : passing a function as an argument?
EscapeCharacter
04-09-2002, 03:34 AM
is this possible? im asking cause i am making some sort of a event handler for a menu system, and was wondering if i do something like this
class.addevent(functionname);
then have some where else in the code
class.execevent();
sans-hubris
04-09-2002, 10:15 AM
It's sort of possible. You need to pass in a function pointer.
Prototype of a function that takes in a function prototype:
void funcme(rettype (*fnptr)(int arg), int args);
All you need to do is call it with the name of a function that returns the rettype and has one int as its argument:
rettype somefunc(int x);
void funcer()
{
//code here
funcme(somefunc,5);
//code here
}
Yup; it's called a callback. The problem with this is that "functionname" has to be a global function. You can't pass something like "class.functionname" as an argument to a function.
Here's an example from some of my code:
typedef DWORD (CALLBACK *GETFILE) (
DWORD dwUser,
DWORD *pdwID,
DWORD *pdwFlags,
LPTSTR pszFileName,
DWORD dwBufSize);
This is the code for a callback in a dll I wrote; generally the dll is used by a class in C++, so during initialization the class provides a pointer to itself to the dll. The DLL then passes that to the callback function in "dwUser". That way, in my global function callback, I can do something like this:
DWORD CALLBACK GetNextFile(DWORD dwUser, DWORD *pdwId, DWORD *pdwFlags, LPTSTR pszFileName, DWORD dwBufSize)
{
return ((CMyClass*)(dwUser))->OnGetFile(pdwId, pdwFlags, pszFileName, dwBufSize);
}
(in visual studio, CALLBACK is a macro for _stdcall)
So you can see here, I'm just using a global function as a wrapper around a class method.
Alternatively, you can pass a reference to an object or a pointer, and call functions on that object. This is certainly the more object oriented way of doing things, and is how java handles it. In fact, java provides "anonymous classes" (i think they're called) which only provide the functionality for, say, handling a gui event. These classes are so small they're often written in-line, write in the function call they're being passed to.
Python is one language that does support actually sending class methods as an argument. so class.functionname is perfectly allowable in python.
EscapeCharacter
04-09-2002, 02:14 PM
excellent thanks guys, now time for me to get back too work :).
edit:
i also got this idea this morning that since im using classes that i could have a class.command() method and just overload it for each different object, which way would be better though?
it's up to you; whatever you're more comfortable with. I generally avoid function pointers if I can, out of personal preference.
EscapeCharacter
04-09-2002, 03:39 PM
ok ill have to play with it to see which i like. thanks both of you for the info it was a great help.
sans-hubris
04-09-2002, 07:31 PM
It sounds like to me you should look up virtual functions and inheritance. I'll let you figure that one out.
MattD
04-11-2002, 12:22 AM
there was a question raised by jamma about something similar.. heres the body of the post
"C++ offers a facility for indirectly referring to a member of a class. A point to a member is a value that identifies a member of a class, you can think of it as the position of the member in an object of the class."
class Std_Interface{
virtual void suspend() = 0;
}
void f(Std_Interface *p){
Std_Interface::* s = &Std_Interface::suspend;
// how to call stuff
p->suspend(); //direct call
(p->*s)(); // call through pointer to member
}
(example lifted and slightly mod'd from pg 418 of bjarne stroustrups the c++ programming language 3rd ed)
so yes you can pass a function a pointer to a member function by calling a function and passing s as a variable. (does this sentance even make sense?)
its not overly clear what your trying to do though, the CALLBACK method might work, its probrably easier to use virtual methods and a little bit of inheritance
or you could just cheat and call a function that normalises a function name and then calls the appropriate member function....
if(strcomp(input, 'ThisFunction'){
this->thisfunction();
}
of course, thats just nasty ;)
Matt D
EscapeCharacter
04-13-2002, 08:29 PM
well what i was going for was having the event() method for all menuitems and be able to change what event did for each different menuitem. like if i had a fileopen and filesave menuitem they would each have a different event method. i know this can be accomplished with overloading but i have only overloaded operators so im reading up on just overloading functions(does any of this make sense?).
sans-hubris
04-15-2002, 04:39 AM
Originally posted by EscapeCharacter
well what i was going for was having the event() method for all menuitems and be able to change what event did for each different menuitem. like if i had a fileopen and filesave menuitem they would each have a different event method. i know this can be accomplished with overloading but i have only overloaded operators so im reading up on just overloading functions(does any of this make sense?).
Yes, it does, and this is exactly what inheritance allows you to do. Inheritance is such a big topic that you really need to read it on your own. It's not something I can explain fully in a paragraph or two.
BTW, while you can pass function pointers in C/C++, you really aren't passing functions. Functions in C/C++ are not "first class functions." This is something you can do in pretty much all functional programming languages (ML/Caml/Objective Caml, LISP, Scheme, etc.), Perl, Python, Pascal (ugh), etc. but not in C/C++.
E.g. in Scheme I can do the following (nb, lambdas are functions and the list immediately following them is its parameters, prefix notation is used, car is the first thing in the list, cdr is the rest of the list, and cons adds something to the front of the list.)
(define powers-seq
(lambda (x)
(lambda (list-length)
(letrec ((make-powers-list
(lambda (lon iteration);lon is list of numbers
(if (zero? iteration)
lon
(make-powers-list
(cons (* x (car lon)) lon) (+ -1 iteration))))))
(make-powers-list (list x) list-length)))))
This allows me to create functions that will return a list of the powers for x for any arbitrary length.
So I can do the following to get functions that take one parameter (the length of the list) and return a list of that number's powers.
(define powers2 (powers-seq 2))
(define powers3 (powers-seq 3))
(define powers5 (powers-seq 5))
Now I have three functions that will return lists of arbitrary length the powers of their respective numbers.
C/C++ do not have the ability to do something like thus unless you use classes and inheritance. You could create a powers-seq class and inherit from that class to create the lists of powers as I did in Scheme. The result would likely be longer than the above, especially for the inherited classes. It probably also would not be nearly as graceful.
stuka
06-13-2002, 09:38 PM
hmm...an odd thought popped into my head. If you create an "action handler" class that's a template class, which takes a function object as its template argument, then you could probably do this without inheritance....I think. (I've been reading a bit of the C/C++ User's Journal lately, and a lot of those guys are big on template programming).
vBulletin® v3.7.0, Copyright ©2000-2009, Jelsoft Enterprises Ltd.