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 trzeba do definiowania nowych pełnomocników.
Poniższy przykład kodu definiuje pełnomocnika, który nazywa się MyCallback.Kod obsługi zdarzeń — funkcji, która jest wywoływana, gdy jest uruchamiany ten nowy delegat — musi mieć typ zwracany 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 staje się alternatywna metoda wywołanie tej funkcji, jak pokazano przez wysłanie ciągu "jeden" do obiektu delegowanego.Następny, dodatkowe wystąpienia MyCallback są ze sobą powiązane i 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ład kodu pokazuje jak powiązać delegata z członkiem 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ć "-" operator, aby usunąć pełnomocnik składnika z składa pełnomocnik.
// 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 macierzystych funkcji, która oczekuje, że wskaźnik funkcji
Od składników zarządzanych można wywołać macierzystych funkcji z funkcją parametry wskaźnik gdzie funkcja macierzystego można wywoływać funkcji składowej obiektu delegowanego 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 angażuje pliku .dll i przechodzi uchwyt pełnomocnika do macierzystych funkcji, która oczekuje, że wskaźnik 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ądzanych
Aby skojarzyć pełnomocnik z rodzimych 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
Aby użyć niezwiązanego delegatów
Niezwiązany delegowanego umożliwia Przekaż wystąpienie typu, którego 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ą for each, in słowa kluczowe — i wywołanie funkcji członka na każde wystąpienie.
Aby zadeklarować, wystąpienia i wywołania związane i niezwiązane pełnomocników:
Akcja |
Powiązane delegatów |
Niezwiązany delegatów |
---|---|---|
Deklaruj |
Podpis pełnomocnik musi odpowiadać podpisu funkcji, do której chcesz zadzwonić przez pełnomocnika. |
Pierwszy parametr podpisu delegata jest typ this dla obiektu, który chcesz wybrać. Po pierwszym parametr podpisu delegata musi odpowiadać podpisu funkcji, do której chcesz zadzwonić przez pełnomocnika. |
Utwórz wystąpienie |
Podczas wystąpienia związanego pełnomocnik, można określić funkcję wystąpienie lub funkcji globalnych lub statyczny element członkowski. Aby określić funkcję wystąpienie, pierwszy parametr jest wystąpienie typu funkcji członka, którego chcesz zadzwonić, a drugi parametr jest adresem funkcji, do której chcesz zadzwonić. Jeśli chcesz wywołać funkcję globalnego lub statyczny element członkowski, po prostu przekazać nazwę funkcja globalna lub nazwę funkcji członka statycznego. |
Podczas wystąpienia niezwiązany pełnomocnika, po prostu przekazać adres funkcji, do której chcesz zadzwonić. |
Wywołanie |
Po wywołaniu związanego pełnomocnika, po prostu przekazać parametry, które są wymagane przez podpisu delegata. |
Sama jak powiązanej delegować, ale należy pamiętać, że pierwszy parametr musi być wystąpieniem obiektu, który zawiera funkcję, którą chcesz wywołać. |
Ten przykład ilustruje sposób zadeklarować, wystąpienia i wywołać delegatów niezwiązany:
// 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 ilustruje sposób użycia niezwiązany delegatów i for each, in słowa kluczowe, aby iteracyjne przeglądanie obiektów w kolekcji i wywołanie funkcji członka na każde wystąpienie.
// 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 jest niezwiązany pełnomocnika 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ższy przykładowy pokazuje, 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