Comment gérer les méthodes anonymes Object Pascal dans C++

De Appmethod Topics
Aller à : navigation, rechercher

Remonter à Gestion des fonctionnalités Object Pascal dans Appmethod C++ - Index

Cette rubrique décrit quelques problèmes de programmation que vous pourriez rencontrer avec les méthodes anonymes, une des nouvelles fonctionnalités de Object Pascal.

Object Pascal implémente les types de méthode anonyme (aussi connus comme des références de méthode) via une interface qui implémente une méthode Invoke(...). Ainsi une méthode qui prend un paramètre référence de méthode dans Object Pascal est exposée dans C++ comme une méthode qui prend une interface. Par exemple :

 interface
 
 type
 
   TRefProc = reference to function (I, J: Integer): Integer;
 
   TTestClass = class
     public
       function TakeRefProc(RefProc: TRefProc; I, J: Integer): Integer;
   end;

Le code suivant est le fichier .hpp généré pour ci-dessus :

 __interface TRefProc;
 typedef System::DelphiInterface <TRefProc> _di_TrefProc;
 
 __interface TRefProc  : public System::IInterface
 {
 public:
  virtual int __fastcall Invoke(int I, int J) = 0 ;
 };
 
 class PASCALIMPLEMENTATION TTestClass : public System::TObject
 {
 public:
  int __fastcall TakeRefProc(_di_TRefProc RefProc, int I, int J);
 };

Le code C++ qui effectue une opération seek pour spécifier une fonction ou une fonction membre comme paramètre référence de méthode doit envelopper la dernière derrière une interface qui expose une méthode Invoke(). Un template C++ peut être utilisé pour l'encapsulation comme une interface. Le code C++ suivant montre un exemple d'un template qui peut être utilisé pour passer des fonctions membre ou des méthodes C++ en tant que références de méthode à Object Pascal.

 enum _DummyType{};      // Paramètre utilisé comme valeur par défaut
 
 template <typename INTF,   // Interface avec Invoke
                 typename F,   // Type fonction
                 typename R,   // Type de retour
                 typename P1 = _DummyType,  // Param #1
                 typename P2 = _DummyType,  // Param #2
                 typename P3 = _DummyType,  // Param #3
                 typename P4 = _DummyType,  // Param #4
                 typename P5 = _DummyType> // Param #5
 class TMethodRef : public TInterfacedObject, public INTF
 
 {
 private:
   F callback;
 public:
   TMethodRef(F _callback) : callback(_callback) {}
 
   HRESULT STDMETHODCALLTYPE QueryInterface (const GUID& riid, void** ppvObject)
   { return TInterfacedObject::QueryInterface (riid, ppvObject); }
   ULONG STDMETHODCALLTYPE AddRef()
   { return TInterfacedObject::_AddRef(); }
   ULONG STDMETHODCALLTYPE Release()
   { return TInterfacedObject::_Release(); }
 
 R __fastcall Invoke(P1 p1)
   {
     return callback(p1);
   }
   R __fastcall Invoke(P1 p1, P2 p2)
   {
     return callback(p1, p2);
   }
   R __fastcall Invoke(P1 p1, P2 p2, P3 p3)
   {
     return callback(p1, p2, p3);
   }
   R __fastcall Invoke(P1 p1, P2 p2, P3 p3, P4 p4)
   {
     return callback(p1, p2, p3, p4);
   }
   R __fastcall Invoke(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
   {
     return callback(p1, p2, p3, p4, p5);
   }
 };

Le code suivant montre comment utiliser le template présenté ci-dessus pour passer une routine C++ en tant que référence de méthode.

 // Fonction C++ que nous voulons passer en tant que référence de méthode.
 int multiplyCallback(int i, int j)
 {
   return i*j;
 }
 
 
 void UseRefProcFlat()
 {
   std::auto_ptr<TTestClass> cls(new TTestClass());
   _di_TRefProc proc = new 
     TMethodRef<TRefProc, int (*)(int, int), int, int, int>(multiplyCallback);
   int i = cls->TakeRefProc(proc, 10, 20);
   assert(i == 200);
 }

Vous pouvez aussi utiliser le template pour passer une fonction membre en tant que référence de méthode. Cela est illustré par le code suivant :

 class TMyClass {
 public:
   int add(int i, int j) {
     return i+j;
   }
 };
 typedef int (__closure *TClosure)(int, int);
 
 void UseRefProcMember()
 {
   TMyClass myClass;
 
   std::auto_ptr<TTestClass> cls(new TTestClass());
   _di_TRefProc proc = new 
     TMethodRef<TRefProc, TClosure, int, int, int>(&myClass.add);
 
   int i = cls->TakeRefProc(proc, 10, 20);
   assert(i == 30);
 }

Voir aussi