#include <string>
#include <iostream>
using namespace std;
class A {
public:
void foo(string s)
{
cout << "A::foo() " << s << endl;
}
void foo2()
{
cout << "A::foo2()" << endl;
}
};
class B {
public:
virtual void foo(string s) = 0;
};
class B1 : public B {
public:
virtual void foo(string s)
{
cout << "B1::foo() " << s << endl;
}
};
class B2 : public B1 {
public:
virtual void foo(string s)
{
cout << "B2::foo() " << s << endl;
}
};
typedef void (*callback1)(string); // normal function pointer
typedef void (A::*callback2)(string); // class A member function pointer
typedef void (B::*callback3)(string); // class B member function pointer
typedef void (A::*callback4)(); // class A member function pointer
int main()
{
// normal function pointer and member function pointer size are different
cout << "size of callback1: " << sizeof(callback1) << endl;
cout << "size of &B::foo : " << sizeof(&B::foo) << endl;
cout << "size of &B1::foo : " << sizeof(&B1::foo) << endl;
cout << "size of &B2::foo : " << sizeof(&B2::foo) << endl;
A* a1 = new A;
A a2;
callback2 f1 = &A::foo;
// need an object to call member function
(a1->*f1)("from pointer");
(a2.*f1)("from reference");
B1 b1;
B2 b2;
// use base class' member callback call sub-class
callback3 f2 = (callback3)&B1::foo;
(b1.*f2)("b1");
// use base class' member callback call sub-class
f2 = (callback3)&B2::foo;
(b2.*f2)("b2");
// even can call other class's member function with same signature
f2 = (callback3)&A::foo;
(b1.*f2)("b1");
(b2.*f2)("b2");
// (a2.*f2)("a2"); // can't compile. the object has to be the same type of the callback class
// even can call other class's member function with different signature
f2 = (callback3)&A::foo2;
(b1.*f2)("b1");
// another example to call other class's member function with different signature
callback4 f4 = (callback4)&A::foo;
(a2.*f4)();
// can't assign member function pointer to normal function pointer
// callback1 f3 = (callback1)&A::foo; // can't compile
return 0;
}
/*
* Compile with g++ on Linux.
*
* Output of the program:
size of callback1: 4
size of &B::foo : 8
size of &B1::foo : 8
size of &B2::foo : 8
A::foo() from pointer
A::foo() from reference
B1::foo() b1
B2::foo() b2
A::foo() b1
A::foo() b2
A::foo2()
A::foo()
*/