本文演示如何定义和使用 C++/CLI中的委托。
尽管 .NET Framework 提供大量委托,有时可能需要定义的新委托。
下面的示例定义了名为 MyCallback 的事件委托。调用的事件处理代码函数,这在此新委托是触发时必须为 void 的返回类型并采用 String 引用。
主函数使用由 SomeClass 定义的 MyCallback 实例化委托的静态方法。委托来调用该函数成为重写方法,如下面通过发送“唯一”的字符串委托对象。MyCallback 下,将的附加实例一起链接由委托对象的调用来执行。
// 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; }
Output
静态的 SomeClass::Func - 单 - 链接中的静态 SomeClass::Func - 链接中的静态 SomeClass::Func - 链接在一起的 OtherClass::Method,数字为 99 - 链接在一起的 OtherClass::Method,数字为 100
下面的代码示例演示如何将与关联委托的值类的成员。
// 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(); }
Output
测试 测试
- 运算符可用于从多播委托中移除组件委托。
// 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"); }
Output
调用委托 a: Hello, A! 调用委托 b: Goodbye,B! 调用委托 c: Hello, C! Goodbye,C! 调用委托 d: Goodbye,D!
在托管组件可以用函数调用本机函数然后可以调用托管组件委托的成员函数的指针参数的本机函数。
此示例创建将 .dll 的本机函数:
// 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"); } }
下一示例使用 .dll 句柄并将委托传递给需要函数指针的本机函数。
// 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 }
Output
为托管函数的调用
若要关联委托与本机函数,必须包装在托管类型的本机函数 (通过声明和 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; }
Output
hello
可以使用无约束的委托传递函数要调用类型的委托实例时调用。
如果要在中的对象集合循环访问由使用 for each,in 关键字和对每个实例,的成员的委托函数未绑定尤其有用。
这是如何,声明、实例化和调用绑定的设置和未绑定的委托:
操作 |
未绑定的委托 |
未绑定的委托 |
---|---|---|
Declare |
委托签名必须匹配要通过委托调用的函数的签名。 |
委托签名的第一个参数是 this 类型要调用对象的。 在第一个参数后得到,委托签名必须匹配要通过委托调用的函数的签名。 |
instantiate |
在实例化一限制的委托时,您可以指定该实例函数或全局或静态成员函数。 若要指定函数实例,第一个参数是一成员函数要调用,第二个参数为要调用函数地址类型的实例。 如果要调用全局或静态成员函数中,请将全局函数的名称或静态成员函数的名称。 |
在实例化一个无约束的委托时,请将传递要调用的函数的地址。 |
Call |
当您调用绑定的一个委托时,请将传递委托签名需要的参数。 |
和一个绑定的委托相同,但应记住,第一个参数必须为函数包含要调用对象的实例。 |
此示例演示如何,声明、实例化和调用无约束的委托:
// 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); 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(); }
Output
2 3 2 3 2 7 8 7 8 7
下一个示例显示如何使用未约束的委托和 for each,in 关键字通过循环访问集合中的对象并对每个实例的成员函数。
// 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( 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(); }
此示例创建未约束的委托给属性的访问器函数:
// 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)); }
Output
11
下面的示例演示如何调用多播委托,一个实例限制的,并且的示例是未绑定的。
// 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); };
Output
in f(R ^ r) 中 f() 中
下一个示例演示如何创建并调用一个不受约束的泛型委托。
// 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; }; genericdelegate int Del(T t); generic delegate int DelV(T% t); int main() { R^ hr = gcnew R(7); System::Console::WriteLine((gcnew Del (&R::f))(hr)); V v; v.m_i = 9; System::Console::WriteLine((gcnew DelV (&V::f))(v) ); }
Output
12 14