C++ & MFC
C++是一种静态数据类型检查的、支持多重编程范式的程序设计语言,支持过程化程序设计、数据抽象、面向对象程序设计、制作图标等泛型程序设计的多种程序设计风格。
MFC(Microsoft Foundation Classes),是一个微软公司提供的类库,以C++类的形式封装了Windows的API,并且包含一个应用程序框架,以减少应用程序开发人员的工作量,同VCL类似,是一种应用程序框架。其中包含的类包含大量Windows句柄封装类和很多Windows的内建控件和组件的封装类。此外MFC的部分类为MFC/ATL 通用,可以在Win32 应用程序中单独包含并使用这些类。
由于它的易用性,初学者常误认为VC++开发必须使用MFC,这种想法是错误的。作为Application Framework,MFC的使用只能提高某些情况下的开发效率,只起到辅助作用,而不能替代整个Win32 程序设计。
从C到C++
计算机诞生初期,人们要使用计算机必须用机器语言或汇编语言编写程序。
世界上第一种计算机高级语言诞生于1954年,它是FORTRAN语言。
BASIC语言是1964年在FORTRAN语言的基础上简化而成的。
C语言是1972年由美国贝尔实验室的D.M.Ritchie研制成功的。
C++是由AT&T Bell(贝尔)实验室的Bjarne Stroustrup博士及其同事于20世纪80年代初在C语言的基础上开发成功的,C++保留了C语言原有的所有优点,增加了面向对象的机制。
面向对象程序设计,是针对开发较大规模的程序而提出来的,目的是提高软件开发的效率。不要把面向对象和面向过程对立起来,面向对象和面向过程不是矛盾的,而是各有用途、互为补充的。学习C++,既要会利用C++进行面向过程的结构化程序设计,也要会利用C++进行面向对象的程序设计。
如果要用C++创建窗口,我们需要使用到系统API或者使用封装了这些API的一些库,前者如Win32程序设计,后者如MFC、wxWidgets。
其实我认为学习C++的初期当然是熟悉C++的语法,中期是学习STL等库、系统API以及熟悉C++的面向对象的思想和一般的设计方法;后期是伴随着你C++生涯的一生的,因为它没有终点的,这时候除了要继续加深对C++的理解之外,还需要去学习各种各样的基于C++的库,因为你需要在这些库的帮助下使用C++去实现更具体的东西,比如一些GUI库如MFC、QT、wxWidgets,一些游戏引擎如Ogre、Unreal、Bigworld等,一些网络库如ASIO、RakNet、ACE等。这些库大多有一个特点就是它们都是基于C++,封装了底层的API使得我们可以不必每次都去使用繁杂的API来实现我们想要的功能。当然,你也可以用C++去封装这些API,让自己成为一个库作者,方便他人。
C++发展历史
C++语言发展大概可以分为三个阶段:
第一阶段
从80年代到1995年。这一阶段C++语言基本上是传统类型上的面向对象语言,并且凭借着接近C语言的效率,在工业界使用的开发语言中占据了相当大份额;
第二阶段
从1995年到2000年,这一阶段由于标准模板库(STL)和后来的Boost等程序库的出现,泛型程序设计在C++中占据了越来越多的比重性。当然,同时由于Java、C#等语言的出现和硬件价格的大规模下降,C++受到了一定的冲击;
第三阶段
从2000年至今,由于以Loki、MPL等程序库为代表的产生式编程和模板元编程的出现,C++出现了发展历史上又一个新的高峰,这些新技术的出现以及和原有技术的融合,使C++已经成为当今主流程序设计语言中最复杂的一员。
编程技巧
使用new和delete进行动态内存分配和释放
使用inline内联函数替代宏调用
对于频繁使用的函数,C语言建议使用宏调用代替函数调用以加快代码执行,减少调用开销。但是宏调用有许多的弊端,可能引起不期望的副作用。例如宏:#define abs(a)(a)<0?(-a):(a)),当使用abs(i++)时,这个宏就会出错。
所以在C++中应该使用inline内联函数替代宏调用,这样既可达到宏调用的目的,又避免了宏调用的弊端。
使用内联函数只须把inline关键字放在函数返回类型的前面。
使用函数重载
用引用(reference)代替指针进行参数传递
使用缺省参数
所有的缺省参数必须出现在不缺省参数的右边。
使用STL
STL(Standard Template Library,标准模板库), STL的代码从广义上讲分为三类:algorithm(算法)、container(容器)和iterator(迭代器),并包括一些工具类如auto_ptr。几乎所有的代码都采用了模板类和模板函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。
作用符被重载,使得我们可以像访问数组一样访问vector中的元素。[12]
使用模板
多泛型设计
根据Effective C++第三版第一条款的描述,现在C++由以下四个“子语言”组成:
1、C子语言。C++支持C语言的几乎全部功能,主要是c89的部分,在语法上与C语言仅有极微妙的差别(如括号表达式的左右值性,具体请参考C++标准文献)。
2、面向对象的C++语言。C++语言原本不具备面向对象的设计功能,然而随着面向对象编程的概念的提出以及如Java等语言的发展成熟,C++语言也开发出了支持面向对象功能的版本。
3、泛型编程语言。C++强大(但容易失控的)模板功能使它能在编译期完成许多工作,从而大大提高运行期效率。
4、STL(C++标准模板库,Standard Template Library)。随着STL的不断发展,它已经逐渐成为C++程序设计中不可或缺的部分,其效率可能比一般的native代码低些,但是其安全性与规范性使它大受欢迎。
此外,包含在TR1等中的C++0x将实现的新功能在开发和测试中。
MFC特点
编程语言函数本质上全部源于API,因此用它们开发出来的应用程序都能工作在Windows的消息机制和绘图里,遵守Windows作为一个操作系统的内部实现。
最后要明白MFC不只是一个功能单纯的界面开发系统,它提供的类绝大部分用来进行界面开发,关联一个窗口的动作,但它提供的类中有好多类不与一个窗口关联,即类的作用不是一个界面类,不实现对一个窗口对象的控制(如创建、销毁),而是一些在Windows(用MFC编写的程序绝大部分都在Windows中运行)中实现内部处理的类,如数据库的管理类等。学习中最应花费时间的是消息和设备环境,对C++和MFC。
MFC编程优势
C++语言应用极为广泛。尤其在底层编程和系统级编程上更是C++的传统优势应用。在数据库和多媒体方面,C++又以其卓越的稳定性而赢得了荣誉。
面对底层程序,它能很轻松的与Windows API或驱动程序结合,就是在自己的代码中直接使用API函数,而API和驱动程序的资料都是以C语言为基础的,这使得VC程序员能够更轻松的使用Windows API。这样造成了一个很有意思的现象,即入门时VC程序员要付出更多的努力来学习,但是一旦掌握后,开发其他领域的程序或使用第三方软件时,如工业控制类的程序,由于底层的程序都是用C语言编写,反倒是VC程序员能够更快的掌握该领域的编程技术。而很多其他的编程语言甚至找不到相关的资料。这就说明VC(MFC)实际上是一种入门困难,但是扩展学习却很轻松的语言框架。如果局限于某一领域的话VC毫无优势可言,但是如果开发一个新的领域的应用程序或者该程序涉及多个应用领域的话,可减少重复学习的频率和难度,VC(MFC)的优势会立刻显现出来。
MFC相关
MFC使用“Afx”作为所有的全局函数和全局变量的前缀。因为在MFC的早期开发阶段它叫“Application Framework Extensions”缩写为“AFX”。AFX提供了对Windows API的高度抽象,建立了全新的面向对象的AFX API,但它对于新手来说太复杂了,所以AFX小组不得不重新开始。后来他们创建了一组C++类,这就是MFC。MFC这个名字被采用得太晚了以至于没来得及修改这些引用。
在免费的Express版本的Visual Studio 2005/2008中没有包含MFC。
MFC作为一个强有力的竞争对手,为Borland的Turbo C++编译器设计OWL(Object Windows Library)在同一时间也发布了。但最后,Borland停止了对OWL的继续开发并且不久就从Microsoft那里购买了MFC头文件,动态链接库等的授权,微软没有提供完整的MFC的集成支持。之后Borland发布了VCL(Visual Component Library)来替换OWL框架。
MFC扩展DLL
每个DLL都有某种类型的接口:变量、指针、函数、客户程序访问的类。它们的作用是让客户程序使用DLL,MFC扩展DLL可以有C++的接口。导出的函数可以使用C++/MFC数据类型做参数或返回值,导出一个类时客户端能创建类对象或者派生这个类。同时,在DLL中也可以使用DLL和MFC。
Visual C++使用的MFC类库也是保存在一个DLL中,MFC扩展DLL动态连接到MFC代码库的DLL,客户程序也必须要动态连接到MFC代码库的DLL。(这里谈到的两个DLL,一个是我们自己编写的DLL,一个装MFC类库的DLL)现在MFC代码库的DLL也存在多个版本,客户程序和扩展DLL都必须使用相同版本的MFC代码DLL。所以为了让MFC扩展DLL能很好的工作,扩展DLL和客户程序都必须动态连接到MFC代码库DLL。而这个DLL必须在客户程序运行的计算机上。
MFC版本更新
Visual C++ 6.0 MFC 6.0 (mfc42.dll)
Visual C++ 2010 MFC 10.0 (mfc100.dll)
C++编程开发
开发方式
- 编译器:gcc,clang等
- 编辑器:一般是vim/emacs
- make:gnu make 或者bsd 的pmake等,功能与用法基本一样
- 版本管理:cvs,svn,git等
- 代码阅读:cscope,ctags,lxr等
集成开发环境(IDE)
- Visual Studio(Visual C++)
- Borland C++ Builder
- Eclipse(Myln + CDT + MinGW32 + GCC)
- Dev-C++(MinGW32 + GCC)
- Code::Blocks(可配合多款编译内核使用)
- CodeLite
- C-Free
- Qt Creator等基于Qt开发框架的IDE
常见的C++开发工具
1.Visual Studio
Visual Studio是微软公司推出的开发环境,它是目前最流行的Windows平台应用程序开发环境。在Visual Studio中可以创建应用程序和网络应用程序,以及智能设备应用程序和Office插件等。从7.0开始,Visual Studio加入了.Net技术,类似Java的JVM。如果不想使用.Net技术,6.0版本也是一个不错的选择。
说明:Visual Studio对标准C++做了扩展,习惯上将在Visual Studio中实现的C++称为Visual C++,即VC。VC是目前使用最广泛的C++开发语言,Visual Studio也是使用最广泛的开发工具。
2.C++ Builder
Borland公司于1998年推出,也是Windows下的开发工具。C++ Builder具有高度安全性、高可靠性、快速性的编译优化方法,所以编译出的软件执行速度很快。所有符合ANSI/ISO标准的原代码都可以在C++ Builder中编译,而且支持最新的ANSI C++/C语言特征。
3.Dev-C++
Dev-C++是Windows平台下的开源C++编程环境。它集成了GCC、MinGW32等众多自由软件,界面类似Visual Studio,但体积要小的多。它的缺点是难以胜任规模较大的软件项目,但对于初学者是一个不错的选择。
4.Anjuta
Anjuta是一款GNOME桌面环境下的C/C++编程的集成环境,也是开源软件。它不仅有项目管理、交互式调试以及强大的代码编辑和语法增色的功能,还可以直接开发Glade图形界面的程序。但是,它主要用在Linux、UNIX平台下,不支持Windows平台。目前,最新版本是2.4.x,可以从anjuta.sourceforge.net站点获得。
5.Code::Blocks
Code::Blocks是一款全功能的、跨平台的C/C++集成开发环境,属于开源软件。它提供了众多的工程模板,包括控制台应用、动态连接库、OpenGL应用、QT应用、Win32 GUI应用等。Code::Blocks的另一引人之处在于它具有丰富的插件,包括代码格式化、类向导、代码补全、代码统计、To-Do列表,以及WindowsXP外观等各种各样的插件。此外,它不仅支持GNU GCC编译器,还支持MS Visual C++、Borland C++编译器5.5,以及Digital Mars C等多种编译器。
6.Eclipse
Eclipse是目前开源平台中最著名的集成开发环境。最初主要用来支持Java语言编程,目前通过插件CDT也可以用来开发C/C++程序。因为它本身只是一个框架,因此插件众多是它的一大特点。这使得Eclipse拥有其他支持单一语言的IDE环境很难具有的灵活性。
此外,还有很多IDE也都支持C++开发,例如Visual Slick Edit、NetBeans、Understand C等,读者可以根据自己的需要选择适合自己的开发环境。
Visual C++ 6.0开发环境简介
Visual C++ IDE一般由3部分组成:Developer Studio、MFC、Platform SDK。用Visual C++编写代码也并不意味着一定要用MFC,使用STL、ATL、编写SDK程序一样没有限制。Platform SDK是以Microsoft C/C++编译器为核心,配合MASM,辅以其他一些工具和文档资料。
表1-1 文件类型
文 件 类 型 |
说 明 |
文 件 类 型 |
说 明 |
Active Server Page |
ASP文件 |
Binary File |
二进制文件 |
Bitmap File |
位图文件 |
C++ Source File |
C++源程序文件 |
C/C++ Header File |
C/C++头文件 |
Cursor File |
光标文件 |
HTML Page |
HTML文件 |
Icon File |
图标文件 |
Macro File |
宏文件 |
Resource Script |
资源脚本文件 |
Resource Template |
资源模板 |
SQL Script File |
SQL语言脚本文件 |
Text File |
文本文件 |
|
|
由于功能强大,Visual C++ 6.0预定义的工程类型也非常多,如表1-2所示。
表1-2 工程类型
项 目 类 型 |
说 明 |
项 目 类 型 |
说 明 |
ATL COM AppWizard |
ATL程序 |
Database Project |
数据库 |
Win32 Dynamic-Link Library |
Win32动态链接库 |
DevStudio Add-in Wizard |
自动嵌入执行文件宏 |
Custom AppWizard |
自定义程序向导 |
ISAPI Extension Wizard |
Internet服务器或过滤器 |
Makefile |
Make文件 |
MFC ActiveX Control Wizard |
Active X控件 |
MFC AppWizard(dll) |
MFC动态链接库 |
MFC AppWizard(exe) |
MFC可执行文件 |
Win32 Application |
Win32程序 |
Win32 Console Application |
Win32控制台程序 |
Win32 Static Library |
Win32静态库 |
Utility Project |
该工程作为其他子工程的容器,从而减少子工程的联编时间 |
经典著作
《The C++ Standard Library: A Tutorial and Reference》(《C++标准程序库:自修教程与参考手册》)
《Standard C++ IOStreams and Locales: Advanced Programmer's Guide and Reference》(《标准C++输入输出流与本地化》)
《Effective STL》
《Generic Programming and the STL: Using and Extending the C++ Standard Template Library》(《泛型编程与STL》)
《C++ Network Programming》(《C++网络编程》)
《Thinking in C++》(《C++编程思想》)
《Ruminations on C++: A Decade of Programming Insight and Experience》(《C++沉思录》)
《Inside The C++ Object Model》(《深度探索C++对象模型》)
《Design Patterns:Elements of Reusable Object-Oriented software》(《设计模式:可复用面向对象软件的基础》)
《Large-Scale C++ Software Design》(《大规模C++程序设计》)
《STL 源码剖析》
《The C++ Standard : Incorporating Technical Corrigendum No. 1》
《C++ Primer中文版(第4版)》
《C++ Primer plus(第五版) 》
附录:
随着C++98标准的确定,iostream.h已经被取消,至少在VC2010下面是这样的,取而代之的是我们要用<iostream>头文件来代替,iostream.h是属于C++的头文件,而非C的,因此标准订立的时候被改成了<iostream>。而C的头文件stdio.h等依然可以继续使用,这是为了兼容C代码。但是它们依然有对应的C++版本,如<cstdio> <cstdlib>等。记住,在VC2010上面采用C++风格的头文件而不是C风格的头文件,除非你是在用C。
VC从2005版本开始,微软引入了一系列的安全加强的函数来增强CRT(C运行时),这里对应的是strcpy_s。_s意为safe的意思,同样的道理,strcat也是同样。因此要解决这个问题,我们可以用strcpy_s来替换strcpy,但是注意strcpy_s并非所有编译器都提供,因此如果要跨编译器,请采用错误信息中所提示的方式,定义_CRT_SECURE_NO_WARNINGS宏来掩耳盗铃吧。另外注意并非所有的加强函数都是在屁股后面加_s,比如stricmp这个字符串比较函数的增强版名字是_stricmp。
高洪臣 (Gavin Gao)
cggos@outlook.com
=======================================================================