Skip to main content
gamedev.net
🔒 Locked

is this callback code bad

Started by heh65532 5 replies 1.6k views
Original Post
heh65532
heh65532
Hi
i was trying to write in c++ a class that calls (callback) a member function and passes parameter, and other that doesnt need a parameter.

here's the code that seems to work but i got some possible heap corruption possibly because of it..

thx for taking a look! please tell me if its good or not and could it cause heap corruption?


class CallMemFnBase{public: virtual		bool call(void * obj)  = 0;};template <class T,class T2> class CallMemFn1: public CallMemFnBase{protected:		typedef bool (T2::*Fn)();		Fn mFunc;public:		CallMemFn1(Fn func): mFunc(func) {}		bool call(void * obj) { return ((static_cast<T2*>(obj))->*mFunc)(); }};template <class T,class A> class CallMemFn2: public CallMemFnBase{		typedef bool (T::*Fn)(A a); 		Fn mFunc;		A arg;public:		CallMemFn2( Fn fn, A arg): mFunc(fn), arg(arg) {}		bool call(void * obj) { return ((static_cast<T*>(obj))->*mFunc)(arg); }};// the pass it to function like this:&CallMemFn2<Entity,S32>(&Entity::isEnemy, getSide())// or like this:&CallMemFn1<Entity,Item>( &Item::isAvailable ) // to function , which takes an argumend like this: CallMemFnBase *callb = 0// and calls it:(*callb).call(entity) 
the_edd
the_edd
First, is there a reason you're not using things like boost's bind and function libraries (or equivalents)? Example:

using namespace boost;function<bool (const Entity &)> enemy = bind(&Entity::IsEnemy, _1, getSide());bool kill_it = enemy(orc);


That aside, is there any reason to use a void pointer? Would it be ok to make CallMemFnBase a template class?

"call()" is typically written "operator()" in C++. Why not use that?
heh65532
heh65532
Thx for the reply The_Edd!

im not using boost because i want to learn this stuff my self..


Quote:

That aside, is there any reason to use a void pointer? Would it be ok to make CallMemFnBase a template class?

"call()" is typically written "operator()" in C++. Why not use that?


ya im applying those now.. thx
frob
frob
Quote:
Original post by the_edd
That aside, is there any reason to use a void pointer? Would it be ok to make CallMemFnBase a template class?

"call()" is typically written "operator()" in C++. Why not use that?

Even better is to simply use a function pointer.

It is also what operator()() was designed for, and automatically converts to.

Both C and C++ prefer function pointers by design. Look at C functions like qsort() and bsearch() that accept function pointers. Many of the C++ Standard Library functions take a Predicate, a function pointer taking one parameter and returning a bool. A raw function pointer satisfies the template's requirements.

Function pointers allow you to use wrappers like bind internally, but don't force you to use anything in particular. Google can find template-based wrappers that handle much of it for you.


Using raw function pointers looks like this:
void(*func)(SomeClass &obj); // Pointer to function named func that accepts a SomeClass reference and returns nothing
Use it with:
func(obj);

Most templates that handle it look like this:
Functor func; // Wrapper for pointer to function named func that accepts a SomeClass reference and returns nothing.
Use it the same way:
func(obj);

Function pointer wrappers can implement safety details for you, like initializing to NULL and not calling anything if the function is NULL.
_swx_
_swx_
Don't reinvent the wheel, use boost or tr1 function and bind.
the_edd
the_edd
Quote:
Original post by frob
Even better is to simply use a function pointer.

How would you implement the O.P's CallMemFn2 with a function pointer?

Quote:

It is also what operator()() was designed for, and automatically converts to.

I'm not sure what you're saying here, but if you really meant to say that operator()() returns an object that is convertible to a function pointer, that's incorrect. The address of SomeClass::operator() returns a pointer to a member function, but that's an entirely different animal.

Quote:

Both C and C++ prefer function pointers by design.

Actually, I wouldn't say that's true about C++ -- at least not about the standard library. function pointers aren't bindable or adaptable by default i.e. you can't pass function pointers to many higher order functors without using ptr_fun or similar.

I'm also under the impression that functors can often be faster, since a function pointer is opaque due to the kind of late binding inherent in their use. That's not true of functors, necessarily.

Quote:

Look at C functions like qsort() and bsearch() that accept function pointers.

Case in point. The std::sort algorithm is generally thought to be faster (though I admittedly have no evidence to hand) because the calls to the functor's operator() can be inlined more easily.

[Edited by - the_edd on October 4, 2010 3:34:55 PM]
no such user
no such user
Quote:
Original post by the_edd
Case in point. The std::sort algorithm is generally thought to be faster (though I admittedly have no evidence to hand) because the calls to the functor's operator() can be inlined more easily.

One reputable source is Matt Austern in Dr Dobbs article, but it's also mentioned in "Effective STL" by Meyers.

Topic Locked

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

Sign in to reply to this topic.