Sdílet prostřednictvím


Postup: definovat a používat delegáty

Tento článek ukazuje, jak definovat a spotřebovávat delegáty v C++/CLI.

I když rozhraní.NET Framework poskytuje několik delegátů, někdy pravděpodobně muset definovat nové delegáty.

Následující příklad kódu definuje delegáta s názvem MyCallback.Kód pro zpracování události – funkce, která je volána při vyvolání tohoto delegáta nové – musí mít návratový typ void a String odkaz.

Hlavní funkce, která používá statickou metodu, která je definovaná pomocí SomeClass k vytvoření instance MyCallback delegáta.Delegát se poté stane alternativní metoda volání této funkce prokázaný odesláním řetězce "jeden" objekt delegáta.Další, další výskyty MyCallback jsou navzájem propojeny a potom provedeny jedním voláním objektu delegáta.

// use_delegate.cpp
// compile with: /clr
using namespace System;

ref class SomeClass
{
public:
   static void Func(String^ str)
   {
      Console::WriteLine("static SomeClass::Func - {0}", str);
   }
};

ref class OtherClass
{
public:
   OtherClass( Int32 n ) 
   {
      num = n;
   }

   void Method(String^ str) 
   {
      Console::WriteLine("OtherClass::Method - {0}, num = {1}", 
         str, num);
   }

   Int32 num;
};

delegate void MyCallback(String^ str);

int main( ) 
{
   MyCallback^ callback = gcnew MyCallback(SomeClass::Func);   
   callback("single"); 

   callback += gcnew MyCallback(SomeClass::Func);   

   OtherClass^ f = gcnew OtherClass(99);
   callback += gcnew MyCallback(f, &OtherClass::Method);

   f = gcnew OtherClass(100);
   callback += gcnew MyCallback(f, &OtherClass::Method);

   callback("chained");

   return 0;
}

Výsledek

  

Další příklad kódu ukazuje, jak přidružit člena třídy hodnoty delegáta.

// mcppv2_del_mem_value_class.cpp
// compile with: /clr
using namespace System;
public delegate void MyDel();

value class A {
public:
   void func1() {
      Console::WriteLine("test");
   }
};

int main() {
   A a;
   A^ ah = a;
   MyDel^ f = gcnew MyDel(a, &A::func1);   // implicit box of a
   f();
   MyDel^ f2 = gcnew MyDel(ah, &A::func1);
   f2();
}

Výsledek

  

Jak vytvořit zástupce

Můžete použít "-" operátor odebrat součást delegáta z skládá delegáta.

// mcppv2_compose_delegates.cpp
// compile with: /clr
using namespace System;

delegate void MyDelegate(String ^ s);

ref class MyClass {
public:
   static void Hello(String ^ s) {
      Console::WriteLine("Hello, {0}!", s);
   }

   static void Goodbye(String ^ s) {
      Console::WriteLine("  Goodbye, {0}!", s);
   }
};

int main() {

   MyDelegate ^ a = gcnew MyDelegate(MyClass::Hello);
   MyDelegate ^ b = gcnew MyDelegate(MyClass::Goodbye);
   MyDelegate ^ c = a + b;
   MyDelegate ^ d = c - a;

   Console::WriteLine("Invoking delegate a:");
   a("A");
   Console::WriteLine("Invoking delegate b:");
   b("B");
   Console::WriteLine("Invoking delegate c:");
   c("C");
   Console::WriteLine("Invoking delegate d:");
   d("D");
}

Výsledek

  

Předat delegáta ^ nativní funkci, která očekává ukazatele na funkci

Z spravované komponenty můžete volat nativní funkce s funkcí ukazatele parametry kde nativní funkce pak můžete volat členské funkce delegáta spravované součásti.

Tento příklad vytvoří soubor knihovny DLL, která exportuje nativní funkce:

// delegate_to_native_function.cpp
// compile with: /LD
#include < windows.h >
extern "C" {
   __declspec(dllexport)
   void nativeFunction(void (CALLBACK *mgdFunc)(const char* str)) {
      mgdFunc("Call to Managed Function");
   }
}

