By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,569 Members | 1,338 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,569 IT Pros & Developers. It's quick & easy.

Function pointer help

P: n/a
I am having trouble implementing some function pointer stuff in c++

An object can register itself for many events

void addEventListener(CFObject *target, CFEventHandler callback,
uint8_t event);

so I declared a function pointer like

typedef void (CFObject::*CFEventHandler)(CFEvent *theEvent);

So when I register a handler

plane->addEventListener((CFObject *)gun, &MachineGun::handleEvent, 0);

MachineGun's class contains

void handleEvent(CFEvent *theEvent);

I am getting the following error:

error: no matching function for call to
'Airplane::addEventListener(CFObject*, void (MachineGun::*)(CFEvent*),
uint8_t&)'/Users/ghulands/Desktop/arduino-0012/hardware/libraries/
CoreFoundation/CFApplication.h:42: note: candidates are: void
CFApplication::addEventListener(CFObject*, void (CFObject::*)
(CFEvent*), uint8_t)

MachineGun is a subclass (not a direct one) of CFObject.

If I put an event handler on CFObject it compiles fine. I don't want
to have to put it in there as a virtual method as it will break the
design.

Is there a way for the function pointer definition to be defined in
that it can also accept subclasses of the type?

Any help is greatly appreciated.

Thanks,
Greg

Oct 23 '08 #1
Share this Question
Share on Google+
7 Replies


P: n/a
On Oct 23, 4:15*pm, "ghula...@gmail.com" <ghula...@gmail.comwrote:
I am having trouble implementing some function pointer stuff in c++

An object can register itself for many events

void addEventListener(CFObject *target, CFEventHandler callback,
uint8_t event);

so I declared a function pointer like

typedef void (CFObject::*CFEventHandler)(CFEvent *theEvent);

So when I register a handler

plane->addEventListener((CFObject *)gun, &MachineGun::handleEvent, 0);

MachineGun's class contains

void handleEvent(CFEvent *theEvent);

I am getting the following error:

error: no matching function for call to
'Airplane::addEventListener(CFObject*, void (MachineGun::*)(CFEvent*),
uint8_t&)'/Users/ghulands/Desktop/arduino-0012/hardware/libraries/
CoreFoundation/CFApplication.h:42: note: candidates are: void
CFApplication::addEventListener(CFObject*, void (CFObject::*)
(CFEvent*), uint8_t)

MachineGun is a subclass (not a direct one) of CFObject.

If I put an event handler on CFObject it compiles fine. I don't want
to have to put it in there as a virtual method as it will break the
design.

Is there a way for the function pointer definition to be defined in
that it can also accept subclasses of the type?

Any help is greatly appreciated.

Thanks,
Greg
Found the solution: static_cast<>

plane->addEventListener(gun,
static_cast<CFEventHandler>(&MachineGun::handleEve nt), 0);

Oct 24 '08 #2

P: n/a
gh******@gmail.com wrote:
On Oct 23, 4:15 pm, "ghula...@gmail.com" <ghula...@gmail.comwrote:
>I am having trouble implementing some function pointer stuff in c++

An object can register itself for many events

void addEventListener(CFObject *target, CFEventHandler callback,
uint8_t event);

so I declared a function pointer like

typedef void (CFObject::*CFEventHandler)(CFEvent *theEvent);

So when I register a handler

plane->addEventListener((CFObject *)gun, &MachineGun::handleEvent, 0);

MachineGun's class contains

void handleEvent(CFEvent *theEvent);

I am getting the following error:

error: no matching function for call to
'Airplane::addEventListener(CFObject*, void (MachineGun::*)(CFEvent*),
uint8_t&)'/Users/ghulands/Desktop/arduino-0012/hardware/libraries/
CoreFoundation/CFApplication.h:42: note: candidates are: void
CFApplication::addEventListener(CFObject*, void (CFObject::*)
(CFEvent*), uint8_t)

MachineGun is a subclass (not a direct one) of CFObject.

If I put an event handler on CFObject it compiles fine. I don't want
to have to put it in there as a virtual method as it will break the
design.

Is there a way for the function pointer definition to be defined in
that it can also accept subclasses of the type?

Any help is greatly appreciated.

Thanks,
Greg

Found the solution: static_cast<>

