Comment : définir et utiliser des délégués (C++/CLI)
Cet article explique comment définir et utiliser des délégués dans C++/CLI.
Bien que le.NET Framework fournit un certain nombre de délégués, quelquefois vous souhaiterez peut-être définir de nouveaux délégués.
L'exemple de code suivant définit un délégué nommé MyCallback.La fonction de - le code de gestion des événements qui est appelée lorsque ce nouveau délégué est déclencher- doit avoir un type de retour d' void et prendre une référence d' String .
La fonction principale utilise une méthode statique définie par SomeClass pour instancier le délégué d' MyCallback .Le délégué devient alors une autre méthode pour appeler cette fonction, comme expliqué en envoyant la chaîne « dans » à l'objet délégué.Suivantes, de autres instances d' MyCallback sont attachées ensemble puis exécutées par un appel à l'objet délégué.
// 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;
}
Sortie
L'exemple de code montre comment associer un délégué à un membre d'une classe de valeur.
// 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();
}
Sortie
Composez comment les délégués
Vous pouvez utiliser l'opérateur « - » pour supprimer un délégué composant d'un délégué composite.
// 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");
}
Sortie
Passez un delegate^ à une fonction native qui nécessite un pointeur fonction
D'un composant managé vous pouvez appeler une fonction native avec les paramètres de pointeur fonction où la fonction native peut appeler la fonction membre du délégué du composant managé.
Cet exemple crée le fichier .dll qui exporte la fonction native :
// 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");
}
}
L'exemple utilise le fichier .dll et passe un handle de délégué à la fonction native qui nécessite un pointeur fonction.
// 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
}
Sortie
Pour associer des délégués avec des fonctions non managées
Pour associer un délégué à une fonction native, vous devez encapsuler la fonction native dans un type managé et déclarer la fonction à appeler via 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;
}
Sortie
Pour utiliser les délégués indépendants
Vous pouvez utiliser un délégué indépendant de passer une instance du type dont la fonction que vous souhaitez appeler lorsque le délégué est appelé.
Les délégués indépendantes sont particulièrement utiles si vous souhaitez effectuer une itération au sein de les objets dans un collection- par utiliser pour chaque, dans mots clés- et appeler une fonction membre sur chaque instance.
Voici comment déclarer, instancier, puis appeler la limite et les délégués annulés la liaison :
Action |
Délégués limite |
Délégués indépendants |
---|---|---|
Declare |
La signature du délégué doit correspondre à la signature de la fonction que vous souhaitez appeler le biais de le délégué. |
Le premier paramètre de la signature du délégué est le type d' this pour l'objet que vous souhaitez appeler. Après le premier paramètre, la signature du délégué doit correspondre à la signature de la fonction que vous souhaitez appeler le biais de le délégué. |
Instancié |
Lorsque vous instanciez un délégué lié, vous pouvez spécifier une fonction d'instance, ou un global ou une fonction membre statique. Pour spécifier une fonction d'instance, le premier paramètre est une instance du type dont la fonction membre vous souhaitez appeler et le deuxième paramètre est l'adresse de la fonction que vous souhaitez appeler. Si vous voulez appeler un global ou une fonction membre statique, passez simplement le nom d'une fonction globale ou le nom de la fonction membre statique. |
Lorsque vous instanciez un délégué indépendant, passez simplement l'adresse de la fonction que vous souhaitez appeler. |
Call |
Lorsque vous appelez un délégué lié, passez simplement les paramètres requis par la signature du délégué. |
De la même façon qu'un délégué lié, mais mémoriser fait que le premier paramètre doit être une instance de l'objet qui contient la fonction que vous souhaitez appeler. |
Cet exemple montre comment déclarer, instancier, et appeler les délégués indépendants :
// 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();
}
Sortie
L'exemple montre comment utiliser les délégués indépendants et les mots clés de pour chaque, dans pour itérer au sein de les objets dans une collection et appeler une fonction membre sur chaque instance.
// 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();
}
Cet exemple crée un délégué indépendant aux fonctions de l'utilisateur d'une propriété :
// 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));
}
Sortie
L'exemple suivant montre comment appeler un délégué multicast, où une instance est liée et une instance est annulée la liaison.
// 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);
};
Sortie
L'exemple montre comment créer et appeler un délégué générique indépendant.
// 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) );
}
Sortie