Další ukázka využívá knihovny DLL a předá delegáta popisovač nativní funkci, která očekává ukazatele na funkci.

// delegate_to_native_function_2.cpp
// compile with: /clr
using namespace System;
using namespace System::Runtime::InteropServices;

delegate void Del(String ^s);
public ref class A {
public:
   void delMember(String ^s) {
      Console::WriteLine(s);
   }
};

[DllImportAttribute("delegate_to_native_function", CharSet=CharSet::Ansi)]
extern "C" void nativeFunction(Del ^d);

int main() {
   A ^a = gcnew A;
   Del ^d = gcnew Del(a, &A::delMember);
   nativeFunction(d);   // Call to native function
}

Výsledek

  

Delegáti přidružit nespravovaných funkcí

Pokud chcete přiřadit delegáta nativní funkci, nativní funkce zabalit do spravovaného typu a deklarovat funkce lze vyvolat pomocí PInvoke.

// mcppv2_del_to_umnangd_func.cpp
// compile with: /clr
#pragma unmanaged
extern "C" void printf(const char*, ...);
class A {
public:
   static void func(char* s) {
      printf(s);
   }
};

#pragma managed
public delegate void func(char*); 

ref class B {
   A* ap;

public:
   B(A* ap):ap(ap) {}
   void func(char* s) {
      ap->func(s); 
   }
};

int main() {
   A* a = new A;
   B^ b = gcnew B(a);
   func^ f = gcnew func(b, &B::func);
   f("hello");
   delete a;
}

Výsledek

  

Chcete-li použít nevázané delegát

Nevázané delegát lze předat instanci tohoto typu, jejíž funkce chcete volat, pokud je volána delegát.

Nevázané Delegáti jsou zvláště užitečné, pokud chcete pro iteraci objektů v kolekci – pomocí pro každý v klíčová slova a volat členské funkce pro každou instanci.

Postup pro deklarování, vytváření instancí a vázané a nevázané delegát volání:

Akce

Vázaný zástupce

Nevázané delegát

Deklarovat

Signatura delegáta musí odpovídat podpisu funkce, kterou chcete volat prostřednictvím delegáta.

První parametr delegáta je typ this pro objekt, který chcete volat.

Po první parametr delegáta musí odpovídat podpisu funkce, kterou chcete volat prostřednictvím delegáta.

Vytvořit instanci

Když konkretizujete vázané delegáta, můžete určit funkce instance aplikace nebo globální nebo statické členské funkce.

Chcete-li specifikovat funkci instance, první parametr je instance typu, jehož členská funkce chcete volat a druhý parametr je adresa funkce, kterou chcete volat.

Pokud chcete volat funkce globální nebo statické člen, stačí pouze předáte název globální funkce nebo název funkce statický člen.

Jestliže konkretizujete nevázané delegát, stačí předáte jeho adresu funkce, kterou chcete volat.

Volání

Při volání delegát vázané pouze předáte parametry, které jsou vyžadované delegáta.

Stejné jako vázaný delegovat, ale mějte na paměti, že první parametr musí být instance objektu, který obsahuje funkci, kterou chcete volat.

Tento příklad ukazuje, jak deklarovat instanci a nevázané delegát volání:

// unbound_delegates.cpp
// compile with: /clr
ref struct A {
   A(){}
   A(int i) : m_i(i) {}
   void Print(int i) { System::Console::WriteLine(m_i + i);}

private:
   int m_i;
};

value struct V {
   void Print() { System::Console::WriteLine(m_i);}
   int m_i;
};

delegate void Delegate1(A^, int i);
delegate void Delegate2(A%, int i);

delegate void Delegate3(interior_ptr<V>);
delegate void Delegate4(V%);

delegate void Delegate5(int i);
delegate void Delegate6();