plane->addEventListener(gun,
static_cast<CFEventHandler>(&MachineGun::handleEve nt), 0);
You should be aware that this is dangerous. You're basically telling
the compiler to shut up, claiming that you know what you're doing. In
fact converting (and using) the pointer to member of derived when a
pointer to member of base is expected is wrought with peril. What if
the object for which you're going to use your handler is not of the type
'MachineGun'? And inside the handler you will pretend that the 'this'
pointer is a pointer to 'MachineGun', which is not right. Undefined
behaviour ensues.

Virtual functions are there for a reason, you know...

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 24 '08 #3

P: n/a
On Oct 24, 3:39 am, Victor Bazarov <v.Abaza...@comAcast.netwrote:
ghula...@gmail.com wrote:
On Oct 23, 4:15 pm, "ghula...@gmail.com" <ghula...@gmail.comwrote:
I am having trouble implementing some function pointer
stuff in c++
An object can register itself for many events
void addEventListener(CFObject *target, CFEventHandler
callback, uint8_t event);
so I declared a function pointer like
typedef void (CFObject::*CFEventHandler)(CFEvent *theEvent);
So when I register a handler
plane->addEventListener((CFObject *)gun, &MachineGun::handleEvent, 0);
Just curious, but: what is the type of gun, and why did you cast
it?
MachineGun's class contains
void handleEvent(CFEvent *theEvent);
I am getting the following error:
error: no matching function for call to
'Airplane::addEventListener(CFObject*, void (MachineGun::*)(CFEvent*),
uint8_t&)'/Users/ghulands/Desktop/arduino-0012/hardware/libraries/
CoreFoundation/CFApplication.h:42: note: candidates are: void
CFApplication::addEventListener(CFObject*, void (CFObject::*)
(CFEvent*), uint8_t)
MachineGun is a subclass (not a direct one) of CFObject.
If I put an event handler on CFObject it compiles fine. I
don't want to have to put it in there as a virtual method
as it will break the design.
Is there a way for the function pointer definition to be
defined in that it can also accept subclasses of the type?
Found the solution: static_cast<>
plane->addEventListener(gun,
static_cast<CFEventHandler>(&MachineGun::handleEve nt), 0);
You should be aware that this is dangerous. You're basically
telling the compiler to shut up, claiming that you know what
you're doing. In fact converting (and using) the pointer to
member of derived when a pointer to member of base is expected
is wrought with peril. What if the object for which you're
going to use your handler is not of the type 'MachineGun'?
And inside the handler you will pretend that the 'this'
pointer is a pointer to 'MachineGun', which is not right.
Undefined behaviour ensues.
Virtual functions are there for a reason, you know...
I agree. It's an example of very poor design. On the other
hand, it seems to be an established idiom in some GUI circles;
I've seen it required by more than one framework. Typically,
it's not quite as dangerous as it looks, because almost always,
you're registering a member function of the class you're in; the
first argument is almost always "this".

On the whole: a much better design would be to define an
abstract base class for the EventHandler, with a pure virtual
function for the notification, and pass a pointer to it. In
many cases, his actual implementation class can just derive from
this abstract base class (in addition to any other classes it
may derive from), and implement the function directly.
Otherwise, it's not too hard to define a forwarding class---you
could even create a template class which you just have to
instantiate---and use it.

If you really insist on using the above pattern, it should be
done by means of a template member function, e.g.:

template< typename T >
void MyClass::addEventHandler(
T* obj,
void (T:* pmf)( CFEvent* ),
uint8_t ) ;

(You can safely do the static_cast<bit inside this function,
and even call a private member function, virtual or not, with
the results of the cast. But you've ensured type safety at the
user interface level, at least.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 24 '08 #4

P: n/a
On Oct 24, 8:51*am, James Kanze <james.ka...@gmail.comwrote:
On Oct 24, 3:39 am, Victor Bazarov <v.Abaza...@comAcast.netwrote:
ghula...@gmail.com wrote:
On Oct 23, 4:15 pm, "ghula...@gmail.com" <ghula...@gmail.comwrote:
>I am having trouble implementing some function pointer
>stuff in c++
>An object can register itself for many events
>void addEventListener(CFObject *target, CFEventHandler
>callback, uint8_t event);
>so I declared a function pointer like
>typedef void (CFObject::*CFEventHandler)(CFEvent *theEvent);
>So when I register a handler
>plane->addEventListener((CFObject *)gun, &MachineGun::handleEvent, 0);

Just curious, but: what is the type of gun, and why did you cast
it?
>MachineGun's class contains
>void handleEvent(CFEvent *theEvent);
>I am getting the following error:
>error: no matching function for call to
>'Airplane::addEventListener(CFObject*, void (MachineGun::*)(CFEvent*),
>uint8_t&)'/Users/ghulands/Desktop/arduino-0012/hardware/libraries/
>CoreFoundation/CFApplication.h:42: note: candidates are: void
>CFApplication::addEventListener(CFObject*, void (CFObject::*)
>(CFEvent*), uint8_t)
>MachineGun is a subclass (not a direct one) of CFObject.
>If I put an event handler on CFObject it compiles fine. I
>don't want to have to put it in there as a virtual method
>as it will break the design.
>Is there a way for the function pointer definition to be
>defined in that it can also accept subclasses of the type?
Found the solution: static_cast<>
plane->addEventListener(gun,
static_cast<CFEventHandler>(&MachineGun::handleEve nt), 0);
You should be aware that this is dangerous. *You're basically
telling the compiler to shut up, claiming that you know what
you're doing. *In fact converting (and using) the pointer to
member of derived when a pointer to member of base is expected
is wrought with peril. *What if the object for which you're
going to use your handler is not of the type 'MachineGun'?
And inside the handler you will pretend that the 'this'
pointer is a pointer to 'MachineGun', which is not right.
Undefined behaviour ensues.
Virtual functions are there for a reason, you know...

