Click here to Skip to main content
6,822,123 members and growing! (17,686 online)
Email Password   helpLost your password?
Languages » C / C++ Language » Delegates     Intermediate License: The Code Project Open License (CPOL)

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

By Mohammad.Nasim

Describes how Borland could bybass standard C++ restrictions via __closure keyword
C++, Dev, Design
Revision:5 (See All)
Posted:26 Nov 2009
Updated:26 Nov 2009
Views:1,986
Bookmarked:5 times
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
2 votes for this article.
Popularity: 1.05 Rating: 3.50 out of 5

1

2
1 vote, 50.0%
3
1 vote, 50.0%
4

5

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 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:

  • Alone::aloneFunc

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){}};
//---------------------- 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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Mohammad.Nasim


Member
Mohammad Nasim is a rented coder. He holds a BSc. degree of Pure Mathematics and Computer Science at department of Mathematics, Al-Azhar University. Cairo, Egypt. During his study he worked as a network troubleshooter at Information Systems and Networking Unit –ISNU-, Al-Azhar University. Also he worked as a tester at ISNU to help debug programs produced there.

As a rented coder, he has contributed in two projects.
In the first project, he contributed by some mathematical calculations and debugging of a software that gets the stem and pattern of Arabic words.

In the second project, he has contributed in developing a SudokuSolver software that can generate/solve given Sudoku puzzle. This project didn't use BackTacking as a method of thinking. Instead it used a lot of searching stratigies and logic to solve and generate an infinite number of solvable puzzles each has a unique solution.

Currently, he is working with Prof. M. Fayad San Jose University, CA. developing a Content Management Engine.

You can contact him at m_nasim7@yahoo.com (+2)014-154-2837
Occupation: Software Developer
Location: Egypt Egypt

Other popular C / C++ Language articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 1 of 1 (Total in Forum: 1) (Refresh)FirstPrevNext
GeneralThank you for formatting PinmemberMohammad.Nasim20:09 27 Nov '09  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads.

PermaLink | Privacy | Terms of Use
Last Updated: 26 Nov 2009
Editor: Deeksha Shenoy
Copyright 2009 by Mohammad.Nasim
Everything else Copyright © CodeProject, 1999-2010
Web17 | Advertise on the Code Project