473,849 Members | 1,811 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Function pointer help

I am having trouble implementing some function pointer stuff in c++

An object can register itself for many events

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

so I declared a function pointer like

typedef void (CFObject::*CFE ventHandler)(CF Event *theEvent);

So when I register a handler

plane->addEventListen er((CFObject *)gun, &MachineGun::ha ndleEvent, 0);

MachineGun's class contains

void handleEvent(CFE vent *theEvent);

I am getting the following error:

error: no matching function for call to
'Airplane::addE ventListener(CF Object*, void (MachineGun::*) (CFEvent*),
uint8_t&)'/Users/ghulands/Desktop/arduino-0012/hardware/libraries/
CoreFoundation/CFApplication.h :42: note: candidates are: void
CFApplication:: addEventListene r(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
7 3831
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 addEventListene r(CFObject *target, CFEventHandler callback,
uint8_t event);

so I declared a function pointer like

typedef void (CFObject::*CFE ventHandler)(CF Event *theEvent);

So when I register a handler

plane->addEventListen er((CFObject *)gun, &MachineGun::ha ndleEvent, 0);

MachineGun's class contains

void handleEvent(CFE vent *theEvent);

I am getting the following error:

error: no matching function for call to
'Airplane::addE ventListener(CF Object*, void (MachineGun::*) (CFEvent*),
uint8_t&)'/Users/ghulands/Desktop/arduino-0012/hardware/libraries/
CoreFoundation/CFApplication.h :42: note: candidates are: void
CFApplication:: addEventListene r(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->addEventListen er(gun,
static_cast<CFE ventHandler>(&M achineGun::hand leEvent), 0);

Oct 24 '08 #2
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 addEventListene r(CFObject *target, CFEventHandler callback,
uint8_t event);

so I declared a function pointer like

typedef void (CFObject::*CFE ventHandler)(CF Event *theEvent);

So when I register a handler

plane->addEventListen er((CFObject *)gun, &MachineGun::ha ndleEvent, 0);

MachineGun's class contains

void handleEvent(CFE vent *theEvent);

I am getting the following error:

error: no matching function for call to
'Airplane::add EventListener(C FObject*, void (MachineGun::*) (CFEvent*),
uint8_t&)'/Users/ghulands/Desktop/arduino-0012/hardware/libraries/
CoreFoundati on/CFApplication.h :42: note: candidates are: void
CFApplication: :addEventListen er(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->addEventListen er(gun,
static_cast<CFE ventHandler>(&M achineGun::hand leEvent), 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
On Oct 24, 3:39 am, Victor Bazarov <v.Abaza...@com Acast.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 addEventListene r(CFObject *target, CFEventHandler
callback, uint8_t event);
so I declared a function pointer like
typedef void (CFObject::*CFE ventHandler)(CF Event *theEvent);
So when I register a handler
plane->addEventListen er((CFObject *)gun, &MachineGun::ha ndleEvent, 0);
Just curious, but: what is the type of gun, and why did you cast
it?
MachineGun's class contains
void handleEvent(CFE vent *theEvent);
I am getting the following error:
error: no matching function for call to
'Airplane::addE ventListener(CF Object*, void (MachineGun::*) (CFEvent*),
uint8_t&)'/Users/ghulands/Desktop/arduino-0012/hardware/libraries/
CoreFoundation/CFApplication.h :42: note: candidates are: void
CFApplication:: addEventListene r(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->addEventListen er(gun,
static_cast<CFE ventHandler>(&M achineGun::hand leEvent), 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::addEve ntHandler(
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 objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 24 '08 #4
On Oct 24, 8:51*am, James Kanze <james.ka...@gm ail.comwrote:
On Oct 24, 3:39 am, Victor Bazarov <v.Abaza...@com Acast.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 addEventListene r(CFObject *target, CFEventHandler
>callback, uint8_t event);
>so I declared a function pointer like
>typedef void (CFObject::*CFE ventHandler)(CF Event *theEvent);
>So when I register a handler
>plane->addEventListen er((CFObject *)gun, &MachineGun::ha ndleEvent, 0);

Just curious, but: what is the type of gun, and why did you cast
it?
>MachineGun's class contains
>void handleEvent(CFE vent *theEvent);
>I am getting the following error:
>error: no matching function for call to
>'Airplane::add EventListener(C FObject*, void (MachineGun::*) (CFEvent*),
>uint8_t&)'/Users/ghulands/Desktop/arduino-0012/hardware/libraries/
>CoreFoundati on/CFApplication.h :42: note: candidates are: void
>CFApplication: :addEventListen er(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->addEventListen er(gun,
static_cast<CFE ventHandler>(&M achineGun::hand leEvent), 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::addEve ntHandler(
* * * * 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_fu n)()>
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(makeCall back<X, &X::foo>(&x) );

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

--
Max
Oct 24 '08 #5
On Oct 24, 2:50*pm, James Kanze <james.ka...@gm ail.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
On Oct 24, 6:57*pm, Maxim Yegorushkin <maxim.yegorush ...@gmail.com>
wrote:
On Oct 24, 2:50*pm, James Kanze <james.ka...@gm ail.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 objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Oct 24 '08 #7
On Oct 24, 8:32*pm, James Kanze <james.ka...@gm ail.comwrote:
On Oct 24, 6:57*pm, Maxim Yegorushkin <maxim.yegorush ...@gmail.com>
wrote:
On Oct 24, 2:50*pm, James Kanze <james.ka...@gm ail.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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

58
10207
by: jr | last post by:
Sorry for this very dumb question, but I've clearly got a long way to go! Can someone please help me pass an array into a function. Here's a starting point. void TheMainFunc() { // Body of code... TCHAR myArray; DoStuff(myArray);
5
2159
by: amit kumar | last post by:
I am calling a function which returns pointer to a map. The declaration of the map is map<int,vectxyz*>. vectxyz is a vector containing pointer to a class xyz. For map<int,vectxyz*>* p1 In the called function, I am using p1->find(1) which is returning a valid iterator and not going to the end. I am returning p1 from the called function. But in the calling function, find(1) is going to the end, i.e unable to find the key 1, which was...
11
2723
by: JKop | last post by:
Take the following simple function: unsigned long Plus5Percent(unsigned long input) { return ( input + input / 20 ); } Do yous ever consider the possibly more efficent:
3
425
by: Jan-Henrik Grobe | last post by:
Hallo, I am coming to this newsgroup with a very strange Problem. I have two c++ files A.cpp and B.cpp....In A.cpp I am creating an openGL window and in B.cpp I have stored the callback functions. Important is, that the object A.o has to be created BEFORE B can be compiled. I am sure that sounds confusing but A.cpp is part of a library that is needed for objects I use in B (kind of client-server thing). So I cannot include a B.h in the...
2
12696
by: sushil | last post by:
+1 #include<stdio.h> +2 #include <stdlib.h> +3 typedef struct +4 { +5 unsigned int PID; +6 unsigned int CID; +7 } T_ID; +8 +9 typedef unsigned int (*T_HANDLER)(void); +10
7
5199
by: Mike D. | last post by:
I have a problem with a dynamic library I am developing, but it is really more of a pointer issue than anything else. Hopefully someone here can lend me some assistance or insight into resolving this. Ok... here goes.... I have a function that passes a pointer to a string to another function. For example: int FunctionA ()
4
3639
by: anonymous | last post by:
Thanks your reply. The article I read is from www.hakin9.org/en/attachments/stackoverflow_en.pdf. And you're right. I don't know it very clearly. And that's why I want to understand it; for it's useful to help me to solve some basic problem which I may not perceive before. I appreciate your help, sincerely.
17
2219
by: Razzel | last post by:
I created this as a test: #include <time.h> main(){ printf(X1: %s\n", putim()); printf(X2: %s\n", putim()); } putim() { time_t t; time(&t); return(ctime(&t));
9
23786
by: Morten Lemvigh | last post by:
Is it possible to pass a pointer to a constructor or a class definition as argument to a function? Maybe in a way similar to passing function pointers...? The function should construct a number of objects using the given constructor. The objects should all inherit from a base class. It's not possible to pass actual objects, since it's not given on beforehand, how many should be created.
20
2259
by: MikeC | last post by:
Folks, I've been playing with C programs for 25 years (not professionally - self-taught), and although I've used function pointers before, I've never got my head around them enough to be able to think my way through what I want to do now. I don't know why - I'm fine with most other aspects of the language, but my brain goes numb when I'm reading about function pointers! I would like to have an array of structures, something like
0
11005
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10665
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10723
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
1
7894
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
7070
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5735
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5921
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4544
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
3177
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.