中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档 | 网通镜像
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 编程语言 > 综合其它
实例解析C++/CLI之代理与事件(2)
作者:佚名 时间:2007-09-24 16:37 出处:中国IT实验室 责编:月夜寒箫
              摘要:实例解析C++/CLI之代理与事件(2)

在标号6中,创建了一个Compare代理类型的实例,用它来包装StrCompare::CompareIgnoreCase,并把此代理句柄传递给Sort函数,其将会利用比较函数进一步进行处理。

正如大家所看到的,Sort可接受一个代理类型的参数--而此参数可像其他函数参数一样,可为传值、传址、传引用。

在标号7中,调用了FindComparisonMethod函数,其返回一个Del代理类型,接着在标号7及8中调用了包装过的函数。此处要重点说一下标号8:首先,FindComparisonMethod函数是被调用来获取代理实例--其常用于调用底层函数;其次,这两个函数的调用操作符都有同等的优先级,所以它们从左至右调用。

FindComparisonMethod函数中也用了一些逻辑用于确定到底需要包装哪个函数,此处就未作详细说明了。

代理类型的兼容性

一个代理类型只与它自身相兼容,与其他任何代理类型都不兼容,即使其他类型的包装函数均为同一类型。请看例3,非常明显,代理类型D1与函数A::M1与A::M2兼容,代理类型D2也与这些函数兼容,然而,这两个代理类型在标号5、6、8、9中并不能互换使用。

例3:

            

delegate void D1();

delegate void D2();

public struct A

{

 static void M1() { /* ... */ }

 static void M2() { /* ... */ }

};

void X(D1^ m) { /* ... */ }

void Y(D2^ n) { /* ... */ }

int main()

{

 D1^ d1;

 /*1*/ d1 = gcnew D1(&A::M1); //兼容

 /*2*/ d1 = gcnew D1(&A::M2); //兼容

 D2^ d2;

 /*3*/ d2 = gcnew D2(&A::M1); //兼容

 /*4*/ d2 = gcnew D2(&A::M2); //兼容

 /*5*/ d1 = d2; //不兼容

 /*6*/ d2 = d1; //不兼容

 /*7*/ X(d1); //兼容

 /*8*/ X(d2); //不兼容

 /*9*/ Y(d1); //不兼容

 /*10*/ Y(d2); //兼容

}

代理类型的合并

一个代理实例实际上能包装多个函数,在这种情况下,被包装的函数集被维护在一个调用列表中,当合并两个代理实例时,它们的调用列表也以指定的顺序连接起来,并产生一个新的列表,而现有的两个列表并没有发生改变。当从调用列表中移除一个或多个函数时,也会产生一个新的列表,且原始列表不会发生变化。请看例4中的代码,每个函数调用后的输出都写在相应函数后。

例4:

            

using namespace System;

delegate void D(int x);

ref struct Actions

{

 static void F1(int i)

 {

Console::WriteLine("Actions::F1: {0}", i);

 }

 static void F2(int i)

 {

Console::WriteLine("Actions::F2: {0}", i);

 }

 void F3(int i)

 {

Console::WriteLine("instance of Actions::F3: {0}", i);

 }

};

int main()

{

 /*1*/ D^ cd1 = gcnew D(&Actions::F1); //包含F1的调用列表

 cd1(10);

 Actions::F1: 10

 /*2*/ D^ cd2 = gcnew D(&Actions::F2); //包含F2的调用列表

 cd2(15);

 Actions::F2: 15

 /*3*/ D^ cd3 = cd1 + cd2; //包含F1 + F2的调用列表

 cd3(20);

 Actions::F1: 20

 Actions::F2: 20

 /*4*/ cd3 += cd1; //包含F1 + F2 + F1的调用列表

 cd3(25);

 Actions::F1: 25

 Actions::F2: 25

 Actions::F1: 25

 Actions^ t = gcnew Actions();

 D^ cd4 = gcnew D(t, &Actions::F3);

 /*5*/ cd3 += cd4; //包含F1 + F2 + F1 + t->F3的调用列表

 cd3(30);

 Actions::F1: 30

 Actions::F2: 30

 Actions::F1: 30

 instance of Actions::F3: 30

 /*6*/ cd3 -= cd1; //移除最右边的F1

 cd3(35); //调用F1、F2,t->F3

 Actions::F1: 35

 Actions::F2: 35

 instance of Actions::F3: 35

 /*7*/ cd3 -= cd4; //移除t->F3

 cd3(40); //调用F1、F2

 /*8*/ cd3 -= cd1; //移除F1

 cd3(45); //调用F2

 /*9*/ cd3 -= cd2; //移除F2,调用列表现在为空

 /*10*/Console::WriteLine("cd3 = {0}",

 (cd3 == nullptr ? "null" : "not null"));

}

Actions::F1: 40

Actions::F2: 40

Actions::F2: 45

cd3 = null

代理可通过 + 和 += 操作符来合并,如标号3、4中所示。两个单入口列表会连接成一个新的双入口列表,以先左操作数,后右操作数的顺序。新的列表被cd3引用,而现有的两个列表并未改变。在此要注意的是,不能合并不同类型的代理。

关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有