C++ Delegates and Borland's C++ Builder Event Handling - Part I






4.60/5 (6 votes)
Describes how Borland could bybass standard C++ restrictions via __closure keyword
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){}};
//----------------------- Normal member-function-pointers ---------------
int main() {
int (Base::*funcPtr)(int); // MFP of type Base::*
funcPtr = &Drvd::baseFunc; // member-function pointed to
Drvd ob; // type of calling object
(ob.*funcPtr)(2); // calling of MFP is from here
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 typeBase
/Drvd
.Drvd::baseFunc
- and can be called from object of typeBase
/Drvd
.
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 typeDrvd
Drvd::baseFunc
- and can be called from object of typeDrvd
Drvd::drvdFunc
- and can be called from object of typeDrvd
But, it cannot point to:
Alone::aloneFunc
Finally if our MFP be of type Alone::*
, it can only point to:
Alone::aloneFunc
- and can be called from object of typeAlone
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 toDrvd
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
andAlone
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){}};
//---------------------- Borland's C++ Buildre's Closures ---------------
int main() {
int ( __closure *funcPtr)(int); // special MFP of type __closure
Drvd ob;
funcPtr = ob.drvdFunc; // member-function pointed to
funcPtr(2); // calling of closure is from here
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" ; }};
//---------------------- Borland's C++ Buildre's Closures ---------------
int main() {
int ( __closure *funcPtr)(int); // special MFP of type __closure
Base *ob = new Base();
funcPtr = ob->baseFunc; // member-function pointed to
funcPtr(2); // calling of MFP is from here
delete ob;
ob = new Drvd(); // polymorphic behaviour
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