
2.4 托管方式
托管方式是使用托管C++语言和.NET Framework开发的Windows应用程序。托管C++对ISO/ANSI C++进行了扩展,以便更好地支持.NET编程环境。.NET Framework是一个编程框架,它对操作系统进行了封装,使得用.NET Framework开发的应用程序和操作系统特性无关,类似于Java的虚拟机JVM,因此,只要操作系统支持.NET Framework,其应用程序就可以在上面运行,而且不需要重新编译。此外,.NET Framework会对用户程序进行管理,故用这种方式开发的Windows程序习惯称为托管程序。下面我们对托管程序开发涉及的概念进行简要介绍。
2.4.1 .NET Framework的概念
.NET Framework是微软近十年力推的一套应用程序开发框架,该套框架具有跨平台和跨语言的特点。它主要是用来对付Java开发平台的。我们知道,传统的编译器是把高级语言编译成可执行的二进制码,然后直接运行。而Java开发平台是先把Java语言解释成中间语言,这个中间语言再在Java虚拟机(JVM)中执行,有了虚拟机就可以实现Java的跨平台,只要目标平台支持Java虚拟机即可,除了跨平台外,虚拟机还能对用户代码进行管理,比如安全检查、内存垃圾回收等,而这些优点克服了传统开发语言容易出现的内存泄露等问题(当然这些问题都是人为疏忽造成的),这就使得Java大为流行起来。微软作为软件巨头为了紧跟技术步法就推出了.NET Framework。在.NET Framework平台开发出来的程序,也是在.NET Framework的虚拟机中执行的,并且.NET Framework也用用户代码进行管理,比如安全检查、内存垃圾回收等,而且比Java更胜一筹的是,.NET Framework是编译执行的,而Java虚拟机是解释执行的,大家知道编译执行的速度比解释执行的速度要快的多。此外,.NET Framework支持多种语言,如C++、C#、Visual Basic等,大家可以选择自己熟悉的语言进行开发,而每种语言调用的系统库函数都来自.NET Framework类库,因此除了语言差异外,其他的差别就很小了,这使得会用C++开发.NET程序的人也很容易转到其他语言的开发,因为类库是一样的。
.NET Framework是一套很大的开发框架,主要由两部分构成:公共语言运行时库(Common Language Runtime, CLR)和.NET Framework类库。
.NET Framework是微软大力支持的一个开发平台,在Visual C++ 2013中,.NET Framework的版本已经发展到4.5.1了。
2.4.2 公共语言运行时库(CLR)
公共语言运行时库也称为.NET运行库。为了让.NET Framework实现跨平台,微软首先提出了一套语言规范——通用语言基础结构(CLI),而CLR就是微软对它的实现。在托管编程中,高级语言会先编译成微软中间语言(Microsoft IL, MSIL),然后CLR里的JIT(Just-In-Time)编译器再把MSIL编译成目标平台专用的代码,同时CLR还对代码进行内存管理、线程管理等来提高程序的安全可靠性,因此CLR中运行的程序是托管的,托管程序通过CLR和操作系统进行通信。
现在CLR已经被ECMA(欧洲计算机制造)的CLI标准(ECMA-335)收录,并且CLI也被ISO认可,并定为ISO/IEC 23271的标准。支持CLR的C++也被称为C++/CLI,或直接叫做托管C++,而传统C++编程因为其代码直接被编译为本地机器代码,并且没有CLR提供的安全性检查、自动内存释放等服务,因此传统C++也称为非托管C++或本地C++。
2.4.3 .NET Framework类库
.NET Framework类库是生成.NET应用程序、组件和控件的编程基础。现代编程语言都离不开类库的支持,比如传统的Viusal C++以MFC作为类库,Delphi和C++ Builder以Visual C++L作为类库。.NET Framework类库提供了数据库、网络、文件、多媒体等各方面编程的支持。
.NET Framework类库十分庞大,本书以MFC为主,因此对.NET Framework类库的使用只能进行简单的介绍。
2.4.4 第一个托管C++控制台程序
这里我们通过托管C++来写一个“Hello World”程序,程序结构和传统C++类似,打印语句用了传统C++中的cout和.Net Framework托管C++中的类库函数。
【例2.5】 第一个托管C++控制台程序
(1)打开Visual C++ 2013,选择菜单“新建”|“项目”,或直接按快捷键Ctrl+Shift+N,弹出“新建项目”对话框,在该对话框上,在左边展开“模板”|Visual C++|CLR,然后在右边选择“CLR控制台应用程序”,如图2-14所示。

