473,399 Members | 2,278 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,399 software developers and data experts.

cool thing with memberfunction pointers as parameters

PKH
This is a technique that was used in an object-oriented program-architecture
in C that I worked with in the past, and I didn't think was possible to do
something similar for classes in C++. Basically it is a way to send virtual
functions as function-parameters, and is useful in cases where you f.ex have
a class that manages other objects and want to call different functions on
these objects without having to rewrite the traversal code for each call.
This may be obvious to many, but I thought it was cool that it could be done
and maybe someone else will find a use for it also.
The drawback is that you need to use a void* to pass any parameters to the
functions.

here is a simple testprogram to show it:
class BaseClass; // foward declaration of class

typedef void (BaseClass::* BaseClassFunc)(void*); // typedef a
functionpointer for

// BaseClass member function.

// The void* is not used here, but

// is meant for any data that would

// need to be passed
class BaseClass
{
protected:
int
m_int;

public:
BaseClass(){m_int = 0;}
virtual void VirtualFunc(void* pxContext) = 0; // just some meaningless
testfunction
void CallVirtual(BaseClassFunc pF, void*
pxContext){(this->*pF)(pxContext);} // call the parameter-function on self
};

class DerivedClass : public BaseClass
{
public:
void VirtualFunc(void* pxContext){m_int = 1;} // override the VirtualFunc
from the BaseClass
};

int main(int argc, char* argv[])
{

DerivedClass
D;

void*
pxContext = NULL;

/* the following actually calls DerivedClass::VirtualFunc on D, as you
can see by stepping into it. */
/* This function would normally be made for some other class, and contain
the traversal-code */
/* but in this example it is just a member of BaseClass */
D.CallVirtual(BaseClass::VirtualFunc, pxContext);

return 0;
}

Jul 22 '05 #1
2 1429
"PKH" <no************@online.no> wrote in message news:<c5******************@news2.e.nsc.no>...
class BaseClass; // foward declaration of class

typedef void (BaseClass::* BaseClassFunc)(void*); // typedef a
functionpointer for

// BaseClass member function.

// The void* is not used here, but

// is meant for any data that would

// need to be passed
class BaseClass
{
protected:
int
m_int;

public:
BaseClass(){m_int = 0;}
virtual void VirtualFunc(void* pxContext) = 0; // just some meaningless
testfunction
void CallVirtual(BaseClassFunc pF, void*
pxContext){(this->*pF)(pxContext);} // call the parameter-function on self
};

class DerivedClass : public BaseClass
{
public:
void VirtualFunc(void* pxContext){m_int = 1;} // override the VirtualFunc
from the BaseClass
};

int main(int argc, char* argv[])
{

DerivedClass
D;

void*
pxContext = NULL;

/* the following actually calls DerivedClass::VirtualFunc on D, as you
can see by stepping into it. */
/* This function would normally be made for some other class, and contain
the traversal-code */
/* but in this example it is just a member of BaseClass */
D.CallVirtual(BaseClass::VirtualFunc, pxContext);

return 0;
}


Actually, you must say &BaseClass::VirtualFunc. Your compiler failed
to warn you, so you might want to check if it's warning level is set
too low.

Besides, it's needlessly complex. You can always say
(D.*(&BaseClass::VirtualFunc))(pxContext).

The function CallVirtual does not add any functionality, it only saves
on parentheses.

With boost::bind, you can do even fancier things:

boost::bind( &BaseClass::VirtualFunc, _1, pxContext )( D ).

The boost::bind call creates a unary functor, where the single
argument _1 is substituted on every call. The second parameter
needed for BaseClass::VirtualFunc, pxContext is kept.
The advantage is of course that you can use the same same
context for every call to the created functor. This means
you can pass it to std::for_each, and have for_each provide
the different BaseClass/DerivedClass objects.

Regards,
Michiel Salters
Jul 22 '05 #2
PKH

"Michiel Salters" <Mi*************@logicacmg.com> wrote in message
news:fc*************************@posting.google.co m...
"PKH" <no************@online.no> wrote in message news:<c5******************@news2.e.nsc.no>...
class BaseClass; // foward declaration of class

