> I'm experimenting with function pointers and found
> two questions. Let's assume this code:
> 1 #include <iostream>
> 2 class A;
> 4 ////////////////////////////////////////////
> 5 class B
> 6 {
> 7 public:
> 8 void printB( void (A::*)(void) );
> 9 };
> 10
> 11 void B::printB( void (A::*func)(void) )
> 12 {
> 13 *func(); // not working
That's because you need an object on which to call the function.
> 14 }
> 15
> 16 ////////////////////////////////////////////
> 17 class A
> 18 {
> 19 public:
> 20 void printA(void);
> 21 void invokeB(void);
> 23 private:
> 24 B myB;
> 25 };
> 27 void A::printA(void)
> 28 {
> 29 std::cout << "A::print" << std::endl;
> 30 return;
> 31 }
> 33 void A::invokeB(void)
> 34 {
> 35 myB.printB( &A::printA );
> 36 return;
> 37 }
> 39 ////////////////////////////////////////////
> 40 int main(void)
> 41 {
> 42 A myA;
> 43 a.invokeB();
> 45 return 0;
> 46 }
> What I want to achieve is a communication between two object
> with a callback function. Object A invokes a function in
> object B passing a callback function. The invoked function in
> object B calls the passed callback function to communicate
> with the caller A.
Are the types known to both objects? The "usual" solution here
involves an abstract base class, something like:
class AbstractCallback
{
public:
virtual ~AbstractCallback() {}
virtual void notify() =3D 0 ; // or some other name.
} ;
The class requesting the callback can then derive from this;
often, you migth also provide a templated concrete derivation:
template< typename T, void (T::*fnc)() >
class Callback : public AbstractCallback
{
public:
Callback( T* obj ) : myObj( obj ) {}
virtual void notify()
{
(myObj->*fnc)() ;
}
private:
T* myObj ;
} ;
In the absense of garbage collection, this solution requires
some complex memory management, however.
> So, I'm passing a pointer to A::printA in line 35 to
> B::printB. The called member function printB of object myB
> than should deference the passed function pointer (line 13,
> not working yet) to invoke again a function (A::printfA) of
> the original caller. Thus, myA invokes myB which in turn
> invokes myA again.
> My first question concerns line 35. What exactly is the
> address of &A::printA?
A pointer to member function. Which is more of a selector than
a pointer in the real sense. At any rate, it definitely must
contain more than just an address, since it must work with
virtual functions (where the actual function called depends on
the dynamic type it is being called on). If you check the
sizeof a pointer to member function, it will typically (but not
necessarily) be larger than a normal pointer to function.
> When I forward this value to "cout", (cout << &A::printA) I
> get the output "1" and not an address.
There is no << operator defined for pointer to members. There
is an implicit conversion of pointers to members to a bool,
which results in true if the pointer to member is not null, and
there is a << operator for bool.
> Since A::printA is a non-static member function, it cannot be
> considered independent of a concrete object. Thus, I would
> assume that &AA::printA is an offset which must be added to
> the memory address where a concrete object of class A is
> allocated.
It's more complicated than that. The class instance doesn't
actually contain a copy of the code of its member functions; in
many ways, the only difference between a member function and a
non member function is that the member function has an
additional hidden argument. The way member functions are
called, however, is different, both in regards to syntax, and
(at least when virtual functions are considered) the mechanics.
> Adding the start address and the offset would result in the
> address where the function printA of an individual object of
> class A is located.
No.
> And this brings me to my second question concerning line 13.
> When I try to compiler this code, I get the compiler error:
> error: must use .* or ->* to call pointer-to-member function
> in `func (...)' I assume the problem is that the function
> pointer "func" has no reference to a concrete object of class
> A (myA in this case). So, the function cannot be invoked. How
> can I solve this? Do I have to pass the address of myA to
> B::printB? Something like "myB.printB( &A::printA, this );"
> in line 35 and than use the pointer in "this" to invoke func?
Exactly. Or you wrap some, using an intermediate "agent" class.
(This is generally considered the prefered solution, since it
means that the class invoking the callback doesn't need to know
of the class which is called back.)
--
James Kanze (GABI Software) email:james.kanze@[EMAIL PROTECTED]
en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34


|