图2-14
然后在下面“名称”文本框中输入项目名称,如“Test”,并输入一个项目位置。最后单击“确定”按钮。随后会出现Test.cpp的代码编辑窗口,Visual C++向导已经为我们生成了一个完整的main函数,代码如下:
#include "stdafx.h" using namespace System; //使用System命名空间 int main(array<System::String ^> ^args) { Console::WriteLine(L"Hello World"); //在控制台上打印Hello World return 0; }
在上面代码中,System是一个命名空间,命名空间相当于一个包含类声明作用域,用来处理程序中常见的同名冲突。比如标准C++库中所包含的所有内容(包括常量、变量、结构、类和函数等)都被定义在命名空间std中。而托管C++中也有很多命名空间,对命名空间中成员的引用,需要使用命名空间的作用域解析运算符::。
args是一个命令行参数,它的类型是String^,相当于一个字符串指针。
Console::WriteLine是向控制台窗口打印内容的类函数。Console是一个类,表示控制台应用程序的标准输入流、输出流和错误流,该类位于命名空间System中。函数WriteLine在输出内容后,会自动换行,如果不需要换行,可以使用另一个成员函数Write。
L表示字符串“Hello World”是一个宽字符串,每个字符占用两个字节。
(2)开始运行工程。单击菜单“调试”|“开始执行(不调试)”,或直接按Ctrl+F5键来运行工程,运行结果如图2-15所示。

图2-15
2.4.5 第一个托管C++表单程序
上面是一个用托管C++编写的控制台程序,下面我们来看一个用托管C++编写的图形界面程序,即Windows Forms(表单)程序。表单(Form)类似于MFC编程中的对话框,可以把工具箱中的控件拖放到表单上,然后为控件添加所需事件处理函数即可。托管C++表单编程已经是快速的可视化图形界面开发方式,开发的速度丝毫不逊色于可视化开发工具,如Visual C#、Visual Basic.NET。
【例2.6】 第一个托管C++表单程序
(1)打开Visual C++ 2013,选择菜单“新建”|“项目”,或直接按快捷键Ctrl+Shift+N,弹出“新建项目”对话框,在该对话框上,在左边展开“模板”|“Visual C++”|“CLR”,然后在右边选择“CLR空项目”,如图2-16所示。

图2-16
并在下方输入项目名称和路径,最后单击“确定”按钮。此时会生成一个空的CLR应用程序。这里要提示一下,在Visual C++ 2010中,CLR的工程模板里还是有CLR表单工程的,就是不需要添加任何代码会自动生成一个表单程序,现在到Visual C++ 2013居然只有CLR空项目了,这样表单资源和程序入口点(main函数)就要自己手动添加。由此可见,微软似乎对用C++开发.NET程序不加重视了。笔者认为,如果要开发.NET程序,还是用C#比较好,至少微软也是这么推荐的。
(2)现在项目是空的,我们要为它添加窗体,打开解决方案资源管理器,然后对“解决方案Test”下方的Test进行右击,在右键菜单上选择“添加”|“新建项”,然后出现“添加新项”对话框,在该对话框的左边选择UI,右边选择“Windows窗体”,名称可以保持默认,如图2-17所示。

图2-17
最后单击“添加”按钮。此时在解决方案资源管理器中会生成MyForm.h和MyForm.cpp,以及一个名字为MyForm的表单出现了在Visual C++设计界面中,同时左边会自动出现工具箱,在工具箱中我们展开“公共空间”,然后对“Button”单击,并不要释放,一直把它拖动到表单上再释放鼠标左键,这个过程叫拖拉控件到表单上。Button就是按钮,最常见的Windows界面元素,当我们单击按钮时,它会产生反应,当然这必须要为它添加单击按钮事件的处理函数。我们对表单上button1双击,来添加事件处理函数,代码如下:
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { MessageBox::Show(this, "Hello World"); //显示一个消息框 }
代码很简单,调用MessageBox的方法Show来显示一个消息框。
此时编译工程会提示程序没有入口点,要注意我们建立的是空项目,还没写main函数呢。
(3)打开MyForm.cpp,加入代码:
using namespace Test; //使用Test命名空间 int main(array<System::String ^> ^args) { Application::Run(gcnew MyForm()); //运行表单程序 return 0; }
其中,gcnew相当于传统C++中的new,意思是为表单分配内存空间。
(4)开始运行工程。单击菜单“调试”|“开始执行(不调试)”,或直接按Ctrl+F5键来运行工程,运行结果如图2-18所示。

图2-18