Porady: definiowanie obiektów delegowanych (C++/CLI) oraz korzystanie z nich
W tym artykule przedstawiono sposób definiowania i zużywają delegatów w C++/CLI.
Chociaż.NET Framework zapewnia liczbę delegatów, czasami może zajść do definiowania nowych pełnomocników.
Poniższy przykład kodu definiuje delegata, który nosi nazwę MyCallback.Kod obsługi zdarzeń — funkcja, która jest wywoływana, gdy ten nowy obiekt delegowany jest uruchamiany — musi mieć typ zwracany z void i String odniesienia.
Główną funkcją używa statycznej metody, która jest zdefiniowana przez SomeClass do utworzenia wystąpienia MyCallback delegować.Pełnomocnik wtedy staje się alternatywną metodę wywołania tej funkcji, jak pokazano przez wysłanie ciągu "jeden" do obiektu delegowanego.Następnie, dodatkowe wystąpienia MyCallback są ze sobą powiązane, a następnie wykonywane przez jedno wywołanie obiektu delegowanego.
// 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;
}
Dane wyjściowe
Następny przykładowy kod ilustruje skojarzyć pełnomocnik członek klasy wartość.
// 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();
}
Dane wyjściowe
Jak komponować delegatów
Można użyć "-" operatora, aby usunąć składnik pełnomocnik z pełnomocnik składa się.
// 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");
}
Dane wyjściowe
Przekazać pełnomocnik ^ do macierzystego funkcja oczekuje, że wskaźnik funkcji
Od składników zarządzanych można wywołać funkcję macierzystych za pomocą funkcji parametry wskaźnik gdzie macierzystych funkcji można wywoływać funkcję członka delegata składników zarządzanych.
W przykładzie tworzony plik .dll, że wywóz macierzystych funkcji:
// 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");
}
}
Następny przykład zużywa pliku .dll i przekazuje mu uchwyt delegowanego macierzystych funkcji, która oczekuje wskaźnika funkcji.
// 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
}
Dane wyjściowe
Aby skojarzyć delegatów z funkcji niezarządzane
Aby skojarzyć pełnomocnik za pomocą macierzystych funkcji, muszą zawinąć macierzystych funkcji w typu zarządzanego i zadeklarować funkcję powoływać się przez 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;
}
Dane wyjściowe
Użycie delegatów niezwiązanego
Niezwiązany delegowanego umożliwia przekaż wystąpienie typu, dla których chcesz się połączyć, gdy pełnomocnik jest wywoływana funkcja.
Niezwiązany delegatów są szczególnie przydatne, jeśli chcesz iteracyjne przeglądanie obiektów w kolekcji — za pomocą dla każdego z nich w słowa kluczowe — i wywołanie funkcji składowej na każde wystąpienie.
Aby zadeklarować, Utwórz wystąpienie, a wywołanie związany i niezwiązane pełnomocników:
Akcja |
Powiązane obiekty delegowane |
Pełnomocnicy niezwiązanego |
---|---|---|
Deklarujemy |
Podpis pełnomocnik musi odpowiadać podpisu funkcji, której chcesz się połączyć przez pełnomocnika. |
Pierwszy parametr podpisu delegata jest typ this dla obiektu, którego chcesz zatelefonować. Po pierwszy parametr podpisu delegata musi być zgodna z sygnaturą funkcji, której chcesz się połączyć przez pełnomocnika. |
Utwórz wystąpienie |
Podczas instancję związanego pełnomocnik, można określić funkcję wystąpienie lub funkcji składowej globalnych lub statycznych. Aby określić funkcję wystąpienie, pierwszy parametr jest wystąpienie typu funkcji członka, którego chcesz się połączyć, a drugi parametr jest adres funkcji, którą chcesz się połączyć. Jeśli chcesz wywołać funkcje globalnych lub statycznych elementów członkowskich, po prostu przekazać nazwę funkcja globalna lub nazwę funkcji członka statycznego. |
Gdy instancję niezwiązany delegata po prostu przekazać adres funkcji, którą chcesz się połączyć. |
Wywołanie |
Po wywołaniu związanego pełnomocnika, po prostu przekazać parametry, które są wymagane przez podpisu delegata. |
Sam, jak powiązanej delegować, ale pamiętaj, że pierwszy parametr musi być wystąpieniem obiektu, która zawiera funkcję, którą chcesz się połączyć. |
W przykładzie pokazano, jak zadeklarować, Utwórz wystąpienie i wywołać niezwiązany delegatów:
// 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();
}
Dane wyjściowe
Następny przykład pokazuje sposób używania niezwiązany delegatów i dla każdego z nich w słowa kluczowe, aby iteracyjne przeglądanie obiektów w kolekcji i wywoływać funkcje elementów członkowskich w każdym wystąpieniu.
// 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();
}
W przykładzie tworzony niezwiązany delegowanego do Akcesory właściwości:
// 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));
}
Dane wyjściowe
Poniżej pokazano jak wywołać multiemisji pełnomocnik, gdzie jedno wystąpienie jest związany i jedno wystąpienie jest niezwiązany.
// 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);
};
Dane wyjściowe
Następny przykład pokazuje, jak utworzyć i wywołać niezwiązany Delegat rodzajowy.
// 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) );
}
Dane wyjściowe