|
Method pointers |
Top Previous Next |
|
What is translated > Method pointers Delphi's event handling is implemented by means of method pointers. Such method pointers are declared by addition of the words "of object" to a procedural type name. E.g.
TNotifyEvent = procedure(Sender: TObject) of object;
According to the Delphi help "a method pointer is really a pair of pointers; the first stores the address of a method, and the second stores a reference to the object the method belongs to". Such method pointers can point to any member functions in any class. For example by means of a method pointer the event handling of a special instance of a control - e.g. TButton - can be delegated to the instance of another class - e.g. TForm .
Delphi's method pointers cannot be translated as standard C++ member function pointers, because they can point to other member functions of the same inheritance hierarchy only. That's why Borland has extended the standard C++ syntax by the keyword __closure. With this keyword method pointers with the same properties as Delphi's method pointers can be declared in Borland C++. E.g. the event above is:
typedef void __fastcall (__closure *TNotifyEvent)(TObject* Sender);
For other compilers than C++Builder d2c::event provides a small, single-cast delegate with Delphi-like behavior:
Quick mapping
Delphi “of object” event
type TNotifyEvent = procedure(Sender: TObject) of object;
type TMyButton = class public OnClick: TNotifyEvent; end;
C++ (with d2c_event.h)
// alias the event type typedef d2c::event<void(System::TObject*)> TNotifyEvent;
class TMyButton : public System::TObject { public: TNotifyEvent OnClick;
void FireClick(System::TObject* sender) { if (OnClick) OnClick(sender); // null-safe invoke } };
Binding a handler (member method)
class TFormMain : public System::TObject { public: void ButtonClick(System::TObject* Sender); };
TMyButton* Button1 = /* ... */; TFormMain* Form1 = /* ... */;
Button1->OnClick = d2c::bind(Form1, &TFormMain::ButtonClick);
d2c::bind(obj, &Class::Method) creates a bound event.
The object must outlive all calls to the event (non-owning).
Calling, reassigning, clearing
Button1->FireClick(Button1); // call if assigned Button2->OnClick = Button1->OnClick; // copy/assign another handler Button2->OnClick.reset(); // clear
Comparing two events
bool same = Button1->OnClick.equals(Button2->OnClick); // true only if both reference the *same instance* and the *same member function*
Arrays / tables of events
Delphi often stores “procedure of object” values in arrays. That translates 1:1:
std::array<d2c::event<void()>, 256> handlers;
// assign handlers['A'] = d2c::bind(this, &TMyClass::OpenProc); // call (null-safe check is recommended) if (handlers['A']) handlers['A']();
|
|
This page belongs to the Delphi2Cpp Documentation |
Delphi2Cpp home Content |