I agree. *It's an example of very poor design. *On the other
hand, it seems to be an established idiom in some GUI circles;
I've seen it required by more than one framework.
wxWidgets is one example.
On the whole: a much better design would be to define an
abstract base class for the EventHandler, with a pure virtual
function for the notification, and pass a pointer to it. *In
many cases, his actual implementation class can just derive from
this abstract base class (in addition to any other classes it
may derive from), and implement the function directly.
They argue that if there are hundreds of events there should be
hundreds of virtual functions. Which leads to relatively large virtual
tables for every derived class.
Otherwise, it's not too hard to define a forwarding class---you
could even create a template class which you just have to
instantiate---and use it.

If you really insist on using the above pattern, it should be
done by means of a template member function, e.g.:

* * template< typename T >
* * void MyClass::addEventHandler(
* * * * T* * * * * * * * * * obj,
* * * * void (T:* * * * * * *pmf)( CFEvent* ),
* * * * uint8_t ) ;

(You can safely do the static_cast<bit inside this function,
and even call a private member function, virtual or not, with
the results of the cast. *But you've ensured type safety at the
user interface level, at least.)
IMHO, using member function pointers for callbacks is always a design
mistake because it requires casting member function pointers, which is
not portable. And looks wrong because there are easier ways to achieve
the desired effect of calling back a member function of an object.

It is trivial to make it right in a 100% portable way using C-style
callbacks, i.e. function pointer + void* pointer. Such callbacks can
be bound to regular functions as well as to member functions. The only
cast required is absolutely safe static_cast<T*>(void*):

#include <stdio.h>

struct Callback
{
void(*fun)(void* arg);
void* arg;
};

void invoke(Callback c)
{
c.fun(c.arg);
}

// a member-function to Callback function adapter
template<class T, void(T::*mem_fun)()>
Callback makeCallback(T* obj)
{
struct local
{
static void call(void* p)
{
(static_cast<T*>(p)->*mem_fun)();
}
};
Callback c = { local::call, obj };
return c;
}

struct X
{
void foo() { printf("foo\n"); }

void bar() { printf("bar\n"); }
// bar to callback adapter
static void bar_cb(void* p) { static_cast<X*>(p)->bar(); }
};

int main()
{
X x;

// autogenerate member function adapter
invoke(makeCallback<X, &X::foo>(&x));

// or use an existing adapter
Callback c = { X::bar_cb, &x };
invoke(c);
}

--
Max
Oct 24 '08 #5

P: n/a
On Oct 24, 2:50*pm, James Kanze <james.ka...@gmail.comwrote:

[]
IMHO, using member function pointers for callbacks is always a
design mistake because it requires casting member function
pointers, which is not portable.

There's no problem with portabilty, as long as the user doesn't
make any mistakes. *There's a serious problem with robustness,
however, since you really have no way of catching those
mistakes.
Although it works on practice, is it not undefined behaviour to cast a
derived class member function pointer back to base class member
function pointer?
And looks wrong because there are easier ways to achieve the
desired effect of calling back a member function of an object.
It is trivial to make it right in a 100% portable way using
C-style callbacks, i.e. function pointer + void* pointer. Such
callbacks can be bound to regular functions as well as to
member functions. The only cast required is absolutely safe
static_cast<T*>(void*):