typedef void (BaseClass::* BaseClassFunc)(void*); // typedef a
functionpointer for

// BaseClass member function.

// The void* is not used here, but

// is meant for any data that would

// need to be passed
class BaseClass
{
protected:
int
m_int;

public:
BaseClass(){m_int = 0;}
virtual void VirtualFunc(void* pxContext) = 0; // just some meaningless testfunction
void CallVirtual(BaseClassFunc pF, void*
pxContext){(this->*pF)(pxContext);} // call the parameter-function on self };

class DerivedClass : public BaseClass
{
public:
void VirtualFunc(void* pxContext){m_int = 1;} // override the VirtualFunc from the BaseClass
};

int main(int argc, char* argv[])
{

DerivedClass
D;

void*
pxContext = NULL;

/* the following actually calls DerivedClass::VirtualFunc on D, as you can see by stepping into it. */
/* This function would normally be made for some other class, and contain the traversal-code */
/* but in this example it is just a member of BaseClass */
D.CallVirtual(BaseClass::VirtualFunc, pxContext);

return 0;
}


Actually, you must say &BaseClass::VirtualFunc. Your compiler failed
to warn you, so you might want to check if it's warning level is set
too low.


I don't think the & is needed. It compiles and runs fine. I've never used &
when taking the address of functions, same as with the address of arrays.

Besides, it's needlessly complex. You can always say
(D.*(&BaseClass::VirtualFunc))(pxContext).

The function CallVirtual does not add any functionality, it only saves
on parentheses.
The point is not to call VirtualFunc directly, but to be able to send a
virtual function as a parameter and have that parameter-function called on
one or more objects. The idea is that you can pass different virtual
functions as the parameter, without rewriting the calling-code. In this
simple example there is no benefit, but if you want to f.ex. traverse some
data-structure and call different virtual functions (passed as the
parameter) on each of the items contained in the data-structure, you would
only need to write the traversal code once.
With boost::bind, you can do even fancier things:

boost::bind( &BaseClass::VirtualFunc, _1, pxContext )( D ).

The boost::bind call creates a unary functor, where the single
argument _1 is substituted on every call. The second parameter
needed for BaseClass::VirtualFunc, pxContext is kept.
The advantage is of course that you can use the same same
context for every call to the created functor. This means
you can pass it to std::for_each, and have for_each provide
the different BaseClass/DerivedClass objects.

Regards,
Michiel Salters


I'm not very familiar with the advanced things you can do with STL, but this
seems to be what I wanted to do (for STL containers).
Pål K Holmberg
Jul 22 '05 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: JB | last post by:
After searching a lot on the ibmsite and googling a lot, i still dont know how to execute a memberfunction in an udf. Example: -----------A.h -------------- class A { public: void run(); }
42
by: x-pander | last post by:
Is is guaranteed, that a pointer to any object in C points exactly at the lowest addressed byte of this object? Specifcally is it possible for any platform/os/compiler combination that: (char...
2
by: Frank Vanris | last post by:
Hi, I have the following code: #include "stdafx.h" #using <mscorlib.dll> using namespace std; __gc class A {
12
by: Lance | last post by:
VB.NET (v2003) does not support pointers, right? Assuming that this is true, are there any plans to support pointers in the future? Forgive my ignorance, but if C# supports pointers and C# and...
5
by: Dinesh Kumar | last post by:
Hi all I am using VB.NET for a Connector dll in Delphi client and some webservice . can you tell me how to handle pointers in Vb.net which are passed by delphi client as parameters in function...
9
by: Sidhu | last post by:
Hai, I like 2 know more abot pointers. Can you please tell me the fields in which pointers are widely used. Yours Sidhu
12
by: claudiu | last post by:
Hi, I'll go straight to the first question. Why does the code below compile? void f(int i = 0); int main() { (&f)();
19
by: MQ | last post by:
Can someone tell me where I should use pointers and where I should use references? In his book, Stroustrup says that you should use pointers for passing arguments that are to be modified, not...
33
by: pateldm15 | last post by:
How do I sort an string array using pointers
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
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,...
0
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...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
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...

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.