﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-BeyondCN-随笔分类-C++</title><link>http://www.cppblog.com/BeyondCN/category/8519.html</link><description /><language>zh-cn</language><lastBuildDate>Sat, 08 Nov 2008 16:30:19 GMT</lastBuildDate><pubDate>Sat, 08 Nov 2008 16:30:19 GMT</pubDate><ttl>60</ttl><item><title>ISO C++实现 类似 C#的 Delegate</title><link>http://www.cppblog.com/BeyondCN/archive/2008/11/06/66180.html</link><dc:creator>BeyondCN</dc:creator><author>BeyondCN</author><pubDate>Thu, 06 Nov 2008 15:29:00 GMT</pubDate><guid>http://www.cppblog.com/BeyondCN/archive/2008/11/06/66180.html</guid><wfw:comment>http://www.cppblog.com/BeyondCN/comments/66180.html</wfw:comment><comments>http://www.cppblog.com/BeyondCN/archive/2008/11/06/66180.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/BeyondCN/comments/commentRss/66180.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/BeyondCN/services/trackbacks/66180.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.cppblog.com/BeyondCN/archive/2008/11/06/66180.html'>阅读全文</a><img src ="http://www.cppblog.com/BeyondCN/aggbug/66180.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/BeyondCN/" target="_blank">BeyondCN</a> 2008-11-06 23:29 <a href="http://www.cppblog.com/BeyondCN/archive/2008/11/06/66180.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Visual C++ .NET编程：托管C++概述</title><link>http://www.cppblog.com/BeyondCN/archive/2008/10/24/64921.html</link><dc:creator>BeyondCN</dc:creator><author>BeyondCN</author><pubDate>Fri, 24 Oct 2008 03:43:00 GMT</pubDate><guid>http://www.cppblog.com/BeyondCN/archive/2008/10/24/64921.html</guid><wfw:comment>http://www.cppblog.com/BeyondCN/comments/64921.html</wfw:comment><comments>http://www.cppblog.com/BeyondCN/archive/2008/10/24/64921.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/BeyondCN/comments/commentRss/64921.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/BeyondCN/services/trackbacks/64921.html</trackback:ping><description><![CDATA[<span  style="border-collapse: collapse; font-family: Verdana; font-size: 12px; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; "><div class="postTitle" style="background-image: url(http://www.cppblog.com/Skins/BlackSun/images/Topic.gif); background-repeat: no-repeat; padding-left: 15px; font-weight: bolder; font-size: 0.9em; margin-top: 6px; margin-bottom: 0px; "><a id="viewpost1_TitleUrl" href="http://www.cppblog.com/mzty/archive/2006/08/18/11393.html" style="color: rgb(0, 0, 0); text-decoration: none; ">Visual C++ .NET编程：托管C++概述</a></div><div class="postText" style="padding-right: 10px; padding-left: 15px; padding-bottom: 2px; padding-top: 2px; font: normal normal normal 13px/normal verdana, sans-serif; color: rgb(51, 51, 51); line-height: 17px; margin-top: 0px; ">2000年6月，Microsoft推出了&#8220;Microsoft.NET下一代互联网软件和服务战略&#8221;，引起IT行业的广泛关注。2000年9月，Microsoft在旧金山发布了Enterprise 2000。同月，Microsoft原总裁兼首席执行官鲍尔默来到中国就&#8220;下一代互联网&#8221;的主题进行演讲，在中国掀起了一股&#8220;.NET旋风&#8221;。2000年11月，Microsoft在Comdex计算机大展上发布了Visual Studio.NET软件，并展示了其.NET发展战略的框架体系和开发工具的相关特性，全面加速了Microsoft以.NET技术进军市场的步伐。&#160;<br><br>　　Microsoft的.NET战略意味着：Microsoft以及在Microsoft平台上的开发者将会制造服务，而不是制造软件。在未来几年之内，Microsoft将陆续发布有关.NET的平台和工具，用于在因特网上开发Web服务。那时，工作在.NET上的用户、开发人员和IT工作人员都不再购买软件、安装软件和维护软件。取而代之的是，他们将定制服务，软件会自动安装，所有的维护和升级也会通过互联网进行。&#8220;Microsoft.NET 代表了一个集合、一个环境、一个可以作为平台支持下一代Internet的可编程结构。&#8221;这就是鲍尔默对.NET的描述。<br><br><table width="80%" align="center"><tbody><tr><td style="font-size: 12px; "><a href="http://book.yesky.com/vc/vc2.htm" target="_blank" style="color: rgb(68, 68, 68); text-decoration: none; "></a></td></tr></tbody></table><br>　　作为.NET的最新特性组成部分，Microsoft .NET Framework是一个用于构建，部署和运行Web服务及应用程序的平台。它为将现有投资与下一代应用程序和服务的集成提供了高产的，基于标准的，多语言环境，同时它还用于解决Internet级应用程序的部署和操作问题。.NET框架包含三个主要部分：通用语言运行时，一组层次化的统一的类库，及组件化版本的动态服务器主页(称为ASP.NET)。<br><br>　　用于开发.NET Framework的语言有Visual C#、VB.NET和C++托管扩展(Managed Extensions for C++)。其中C#是开发.NET的元语言，而C++托管扩展是在C++基础上建立起来的，用来为Visual C++程序员开发.NET框架应用程序而设计。为叙述方便，我们将C++托管扩展就称之为&#8220;托管C++&#8221;。<br>为了帮助C/C++以及Visual C++程序员或爱好者快速使用托管C++开发.NET Framework程序，我们将陆续推出相关的一系列文章。<br><br>　　本篇&#8220;托管C++概述&#8221;主要讲述了什么是托管C++、开发.NET Framework(框架)的项目类型以及与标准C++之间的区别。<br><br>　　<strong><font color="#ac000">1、什么是托管C++？</font></strong><br><br>　　在回答这个问题，首先要搞清楚什么是&#8220;托管&#8221;(Managed)。托管是.NET的一个专门概念，它是融于通用语言运行时(CLR)中的一种新的编程理念，因此我们完全可以把&#8220;托管&#8221;视为&#8220;.NET&#8221;。那么什么是&#8220;通用语言运行时&#8221;？通用语言运行时是.NET 框架应用程序的执行引挚。它提供了许多服务，其中包括：代码管理(装入和执行)、类型安全性验证、元数据(高级类型信息)访问、为管理对象管理内存、管理代码，COM对象和预生成的DLLs(非管理代码和数据)的交互操作性、对开发人员服务的支持等等。<br><br>　　也就是说，使用托管C++意味着，我们的代码可以被CLR所管理，并能开发出具有最新特性如垃圾自动收集、程序间相互访问等的.NET框架应用程序。<br><br>　　由托管概念所引发的C++应用程序包括托管代码、托管数据和托管类三个组成部分。　　<br><br>　　(1)&#160;<strong>托管代码</strong>：.Net环境提供了许多核心的运行(RUNTIME)服务，比如异常处理和安全策略。为了能使用这些服务，必须要给运行环境提供一些信息代码(元数据)，这种代码就是托管代码。所有的C#、VB.NET、JScript.NET默认时都是托管的，但Visual C++默认时不是托管的，必须在编译器中使用命令行选项(/CLR)才能产生托管代码。<br><br>　　(2)&#160;<strong>托管数据</strong>：与托管代码密切相关的是托管数据。托管数据是由公共语言运行的垃圾回收器进行分配和释放的数据。默认情况下，C#、Visual Basic 和 JScript.NET 数据是托管数据。不过，通过使用特殊的关键字，C# 数据可以被标记为非托管数据。Visual C++数据在默认情况下是非托管数据，即使在使用 /CLR 开关时也不是托管的。<br><br>　　(3)<strong>&#160;托管类</strong>：尽管Visual C++数据在默认情况下是非托管数据，但是在使用C++的托管扩展时，可以使用&#8220;__gc&#8221;关键字将类标记为托管类。就像该名称所显示的那样，它表示类实例的内存由垃圾回收器管理。另外，一个托管类也完全可以成为 .NET 框架的成员，由此可以带来的好处是，它可以与其他语言编写的类正确地进行相互操作，如托管的C++类可以从Visual Basic类继承等。但同时也有一些限制，如托管类只能从一个基类继承等。需要说明的是，在托管C++应用程序中既可使用托管类也可以使用非托管类。这里的非托管类不是指标准C++类，而是使用托管C++语言中的__nogc关键字的类。<br><br><strong><font color="#ac0000">2、用托管C++可以开发.NET框架的项目类型<br><br></font></strong>　　使用托管C++应该是C++程序员编写.NET框架应用程序最好的一种选择，通过集成在Visual Studio.NET开发环境的托管C++向导，我们可以创建以下几种开发.NET框架的项目类型：<br><br>　　(1) 托管C++应用程序:用来创建一个支持托管扩展的单独C++应用程序，使用它还可创建任何类型的应用程序，包括.NET框架客户应用程序。<br><br>　　(2) 托管C++类库:用来创建一个支持托管扩展的C++DLL，使用它可以生成一个能被.NET框架应用程序调用的托管类型的组件。<br><br>　　(3) 托管C++空项目：用来创建一个空的托管项目，该项目只含有支持托管扩展的正确编译和链接的开关选项。使用它能将一个已有的C++源文件进入到一个托管环境中。<br><br>　　(4) 托管C++ Web服务：用于创建两个项目，一个是C++托管扩展项目，另一个是部署项目。<br><br>　　<strong><font color="#ac000">3、托管C++与标准C++的主要区别</font></strong><br><br>　　尽管托管C++是从标准C++建立而来的，但它与标准C++有着本质上的区别，这主要体现在以下几个方面：<br><br>　　<strong>(1) 广泛采用&#8220;名称空间&#8221;(namespace)</strong><br><br>　　名称空间是类型的一种逻辑命名方案，.NET使用该命名方案用于将类型按相关功能的逻辑类别进行分组，利用名称空间可以使开发人员更容易在代码中浏览和引用类型。当然，我们也可将名称空间理解成是一个&#8220;类库名&#8221;。&#160;<br><br>　　尽管很早Microsoft就在Visual C++中支持名称空间的编程方式，但是很少引起Visual C++程序员的普遍关注。现在在托管C++程序中，我们必须使用这一方式，即使用#using和using关键字。例如下面的简单程序代码是在控制台上输出&#8220;Hello World&#8221;：<br><br><table width="80%" bgcolor="#ffffff"><tbody><tr><td style="font-size: 12px; ">#using&#160;<mscorlib.dll><br>using namespace System;<br>int main(void)<br>{<br>Console::WriteLine(S"Hello World");<br>return 0;<br>}</mscorlib.dll></td></tr></tbody></table><br>　　代码中，#using是用来将一个元数据文件输入到托管C++程序中，这些文件可以是包含托管数据和结构的MSIL (Microsoft intermediate language，微软中间语言)文件，如DLL、EXE、OBJ文件等。mscorlib.dll是.NET框架的一个核心类库，包含主要的名称空间System。程序的第二行代码&#8220;using namespace System;&#8221;用来使用System名称空间。System是.NET框架根名称空间，包含最基本的类型，如用于数据流的输入/输出的System::IO等。<br><br>　　在对托管C++程序开发的不断深入，我们不久就会发现，许多类型的引用都要在程序的前面使用#using和using来进行。<br><br>　　<strong>(2) 基本数据类型的变化</strong><br><br>　　我们知道，标准C++语言的数据类型是非常丰富的。而托管C++的数据类型更加丰富，不仅包含了标准C++中的数据类型，而且新增了__int64(64位整型)、Decimal(96位十进制数)、String*(字符串类型)和Object*(对象类型)等类型，表1-1列出它们各自数据类型。<br><br><table cellspacing="0" width="80%" align="center" border="1"><tbody><tr><td width="139" height="19" style="font-size: 12px; ">类型描述</td><td width="203" height="19" style="font-size: 12px; ">标准C++类型名</td><td width="170" height="19" style="font-size: 12px; ">托管C++类型名</td><td width="70" height="19" style="font-size: 12px; ">长度(位)</td></tr><tr><td width="139" style="font-size: 12px; ">布尔型</td><td width="203" style="font-size: 12px; ">bool</td><td width="170" style="font-size: 12px; ">bool</td><td width="70" style="font-size: 12px; ">8</td></tr><tr><td width="139" height="19" style="font-size: 12px; ">字符型</td><td width="203" height="19" style="font-size: 12px; ">char</td><td width="170" height="19" style="font-size: 12px; ">signed char</td><td width="70" height="19" style="font-size: 12px; ">8</td></tr><tr><td width="139" style="font-size: 12px; ">无符号字符型</td><td width="203" style="font-size: 12px; ">unsigned char</td><td width="170" style="font-size: 12px; ">char</td><td width="70" style="font-size: 12px; ">8</td></tr><tr><td width="139" style="font-size: 12px; ">短整型</td><td width="203" style="font-size: 12px; ">short [int]</td><td width="170" style="font-size: 12px; ">short</td><td width="70" style="font-size: 12px; ">16</td></tr><tr><td width="139" style="font-size: 12px; ">无符号短整型</td><td width="203" style="font-size: 12px; ">unsigned short [int]</td><td width="170" style="font-size: 12px; ">unsigned short</td><td width="70" style="font-size: 12px; ">16</td></tr><tr><td width="139" style="font-size: 12px; ">整型</td><td width="203" style="font-size: 12px; ">int</td><td width="170" style="font-size: 12px; ">int 或 long</td><td width="70" style="font-size: 12px; ">32</td></tr><tr><td width="139" style="font-size: 12px; ">无符号整型</td><td width="203" style="font-size: 12px; ">unsigned [int]</td><td width="170" style="font-size: 12px; ">unsigned int 或 long</td><td width="70" style="font-size: 12px; ">32</td></tr><tr><td width="139" style="font-size: 12px; ">长整型</td><td width="203" style="font-size: 12px; ">long [int]</td><td width="170" style="font-size: 12px; ">long</td><td width="70" style="font-size: 12px; ">32</td></tr><tr><td width="139" style="font-size: 12px; ">无符号长整型</td><td width="203" style="font-size: 12px; ">unsigned long [int]</td><td width="170" style="font-size: 12px; ">unsigned long</td><td width="70" style="font-size: 12px; ">32</td></tr><tr><td width="139" style="font-size: 12px; ">单精度浮点型</td><td width="203" style="font-size: 12px; ">float</td><td width="170" style="font-size: 12px; ">float</td><td width="70" style="font-size: 12px; ">32</td></tr><tr><td width="139" style="font-size: 12px; ">双精度浮点型</td><td width="203" style="font-size: 12px; ">double</td><td width="170" style="font-size: 12px; ">double</td><td width="70" style="font-size: 12px; ">64</td></tr><tr><td width="139" style="font-size: 12px; ">长双精度浮点型</td><td width="203" style="font-size: 12px; ">long double</td><td width="170" style="font-size: 12px; ">--</td><td width="70" style="font-size: 12px; ">64</td></tr><tr><td width="139" style="font-size: 12px; ">Unicode字符</td><td width="203" style="font-size: 12px; ">--</td><td width="170" style="font-size: 12px; ">wchar_t</td><td width="70" style="font-size: 12px; ">16</td></tr><tr><td width="139" style="font-size: 12px; ">64位整型</td><td width="203" style="font-size: 12px; ">--</td><td width="170" style="font-size: 12px; ">__int64</td><td width="70" style="font-size: 12px; ">64</td></tr><tr><td width="139" style="font-size: 12px; ">无符号64位整型</td><td width="203" style="font-size: 12px; ">--</td><td width="170" style="font-size: 12px; ">unsigned __int64</td><td width="70" style="font-size: 12px; ">64</td></tr><tr><td width="139" style="font-size: 12px; ">96位十进制值</td><td width="203" style="font-size: 12px; ">--</td><td width="170" style="font-size: 12px; ">Decimal</td><td width="70" style="font-size: 12px; ">96</td></tr><tr><td width="139" style="font-size: 12px; ">对象类型</td><td width="203" style="font-size: 12px; ">--</td><td width="170" style="font-size: 12px; ">Object*</td><td width="70" style="font-size: 12px; ">32</td></tr><tr><td width="139" style="font-size: 12px; ">字符串类型</td><td width="203" style="font-size: 12px; ">--</td><td width="170" style="font-size: 12px; ">String*</td><td width="70" style="font-size: 12px; ">--</td></tr></tbody></table><br><br>　　需要注意的是，String和Object在定义一个变量时，注意要有星号(&#8220;*&#8221;)，但这个变量不是指针变量，这与标准C++的含义是不一样的。例如上面的代码可以改为：<br><br><table width="80%" bgcolor="#ffffff"><tbody><tr><td style="font-size: 12px; ">#using&#160;<mscorlib.dll><br>using namespace System;<br>int main(void)<br>{<br>String* hello = S"Hello World";<br>Console::WriteLine(hello);<br>return 0;<br>}</mscorlib.dll></td></tr></tbody></table>　<strong>(3) 新增三个托管C++类型：__gc class、__value class和__gc interface</strong><br><br>　　一个__gc类或结构意味着该类或结构的生命周期是由.NET开发平台自动管理及垃圾自动收集，用户不必自已去调用delete来删除。定义一个__gc类或结构和标准C++基本相似，所不同的是在class或struct前加上__gc，例如下面的代码：<br><br><table width="80%" bgcolor="#ffffff"><tbody><tr><td style="font-size: 12px; ">__gc class G {<br>public:<br>int k;<br>int sum(int);<br>};<br><br>G::sum(int i) {return i*(i + 1)/2;}<br>int main()<br>{<br>G * g = new G;<br>Console::WriteLine(g->sum(4)); // 结果输出10<br>return 0;<br>}</td></tr></tbody></table><br>　　<strong><font color="#ff0000">但要注意：</font></strong><br><br>　　A. 一个__gc类不能从一个非托管类中继承，且不能包含从它派生的非托管类。但一个__gc类最多可以从一个托管类中继承。<br><br>　　B. 一个__gc类不能定义成一个友元类或包含一个友元成员函数。所谓友元函数，是用来让外部函数访问类中的私有和保护类型成员。<br><br>　　C. 一个__gc类不能声明或定义以及重载new或delete操作以及不能包含using等声明。<br><br>　　__value类是用来使用具有短生命期的小型数据项，它不同于__gc类。__gc类数据分配在CLR堆中，而__value类对象是在运行栈或称为NDP(.NET Developer Platform，.NET开发者平台)堆中创建的，从而避免了垃圾回收器不断分配和释放空间而带来的开销。一个__value类可以声明成为一个局部变量、参数和返回值，也可嵌入到一个__gc类中或是作为一个静态变量或在C++堆中分配的变量。例如下面的代码：<br><br><table width="80%" bgcolor="#ffffff"><tbody><tr><td style="font-size: 12px; ">#using&#160;<mscorlib.dll><br>using namespace System;<br>__value struct V { int i; };<br>__gc struct G { V v; }; // 嵌入到__gc类中<br>V f(V v) { // 定义一个全局函数，其值存储在运行栈中<br>v.i += 1; // 不影响原来形参v的值<br>return v; // 返回V结构类型的值<br>}<br>int main(void)&#160;<br>{<br>V v1 = {10}; // 在运行栈中声明并初始化<br>V v2 = f(v1); // 调用f函数，此时v1中的i为10，而v2中的i为11<br>G *pG = new G; // 为G实例分配堆空间<br>pG->v = v1; // pG的v中的i为10<br>pG->v.i += v2.i; // pG的v中的i为10+11=21<br>Console::WriteLine(v1.i); // 输出结果为10<br>Console::WriteLine(v2.i); // 输出结果为11<br>Console::WriteLine(pG->v.i); // 输出结果为21<br>return 0;<br>}</mscorlib.dll></td></tr></tbody></table><br>　　除此之外，所有的__gc对象都是从类System::Object派生而来，因而能够很容易使用作用在__gc类中的集合和映射功能。然而__value类型并没有与这个基类所共享，因而不能直接将__value作为函数中的Object*实参。为了解决这个问题，.NET允许我们使用__box关键字将一个__value类型视为一个__gc对象。此时__value类型被封装成一个__gc类桩子(Stub)，并被复制到NDP堆中。由于在托管C++中，box不具备隐式转换的功能，因此在转换时必须指明转换的类型。<br><br>　　托管C++中的__gc接口最能体现COM接口的思想，它的定义和声明是非常简单的，它除了关键字不同外，与一个__gc类的声明极为相似。例如下面的代码定义了一个接口IMyBase，其中包含了一个f的方法：<br><br><table width="80%" bgcolor="#ffffff"><tbody><tr><td style="font-size: 12px; ">__gc __interface Ibase {<br>void f();<br>};</td></tr></tbody></table><br>　　需要说明的是，接口中所有的方法默认时都是纯虚的且都是公有的，我们不需要在方法之前使用virtual关键字或在方法之后加上&#8220;= 0&#8221;。其次，在一个__gc接口中不能包含数据成员以及静态成员，也不能包含任何类的声明。下面举一个示例来说明__gc接口的使用：<br><br><table width="80%" bgcolor="#ffffff"><tbody><tr><td style="font-size: 12px; ">#using&#160;<mscorlib.dll><br>using namespace System;<br><br>__gc __interface Ibase1 {<br>int f(int);<br>};<br>__gc __interface Ibase2 {<br>int f(int);<br>};<br>__gc struct C: Ibase1, Ibase2 {<br>int f(int i) { // 接口方法的实现<br>return 2*i-1;<br>};<br>};<br><br>int main(void){<br>C* c = new C;<br>Console::WriteLine((c -> f(1)).ToString()); // 输出结果为1<br>Console::WriteLine((__try_cast&#160;<ibase1 *="">(c)->f(2)).ToString());&#160;<br>// 输出结果为3<br><br>Console::WriteLine((__try_cast&#160;<ibase2 *="">(c)->f(3)).ToString());<br>// 输出结果为5<br><br>return 0;<br>}</ibase2></ibase1></mscorlib.dll></td></tr></tbody></table><br>　　代码中，__try_cast用来将某个对象转换成一个指定类型，并当类型转换失败时自动处理由此产生的异常。ToString用来将对象描述成一个字符串。<br><strong>(4) 简化属性操作<br><br></strong>　　在__gc类中可以使用.NET的属性，这个属性简化了属性函数的调用操作，这与标准C++中的属性不一样。在标准C++中分别通过get_和put_成员函数来设置或获取相关属性的值。现在，托管C++中的属性操作就好比是对一个属性变量进行操作，例如下列代码：<br><br><table width="80%" bgcolor="#ffffff"><tbody><tr><td style="font-size: 12px; ">#using&#160;<mscorlib.dll><br>using namespace System;<br><br>__gc class G {<br>public:<br>__property int get_Size() {<br>Console::WriteLine(S"get_属性");<br>return nSize;<br>};<br>__property void set_Size(int i) {&#160;<br>Console::WriteLine(S"set_属性");<br>nSize = i;<br>};<br>private:<br>int nSize;<br>};<br><br>int main() {<br>G * pG = new G;<br>pG->Size = 10; // 调用set_Size<br>int i = pG->Size; // 调用get_Size<br>Console::WriteLine(i);<br>}</mscorlib.dll></td></tr></tbody></table><br>　　程序结果为：<br><br>　　　set_属性<br><br>　　　get_属性<br><br>　　　10<br><br>　　需要说明的是，托管C++使用__property关键字来定义一个属性的成员函数。从代码中可以看出设置和获取属性的成员函数名称中分别使用了set_和get_，这样编译器会自动生成一个伪成员变量Size，这个变量名是set_和get_成员函数后面的名称。注意不要再在get_成员函数代码中使用这个伪成员变量Size，它会引起该函数的递归调用。<br><br>　　<strong>(5) 托管C++的委派</strong><br><br>　　在C/C++中，一个函数的地址就是内存地址。这个地址不会带有任何其它附加信息，如函数的参数个数、参数类型、函数的返回值类型以及这个函数的调用规范等。总之，C/C++的回调函数不具备类型安全性。而.NET框架在回调函数的基础增加了提供类型安全的机制，称为委派。<br><br>　　托管C++的委派方法不像C#那么复杂，它简化了委派绝大部分的内部机制，因而使得它的使用变成非常简单容易。例如下面的代码：<br><br><table width="80%" bgcolor="#ffffff"><tbody><tr><td style="font-size: 12px; ">#using&#160;<mscorlib.dll><br>using namespace System;<br><br>__delegate int GetDayOfWeek(); // 委派方法的声明<br>__gc class MyCalendar<br>{<br>public:<br>MyCalendar() : m_nDayOfWeek(4) {}<br>int MyGetDayOfWeek() {<br>Console::WriteLine("非静态方法");&#160;<br>return m_nDayOfWeek;&#160;<br>}<br>static int MyStaticGetDayOfWeek() {&#160;<br>Console::WriteLine("静态方法");&#160;<br>return 6;&#160;<br>}<br>private:<br>int m_nDayOfWeek;<br>};<br><br>int main(void)<br>{<br>GetDayOfWeek * pGetDayOfWeek; // 声明委派类型变量<br>int nDayOfWeek;<br><br>// 将类的静态方法MyStaticGetDayOfWeek绑定成委派<br>pGetDayOfWeek = new GetDayOfWeek(0, &amp;MyCalendar::MyStaticGetDayOfWeek);<br>nDayOfWeek = pGetDayOfWeek->Invoke(); // 委派的调用<br>Console::WriteLine(nDayOfWeek);<br><br>// 将一个类的实例绑定成委派<br>MyCalendar * pcal = new MyCalendar();<br>pGetDayOfWeek =&#160;<br>static_cast<getdayofweek*>(Delegate::Combine(pGetDayOfWeek,<br>new GetDayOfWeek(pcal, &amp;MyCalendar::MyGetDayOfWeek)));<br>nDayOfWeek = pGetDayOfWeek->Invoke();<br>Console::WriteLine(nDayOfWeek);<br><br>// 删除绑定委派的类实例<br>pGetDayOfWeek =&#160;<br>static_cast<getdayofweek*>(Delegate::Remove(pGetDayOfWeek,<br>new GetDayOfWeek(pcal, &amp;MyCalendar::MyGetDayOfWeek)));<br><br>return 0;<br>}</getdayofweek*></getdayofweek*></mscorlib.dll></td></tr></tbody></table><br>　　输出结果是：<br><br>　　　静态方法<br>　　<br>　　　6<br><br>　　　静态方法<br><br>　　　非静态方法<br><br>　　　4<br><br>　　<strong><font color="#ac000">4、结速语</font></strong><br><br>　　总之，使用托管C++是C++程序员编写.NET框架应用程序最好的一种选择，在充分理解.NET框架基础上，避免了使用其他语言如C#、VB.NET所带来的额外开销。</div></span>
<img src ="http://www.cppblog.com/BeyondCN/aggbug/64921.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/BeyondCN/" target="_blank">BeyondCN</a> 2008-10-24 11:43 <a href="http://www.cppblog.com/BeyondCN/archive/2008/10/24/64921.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>