The code you propose is no safer than the pointer to member
solution with my template wrapper.
I think it is, because it does not rely on casting member function
pointers.
And a lot uglier and more difficult to understand.
It looks alien to you probably because you are not used to it.

I agree that having to adapt a member function to a regular (static)
function may seem onerous at first. However, I see no fundamental
difference (in the context of callbacks) between:

struct X
{
void foo();
};

and:

struct X
{
static void foo(X* that);
};

Speaking purely technically, I think C-style callbacks are superior to
member function pointer based callbacks:

1) they can be bound both to plain functions and to member functions.
2) the callback structure occupies less memory, since a regular
function pointer is 2-3 times smaller than a member function pointer.
3) they do not rely on any undefined behaviour.

--
Max
Oct 24 '08 #6

P: n/a
On Oct 24, 6:57*pm, Maxim Yegorushkin <maxim.yegorush...@gmail.com>
wrote:
On Oct 24, 2:50*pm, James Kanze <james.ka...@gmail.comwrote:
[]
IMHO, using member function pointers for callbacks is
always a design mistake because it requires casting member
function pointers, which is not portable.
There's no problem with portabilty, as long as the user
doesn't make any mistakes. *There's a serious problem with
robustness, however, since you really have no way of
catching those mistakes.
Although it works on practice, is it not undefined behaviour
to cast a derived class member function pointer back to base
class member function pointer?
No. Undefined practice only creeps in if you use it with a
pointer that doesn't actually point to a derived class of the
correct type. (I had the same reaction the first time I saw
it:-). It doesn't like like it should work, especially if e.g.
virtual inheritance et al. are involved. But the standard says
it has to.)
And looks wrong because there are easier ways to achieve
the desired effect of calling back a member function of an
object. It is trivial to make it right in a 100% portable
way using C-style callbacks, i.e. function pointer + void*
pointer. Such callbacks can be bound to regular functions
as well as to member functions. The only cast required is
absolutely safe static_cast<T*>(void*):
The code you propose is no safer than the pointer to member
solution with my template wrapper.
I think it is, because it does not rely on casting member
function pointers.
It requires using a void*, which in my experience can be even
more dangerous.
And a lot uglier and more difficult to understand.
It looks alien to you probably because you are not used to it.
Certainly:-). (Actually, I can follow it, because when
interfacing to C, you often have to do things like that. It is
the first time I've seen it used when there was no C involved,
however.)

I think what I really don't like about it is that it doesn't
look wierd enough, given what you're actually doing.

[...]
Speaking purely technically, I think C-style callbacks are
superior to member function pointer based callbacks:
Quite frankly, neither come close to using virtual functions.
However...
1) they can be bound both to plain functions and to member functions.
If that is a requirement, of course (e.g. to be able to
interface with C as well), then your solution is the way to go.
2) the callback structure occupies less memory, since a
regular function pointer is 2-3 times smaller than a member
function pointer.
As if that's seriously going to make any difference. This is a
GUI we're talking about. With large, graphic images behind the
scenes; a couple of Meg, at the least. And even with a hundred
callbacks, you won't be adding over a KB.
3) they do not rely on any undefined behaviour.
Nor does the pointer to member solution.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 24 '08 #7

P: n/a
On Oct 24, 8:32*pm, James Kanze <james.ka...@gmail.comwrote:
On Oct 24, 6:57*pm, Maxim Yegorushkin <maxim.yegorush...@gmail.com>
wrote:
On Oct 24, 2:50*pm, James Kanze <james.ka...@gmail.comwrote:
[]
IMHO, using member function pointers for callbacks is
always a design mistake because it requires casting member
function pointers, which is not portable.
There's no problem with portabilty, as long as the user
doesn't make any mistakes. *There's a serious problem with
robustness, however, since you really have no way of
catching those mistakes.
Although it works on practice, is it not undefined behaviour
to cast a derived class member function pointer back to base
class member function pointer?

No. *Undefined practice only creeps in if you use it with a
pointer that doesn't actually point to a derived class of the
correct type. *(I had the same reaction the first time I saw
it:-). *It doesn't like like it should work, especially if e.g.
virtual inheritance et al. are involved. *But the standard says
it has to.)
[]
3) they do not rely on any undefined behaviour.

Nor does the pointer to member solution.
Sorry, I was wrong with regards to UB arising when casting derived
class member function pointer to base class one. It seems that
static_cast<is enough to do the trick.

--
Max
Oct 27 '08 #8

This discussion thread is closed

Replies have been disabled for this discussion.