如何:定义和使用委托 (C++/CLI)

https://technet.microsoft.com/zh-CN/library/c320cx3h.aspx/

如何:定义和使用委托 (C++/CLI)

Visual Studio 2015
其他版本
 

本文演示如何定义和使用 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;
};

generic 
delegate 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

你可能感兴趣的:(如何:定义和使用委托 (C++/CLI))