int main() {
   A^ a1 = gcnew A(1);
   A% a2 = *gcnew A(2);

   Delegate1 ^ Unbound_Delegate1 = gcnew Delegate1(&A::Print);
   // delegate takes a handle
   Unbound_Delegate1(a1, 1);
   Unbound_Delegate1(%a2, 1);

   Delegate2 ^ Unbound_Delegate2 = gcnew Delegate2(&A::Print);
   // delegate takes a tracking reference (must deference the handle)
   Unbound_Delegate2(*a1, 1);
   Unbound_Delegate2(a2, 1);

   // instantiate a bound delegate to an instance member function
   Delegate5 ^ Bound_Del = gcnew Delegate5(a1, &A::Print);
   Bound_Del(1);

   // instantiate value types
   V v1 = {7};
   V v2 = {8};

   Delegate3 ^ Unbound_Delegate3 = gcnew Delegate3(&V::Print);
   Unbound_Delegate3(&v1);
   Unbound_Delegate3(&v2);

   Delegate4 ^ Unbound_Delegate4 = gcnew Delegate4(&V::Print);
   Unbound_Delegate4(v1);
   Unbound_Delegate4(v2);

   Delegate6 ^ Bound_Delegate3 = gcnew Delegate6(v1, &V::Print);
   Bound_Delegate3();
}

Výsledek

  

Další ukázka zobrazuje způsob použití nevázaných delegátů a pro každý v klíčová slova pro iteraci v kolekci objektů a volání členské funkce pro každou instanci.

// unbound_delegates_2.cpp
// compile with: /clr
using namespace System;

ref class RefClass {
   String^ _Str;

public:
   RefClass( String^ str ) : _Str( str ) {}
   void Print() { Console::Write( _Str ); }
};

delegate void PrintDelegate( RefClass^ );

int main() {
   PrintDelegate^ d = gcnew PrintDelegate( &RefClass::Print );

   array< RefClass^ >^ a = gcnew array<RefClass^>( 10 );

   for ( int i = 0; i < a->Length; ++i )
      a[i] = gcnew RefClass( i.ToString() );

   for each ( RefClass^ R in a )
      d( R );

   Console::WriteLine();
}

Tento příklad vytvoří delegáta nevázané na přístupové funkce vlastnosti:

// unbound_delegates_3.cpp
// compile with: /clr
ref struct B {
   property int P1 {
      int get() { return m_i; }
      void set(int i) { m_i = i; }
   }

private:
   int m_i;
};

delegate void DelBSet(B^, int);
delegate int DelBGet(B^);

int main() {
   B^ b = gcnew B;

   DelBSet^ delBSet = gcnew DelBSet(&B::P1::set);
   delBSet(b, 11);

   DelBGet^ delBGet = gcnew DelBGet(&B::P1::get);   
   System::Console::WriteLine(delBGet(b));
}

Výsledek

  

Následující příklad ukazuje, jak vyvolat delegát vícesměrového vysílání, kde jedna instance je vázán a není vázána jedna instance.

// unbound_delegates_4.cpp
// compile with: /clr
ref class R {
public:
   R(int i) : m_i(i) {}

   void f(R ^ r) {
      System::Console::WriteLine("in f(R ^ r)");
   }

   void f() {
      System::Console::WriteLine("in f()");
   }

private:
   int m_i;
};

delegate void Del(R ^);

int main() {
   R ^r1 = gcnew R(11);
   R ^r2 = gcnew R(12);

   Del^ d = gcnew Del(r1, &R::f);
   d += gcnew Del(&R::f);
   d(r2);
};

Výsledek

  

Další příklad ukazuje, jak vytvořit a nevázaného obecný delegát volání.

// unbound_delegates_5.cpp
// compile with: /clr
ref struct R {
   R(int i) : m_i(i) {}

   int f(R ^) { return 999; }
   int f() { return m_i + 5; }
   
   int m_i;
};

value struct V {
   int f(V%) { return 999; }
   int f() { return m_i + 5; } 

   int m_i;
};

generic <typename T>
delegate int Del(T t);

generic <typename T>
delegate int DelV(T% t);


int main() {   
   R^ hr = gcnew R(7);
   System::Console::WriteLine((gcnew Del<R^>(&R::f))(hr));

   V v;
   v.m_i = 9;
   System::Console::WriteLine((gcnew DelV<V >(&V::f))(v) );
}

Výsledek

  

Viz také

Referenční dokumentace

delegate (rozšíření komponent C++)