Introduction
This article is partitioned into two main parts.
Part I discusses standard C++ member-function-pointers (MFP), which is different from normal function-pointers. It also illustrates the restrictions on these type of pointers and how Borland's C++ Builder bypasses them via its special type of MFP __closure.
Part II shows an application of using this type of MFP. It explains in detail how Borland uses their own type of MFP to handle Windows Events and how it is fascinating rather MFC style or Win32 API style.
Backgrounds
I assume that the reader has enough background in order to use MFP. I know its syntax is a little stupid, but I didn't explain it in details. Instead I used comments to explain what lines of code do.
Also, I assume that the reader is aware of Inheritance and polymorphism.
Part I - Closures: An introduction
Closures are a very useful feature in C++ builder. To illustrate this, let's talk first about normal member-function-pointers in C++.
Try the following code:
#include <stdlib.h>
class Base{public:int baseFunc(int){}};
class Drvd:public Base{public:int drvdFunc(int){}};
class Alone{public:int aloneFunc(int){}};
int main() {
int (Base::*funcPtr)(int); funcPtr = &Drvd::baseFunc; Drvd ob; (ob.*funcPtr)(2); system("pause");
return 0;
}
This code shows the behavior of normal C++ member-function-pointers (MFP).
As we see, MFP of type Base::*
can point to the following:
Base::baseFunc
- and can be called from object of type Base
/Drvd
. Drvd::baseFunc
- and can be called from object of type Base
/Drvd
.
But cannot point to the following:
Drvd::drvdFunc
Alone::aloneFunc
If we changed MFP’s type to be Drvd::*
, the situation is going to be changed slightly to point to:
Base::baseFunc
- and can be called form object of type Drvd
Drvd::baseFunc
- and can be called from object of type Drvd
Drvd::drvdFunc
- and can be called from object of type Drvd
But, it cannot point to:
Finally if our MFP be of type Alone::*
, it can only point to:
Alone::aloneFunc
- and can be called from object of type Alone
And it cannot point to:
Base::baseFunc
Drvd::baseFunc
Drvd::drvdFunc
Borland’s "__closure" Keyword
Borland has added a new keyword to language to bypass restrictions set by the standard C++.
This keyword is __closure
.
So far we have three restrictions that are:
- MFP of type
Base
cannot point to Drvd
member-functions that are new (not inherited). - MFP cannot point to any member-function that is in a class out of inheritance hierarchy
Base
/Drvd
and Alone
for example. - We cannot assign a pointer to member-function to our MFP using object name, instead we have to use the fully qualified name
Class::member
-function. This would be very useful if solved, since objects may change polymorphically at run-time.
Actually the first and the second restrictions are very similar. In other words our goal is to make any MFP point to any member-function in any class that is either in the inheritance hierarchy or not.
Let’s see how Borland solved this problem using the __closure
keyword.
#include <stdlib.h>
class Base{public:int baseFunc(int){}};
class Drvd:public Base{public:int drvdFunc(int){}};
class Alone{public:int aloneFunc(int){}};
int main() {
int ( __closure *funcPtr)(int); Drvd ob;
funcPtr = ob.drvdFunc; funcPtr(2); system("pause");
return 0;
}
Try to point funcPtr
to any member function and see the result. Just make sure that it has the same parameters list and and the same return type.
Now let’s see how solving the third problem would be very useful. Check out this code:
#include <iostream.h>
class Base{public:virtual int baseFunc(int){cout << "i am baseFunc in Base class\n" ; }};
class Drvd:public Base{public:int baseFunc(int)
{cout << "i am baseFunc in Drvd class\n" ; }};
int main() {
int ( __closure *funcPtr)(int); Base *ob = new Base();
funcPtr = ob->baseFunc; funcPtr(2); delete ob;
ob = new Drvd(); funcPtr = ob->baseFunc;
funcPtr(2);
delete ob; ob=NULL;
system("pause");
return 0;
}
Isn’t this great? Thank you Borland.
See you in Part II.
History
- 26th November, 2009: Initial post