VS2010学习教程

文章描述:-2022年3月28日发(作者:尹耜) 第一章: 关于Visual Studio、VC和C++的那些事 首先,这三个东西有什么区别呢?VC和C++是相同的吗,有什么区别呢?我刚开始学C++的时候也有这样的问题,在这里我来替大家解释一下他们到底是什么。 Visual Studio,我们一般都简称为VS,VC全称是Visual C++,C++就不用解释了吧?

-

VS2010学习教程2022年3月28日发(作者:尹耜)




第一章: 关于Visual Studio、VC和C++的那些事

首先,这三个东西有什么区别呢?VC和C++是相同的吗,有什么区别呢?我刚开始学C++的时
候也有这样的问题,在这里我来替大家解释一下他们到底是什么。
Visual Studio,我们一般都简称为VS,VC全称是Visual C++,C++就不用解释了吧?Visual
Studio其实是微软开发的一套工具集,它由各种各样的工具组成,这就好像Office 2007是由Word
2007、Excel 2007、Access 2007等等组成的一个道理。其中Visual C++就是Visual Studio的一
个重要的组成部分。Visual Studio可以用于生成Web应用程序,也可以生成桌面应用程序,在
Visual Studio下面,除了VC,还有Visual C#,Visual Basic,过去还有Visual J#,现在还有
Visual F#等等组件工具,使用这些工具你可以使用C++语言、C#语言或者Basic语言(微软改进版)
进行开发。这就好比桌上放着刀、叉、筷子,你可以用它们来吃饭,无论你用什么工具都可以,因
为它们都是餐具的一种。
VC,全称是Visual C++,它只是一个工具而已。
C++是一门和C、Basic、C#、Java一个概念的东西,它是一门语言,这个概念就同汉语、英语、
法语之间的关系一样。语言的可以不同,他们有的复杂有的精简,比如汉语,我个人认为这是这个
星球上最复杂的语言;又比如电影《阿凡达》中外星人使用的语言,不过100都个单词而已。当然,
语言并没有高低贵贱之分,而对语言掌握的好不好,说的好不好是有高下之别的。
一个语言都有哪些要素呢?语法就是其中一个重要的方面,比如你要对你所喜欢的人表达爱
慕之情,那么你应该说“我爱你”,你不能说“你爱我”,因为这搞错了主谓宾关系,因此我们通
常都需要按照一定的规矩和原则表达才会让别人正确理解我们真正的含义。在我们的汉语中有一些
成语,它们通常都比较简单短小,但是却能表达非常强烈的感情,而且效果非常好。比如你想骂一
个坏人“你实在是太变态了,这种事情都干得出来。”你可以这样说:“你也太禽兽不如了!”对
于编程的语言来说,其实也是有成语的,在我看来,这就是库函数。通常我们在编程的时候都推荐
选择库函数,因为它通常会比较快一些。
一直以来都有不少人混淆Visual C++和Visual Studio,其实最初Visual C++发布的时候还没
有Visual Studio这个东西,Visual C++是一个独立的开发工具,与Visual Basic等并列,最后
微软将它们整合在一起组成了Visual Studio。
Visual C++从发布起到现在已经有10个大版本了,我们这里介绍的Visual C++ 2010就是
Visual C++ 10,简称VC10。上朔10多年,Visual C++ 6.0发布了,这个被称为史上最经典的VC,
现在有很多企业还在用它,大量的教材基于这个版本的VC来写的。然而实际上VC6并没有想象中
的那么美好,孱弱的IDE,不完善的STL等等让它越来越不适应时代的发展,同时由于后来的版本
和它的差别越来越大,让很多习惯于VC6教材的人在新版本上无所适从。VC6走向历史的终结点其
实是必然的,只在于时间问题罢了,况且大部分人都有追求最新的“嗜好”,所以这里也选择最新
版的VC来做入门教程。


下面来介绍下这个VC版本和VS版本的对应关系:
Visual Studio .net (2002) --> Visual C++ .net (2002) --> Visual C++ 7.0 -> _MSC_VER
值1300
这个是微软推出.net战略之后的最早的一个版本的VC,这个版本相对VC6来说变化并不是
很大,一些不标准的语法依然得到支持,不过IDE界面已经出现了VS时代的雏形。
Visual Stuido .net 2003 -> Visual C++ .net 2003 -> Visual C++ 7.1 -> _MSC_VER值1310
这个版本我觉得只能算是一个对.net 2002的一个Patc本,解决了一些Bug,不规范的
语法依然得到支持,比如for循环变量作用域的问题。
Visual Studio 2005 -> Visual C++ 2005 -> Visual C++ 8.0 -> _MSC_VER 1400
这个版本算是一个比较符合C++标准的VC版本了,微软为这个版本的VC加入了大量的增强
版的C库函数(CRT函数),如strcpy_s之类,当然,这部分并不是C和C++标准所要求的。
Visual Studio 2008 -> Visual C++ 2008 -> Visual C++ 9.0 -> _MSC_VER 1500
这个版本应该是在Vista发布之后出的,如果你是在Vista或者Win7下面使用,那么应该选
择这个版本。这个版本与VC2005变化并不大,不过它的SP1为C++带来一些新的STL库组件(tr1
部分),以及MFC下面的Ribbon界面。
Visual Studio 2010 -> Visual C++ 2010 -> Visual C++ 10.0 -> _MSC_VER值1600.
这个就是我们即将要介绍的版本,那么让我们来看一下它的启动画面吧。



这个是Visual Studio 2010中文旗舰版的启动画面。下一章中,我将教大家安装、配置
VS2010VC2010,以及如何使用它来创建第一个C++程序。
如果你没有下载过Visual Studio 2010的话,那么请你提前下载好它吧:
http:_%E2d_%B7%B3_%DE%B2%C2%D2blogitem
《Visual C++ 2010入门教程》


第二章 安装、配置和首次使用VS2010

本章将帮助大家安装Visual C++ 2010,帮助大家做一些常见的配置,以及第一次使用
它来写HelloWord程序。

安装

Visual C++ 2010是属于Visual Studio 2010的一部分,这个在前一章中已经讲解过,
实际上Visual C++ 2010也有更多的子版本,正如Windows7有旗舰版、家庭高级版、家庭
初级版一样。在上一章的下载地址中有两个版本可以选择,我选择的时候旗舰版,这个功能
最全面。
如果你下载完毕了,应该有一个ISO镜像文件,如果你是从我给的地址下载的,那么
那个序列号已经被 替换成正版序列号,直接安装即可。下面是ISO文件截图:



这就是光盘镜像文件,我们有多种方式可以安装它,你可以把它烧录成光盘,也可以
用虚拟光驱软件安装它,由于这个ISO已经被修改过了,你甚至可以直接解压它,然后运
行里面的进行安装。
这里我使用虚拟光驱进行说明,首先我假设你已经安装好了虚拟光驱软件DAEMO
Tools Lite,如果你还没有安装,请去游侠补丁网下载,因为在那里你总是能到最新的免
费版本。
接下来我们通过虚拟光驱加载刚才下载好的ISO镜像:



在弹出的对话框中选择我们下载好的ISO文件。这个时候,虚拟光驱里面已经替我们
打开了ISO文件,有的机器可能会自动弹出安装提示,有的不会。如果自动弹出安装提示,
那么直接通过即可,如果没有弹出,那么用资源管理器方式进入虚拟光驱点击
即可开始安装。

由于我已经安装好了VS2010,所以接下来无法给大家截图了,我就直接用文字描述吧。
当弹出VS2010安装程序之后点下一步,然后我们可能会看到 完全 最小 自定义 这
样的选项,我推荐大家选择自定义,因为只有这样我们才可以自定我们安装的目录。接下来
会选择安装的组件。这个时候我们会看到大量的VS2010的组件,这里我们可以选择是否


安装Basic是否安装C#等等,我在网上到一些图片,虽然跟中文版2010不一样,大家
大概的样子是一样的,大家就凑合着看看吧。
下面是开始的界面,我们应该选择安装VS2010.




上面这个时候选择同意。然后安装包会开始搜集信息:



选择目录:



然后就是开始安装了,注意安装的时候可能需要重启一两次。



最后安装成功:




配置

当安装成功之后,我们就可以开始使用了,这里我先教大家做一些常见的配置,当然
大家也可以直接用默认的设置,我这样配置主要是为了方便。
下面通过开始菜单来启动VS2010吧:



如果你是第一次开始,那么可能会让你选择默认的环境设置,我们要使用VC当然选
择VC的配置:




出现下面的画面表示已经成功安装和运行了。这是起始页面,以后你会经常见到它。




注意,你可能会没有VAssistX这个菜单,因为这个是个外部工具,以后会给大家解释它的
用处,现在暂时忽略。接下来让我们来做一些常见的设置。通过菜单工具》选项调出配置对
话框,下面是一些常见的设置:
调处行号,选择文本编辑器,所有语言,把行号打成勾。


如果你想调整字体或者颜,那么可以在这里选择:



单击工具栏的空白区域,让我们把生成工具栏调出来:



这样我们就可以直接在工具栏上面选择编译项目、编译整个解决方案、运行程序和调
试程序了。选择生成工具栏旁边的小三角形可以自定,我们还可以添加一些按钮:



单击自定义界面下面的添加按钮就可以添加新的按钮了,现在我们把开始执行(不调试)
添加工具栏中:



以前经常有人问我为什么我的程序闪一下就没了,这就是因为它们把调试(F5,那
个实心的三角形)当成了运行(不调试,Ctrl+F5,空心带尾巴的三角形)了。当然是一闪
而过啦。关于调试以后说到。


HelloWorld.

下面让我们用VC++ 2010也就是VC10来做一个控制台的HelloWorld程序吧。
VC2010里面不能单独编译一个.cpp或者一个.c文件,这些文件必须依赖于某一个项
目,因此我们必须创建一个项目。有很多种方法都可以创建项目,可以通过菜单:文件,新
建,项目;也可以通过工具栏点击新建项目进行创建。这里我们点击起始页面上面的新建项
目:




点击之后进入新建项目向导:


上面选择Win32控制台应用程序,名称中输入HelloWorld点确定,至于是否为解决方案创
建目录我们暂时不管,那主要区别在于解决方案是否和项目文件在同一目录。




接下来进入创建页面,在Win32应用程序向导的第一个页面直接点下一步即可:



下个页面记得选择空项目,我们不需要预编译头:



点击完成。
这时候一个空的项目编译成功了,我们不妨编译一些试试。点击刚才添加的生成工具
栏的生成按钮:


这时候我们会遇到编译错误,为什么呢?因为我们还没有Main函数,对于一个C++
项目来说,一定要有一个且仅有一个main函数(Windows程序需要WinMain,区别以后再
讲),可以是隐式提供也可以是显式提供,至于区别以后会讲到。现在让我们记住这个错误,
以后遇到这个错误的时候一定要想想,我们项目中是否有Main函数。注意这时候即使你托
一个有Main函数的文件到VC10中进行编译也是没有意义的,因为那个文件并不是我们项
目的一部分。

现在我们可以添加一个代码文件进来了,这个代码文件可以是已经存在的也可以是新
建的,这里新建一个。右键单击项目名称,选择添加,新建项:




在向导中选择代码、C++文件(.cpp),名称输入Main,确定。

这时候已经成功添加了一个Main文件,注意添加新文件的时候要防止重名:


然后我们输入最简单的几行代码,然后编译它吧,编译方法和上面一样。





如果编译成功你会看到上面的画面,如果失败会有错误提示,那么你可以根据提示
去修改项目配置或者代码。然后让我们用Ctrl+F5或者点那个空心三角形运行一下吧:


OK了,接下来你可以通过更改这个程序去练习C++教材上面的程序了。
这一章的内容就是这么多了,下一章中我们将讨论以下内容:什么是C++?什么是编程
等等。

第三章
关于C++的一些问题
这一回我自己都不知道应该写点什么好,或许今天的篇幅会比往常短很多。我说过,
这不是C++的教程,因为我还没有那个能力来教大家C++,我能做的,是分享一些学习的
经验,以及教新手如何使用VC2010这个工具去练习和实践其它C++教材上面的程序,如
《C++Primer》等。


今天说的是我学习和使用C++这些年来对C++的一些理解,这样的日志其实是最难写
的,因为众口难调,为什么这么说呢?同样的一段音乐不同的人去倾听都会有不同的感受,
不同的心境去听也会有不同的感觉。记得当年我在听雅尼的《If I could tell you》听到的是
无尽的伤感和无奈,而我的朋友却怎么也听不出来,呵,你去听听之后会有什么感觉?
好,回归正题吧。

什么是编程

下面这段话我是从百度百科“编程”词条复制过来的,不敢掠人之美:

编程就是让计算机为解决某个问题而使用某种程序设计语言编写
程序代码,并最终得到结果的过程。为了使计算机能够理解人的意图,
人类就必须要将需解决的问题的思路、方法、和手段通过计算机能够理
解的形式告诉计算机,使得计算机能够根据人的指令一步一步去工作,
完成某种特定的任务。这种人和计算机之间交流的过程就是编程。

这段话说的比较明白,我们如果想让计算机按照我们想要的方式工作,那么我们必须
给它命令,有的常见的任务已经由操作系统帮助我们提供了,操作系统将一些简单的指令封
装成一个简单的操作,使得我们的操作更容易更简单,然而操作系统提供的操作始终是有限
的,如果要扩展计算机的软件系统,就需要编程了。

什么是编程语言

如上所说,编程语言就是人类与计算机交流的桥梁。首先编程语言必须是计算机可以
理解的或者是可以间接转换成计算机可以理解的指令的东西。打个比方,如果你在一台普通
电脑面前站着,大叫道:“电脑,给哥把C盘根目录下面的A文件拷贝到D盘根目录下面去”。
我猜想你就算叫上一天也没用,因为普通的电脑无法识别你的指令,这就算是对“机”弹琴吧。

什么是编译器

如上所说,编程语言是计算机可以直接理解的如机器码或者可以间接转换成计算机可
以理解的指令的东西。那么C++就属于后者,那么是什么把C++翻译成计算机可以识别的
指令的呢?这就是编译器。

什么是C++

我不想说C++的历史了,我想说,它是一门编程语言,它可以通过编译器的翻译成为


计算机可以识别的指令。比如我们常见的C++代码:
int a = 3 + 1;
cout<< a << endl;
这翻译成机器码或者计算机可以理解的指令大概可以是这样的:
现在请为我准备一个变量a,请用3+1的和去初始化它,然后请加它的值输出到控制
台上并追加上一个空格。
关于C++的更多东西,建议大家去看专门的C++教材或者、百度百科等相关
词条。

学C++学的是什么?

学C++学的是什么?可以说C++是很复杂的,因为要实现一些在其它语言中很简单的
任务,在C++中通常都需要更多的代码和时间,以创建一个窗口为例,其它语言由于有内
置的支持,甚至当我们创建一个HelloWorld程序时候就已经创建了一个窗口。而在纯粹的
C++环境中,这是做不到的,因为C++并没有提供GUI的内置支持,如果要用C++创建窗
口,我们需要使用到系统API或者使用封装了这些API的一些库,前者如Win32程序设计
后者如MFC、wxWidgets。
但是这些并不能代表C++不好,反而C++是很强大的,我们学习C++学得不仅仅是
C++的语法,因为仅仅懂得C++的一些语法又能怎么样呢?演示算法么?其实我认为学习
C++的初期当然是熟悉C++的语法,中期当然是学习STL等库、系统API以及熟悉C++的
面向对象的思想和一般的设计方法;后期是伴随着你C++生涯的一生的,因为它没有终点
的,这时候除了要继续加深对C++的理解之外,还需要去学习各种各样的基于C++的库,
因为你需要在这些库的帮助下使用C++去实现更具体的东西,比如一些GUI库如QT、
wxWidgets,一些游戏引擎如Ogre、Unreal、Bigworld等,一些网络库如ASIO、Raket、
ACE等。这些库大多有一个特点就是他们是基于C++,封装了底层的API使得我们可以不
必每次多去使用繁杂的API来实现我们想要的功能。当然,你也可以用C++去封装这些API,
让自己成为一个库作者,方便他人。
学习C++,学习C和C++的库,学习其它各领域的C++库,好好的使用这些库或者
自己写一些库,其它一些你能想到的与C++相关的事情。

怎样才能用C++来做事情

通常我认为如果只使用最基本的C++以及其内置库来做事情,那么能做的事情始终是
有局限的,因为C++的库毕竟是有限的,我们能用它来写一些核心代码,因为这部分代码
通常都不需要与具体的应用关联起来。使用C++以及C++继承的C库我们能做一些简单的
文件操作,因此还可以写一些与此相关的处理程序。其实不仅仅是C++,比如C#,加入你
在应用中不引入.net Framework下面提供的大量的其它的类(指除了最基本的如
e等之外的类),你又能用C#做什么呢?我们在做C#的时候通常要引入一


些新的类,引用一些新的命名空间,其实C++也是这样的,要做更具体的事情,就需要除
C++本身之外的更多东西才行。
因此,要用C++来做事情,除了C++的基本语法之外,还需要学习一些其它一些内容
如Windows API、MFC、DirectX 3D API等。

C++、C#、Java到底谁好?

对于这个问题,我想说的是:语言无贵贱,技术有高低。其实无论什么语言,它们在
这里都是编程语言,也许它们看起来不一样,它们用起来也不一样,它们的“翻译”编译器不
一样,但是它们的本质作用就是要用它们自己的方式将我们人类的解决问题的方法、思路和
流程告知给计算机。这也就是为什么C++、C#、Java可以相互交互的原因。
每个语言就像江湖上的各门派的武功一样,其实真的没有高下之分,只有个人的修为,
少林武功就一定强于武当么?《碧血剑》中袁承志不也用普普通通的五行拳击溃了荣彩么?
只是不同的武功在不同的条件下表现不同,他们各自占据了自己有利的地位罢了,以杨家
法为例,或许二人比武它不厉害,但是征战沙场估计是再适合不过了。
因此不要再纠结什么语言好,什么语言流行了,选择一个自己喜欢的方向,然后调查
好那个方向最常用最适合的语言,然后集中注意力坚持的去学习它,这就好了。

今天的内容就是这些,希望对大家有帮助。请大家务必好好学习C++教材,并使用
VC2010好好演练,最好能够举一反三自己创造问题自己解决!多看看百度知道CC++下面
的那些问题,每解决一个那样的问题,你自己也会进步。
第四章VC2010中初学者常见错误、警告和问题
这一章将帮助大家解释一些常见的错误、警告和问题,帮助大家去理解和解决一些常
见问题,并了解它的根本原因。

iostream.h与

下面的代码为什么在VC2010下面编译不过去?
#include
int main()
{
cout<<

return 0;
}


错误信息:fatal error C1083: 无法打开包括文件:“iostream.h”: o such file or
directory
造成这个错误的原因在于历史原因,在过去C++98标准尚未订立的时候,C++的标准
输入输出流确实是定义在这个文件里面的,这是C风格的定义方法,随着C++98标准的确
定,iostream.h已经被取消,至少在VC2010下面是这样的,取而代之的是我们要用
头文件来代替,你甚至可以认为是这样定义的:
namespace std
{
#include
}
因此我们可以简单的修改我们的Hello World。
#include
using namespace std;
int main()
{
cout<<

return 0;
}
iostream.h是属于C++的头文件,而非C的,因此标准订立的时候被改成了
而C的头文件stdio.h等依然可以继续使用,这是为了兼容C代码。但是它们依然有对应的
C++版本,如 等。记住,在VC2010上面采用C++风格的头文件而不是C
风格的头文件,除非你是在用C。

warning C4996

这是一个警告,请看下面的代码:
#include
using namespace std;
int main()
{
char sz[128] = {0};
strcpy( sz,
cout<< sz << endl;
return 0;
}


上面的strcpy会产生这个警告:
warning C4996: 'strcpy': This function or variable may be unsafe. Cider using
strcpy_s instead. To disable deprecation, use _CRT_SECURE_O_WARIGS. See
online help for details.
这是因为VC从2005版本开始,微软引入了一系列的安全加强的函数来增强CRT(C
运行时),这里对应的是strcpy_s。_s意为safe的意思,同样的道理,strcat也是同样。
因此要解决这个问题,我们可以用strcpy_s来替换strcpy,但是注意strcpy_s并非所有编
译器都提供,因此如果要跨编译器,请采用错误信息中所提示的方式,定义
_CRT_SECURE_O_WARIGS宏来掩耳盗铃吧。另外注意并非所有的加强函数都是在
屁股后面加_s,比如stricmp这个字符串比较函数的增强版名字是_stricmp。下面,用
strcpy_s来更改程序:
int main()
{
char sz[128] = {0};
strcpy_s( sz,
cout<< sz << endl;
char* pSz2 = new char[128];
strcpy_s( pSz2, 128,
cout<< pSz2 << endl;
delete pSz2;
return 0;
}
注意,strcpy_s有两个版本,一个可以帮助我们自动推断缓冲区的大小,而另外一个
不能帮助我们推断,因此在编译器不能推断缓冲区大小的时候,我们需要自己指定缓冲区的
大小,如上面的程序所演示的那样,关于增强版的函数请参考我写的《深入学习C++
String2.1版》。

TCHAR、wchar_t、char

请大家看下面这个程序:
#include
#include
#include
using namespace std;
int main()
{
MessageBox( ULL, 你好HelloWorld!


return 0;
}
貌似没什么问题吧?错了,如果你是按照我教你的方法创建的控制台空工程的话,那
么会有编译错误:
error C2664: “MessageBoxW”: 不能将参数 2 从“ct char [17]”转换为
“LPCWSTR”
这个问题太普遍了,几乎所有的初学者都会遇到而且感到难以应付,因为按照提示使
用(LPCWSTR)强制转型貌似并不能帮助我们解决问题,而且这个程序在VC6下面应该是没
有任何问题的,那问题出现在哪里呢?问题在这里,请右键单击解决方案浏览器下面的项目,
属性,


问题的根本就是字符集问题,在VC6中,我们默认使用的是多字节字符集,而现在我
们默认需要的是UICODE字符集,简单的,我们把这个字符集改成多字节字符集这个问
题就解决了:


再试试应该就可以了吧?但是我并不推荐大家这么做,因为让自己的程序适应各种
字符集是我们写代码的人义不容辞的义务。
我们把程序改成下面这样:
#include
#include
#include
using namespace std;
int main()
{
MessageBox( ULL, TEXT(你好HelloWorld!
MessageBox( ULL, _T(你好HelloWorld!
return 0;
}
用两个宏TEXT或者_T都可以解决这个问题,它们两个并没有太大区别,也许区别在
于前者是通过windows.h头文件引入的,而_T是通过tchar.h引入的,我推荐大家使用_T
和tchar.h,因为tchar.h还帮助我们引入了其它一些很有用的宏,比如_tcscpy_s,这个宏
在使用UICODE字符集的时候被替换成wcscpy_s,在使用多字节字符集的使用被替换成
strcpy_s。关于这部分的内容,请大家不要错过《Windows核心编程》的第二章(第四版或
第五版都可以),以及《深入学习C++ String2.1版》。 它们都有提到。
有人听说_T可以把多字节字符串转换成UICODE,因此他写了如下的代码:
ct char* pStr = 哈哈
MessageBox( ULL, _T(pStr), _T(
当然,除非你运气好的抓狂,否则你是编译不过去的,为什么呢?我们现在应该知道对
于这样的字符串,VC2010会默认的将它视为ct char*,即多字节字符串,而


L前面有个L前缀的被视为UICODE字符串,这和C#是有区别的,因为C#的字符
串总是被视为UICODE,C++CLI下面编译器也会帮助我们做到这件事情,所以它们不需
要L(C++CLI兼容L这种写法)。
让我们看看_T的定义吧:
#define wxCOCAT_HELPER(text, line) text ## line
* could already be defined by tchar.h (it's quasi standard) *
#ifndef _T
#if !wxUSE_UICODE
#define _T(x) x
#else * Unicode *
* use wxCOCAT_HELPER so that x could be expanded if it's a macro *
#define _T(x) wxCOCAT_HELPER(L, x)
#endif * ASCIIUnicode *
#endif * !defined(_T) *
_T在UICODE下面最终会被替换成L ## x。 ##是一个编译预处理指令,意味着让L
和x贴在一起,比如L ## 最终就是L,因此它可以把转换成UICODE
字符串。那为什么上面的程序不行呢?让我们看看_T(会被替换成什么:L ## pStr ->
LpStr,哦,LpStr是一个新的标识符,如果你没有定义过它,你当然不能通过编译啦。
因此我们可以了解到_T这样的宏只能处理直接的常量字符串,不能处理其它的情况。
而我们上面演示的那种情况需要我们动态的去转换编码,Windows有API可以帮助我们做
到,C库也有函数可以帮助我们。恰好我曾经写过这样的代码,欢迎大家参考:
ASCIIUICODEUTF8字符串互相转换的C++代码
对于_T宏,再说一点东西,或许你会感到奇怪为什么_T不直接定义成#define _T(x) L ##
x,而要绕个圈子去调用wxCOCAT_HELPER呢?这实际上涉及到宏展开顺序和截断的问
题。在这里,我们需要说一个宏参数的概念,这很函数的参数是类似的,这里_T(x)的x就
是宏参数,好,记住下面一句话:
如果你定义的宏中使用了#或者是##的话,宏参数将不会被展开,也就是说_T(x)如果直
接定义成L##x那么在下面这种情况就会出错( PS: #是给参数加引号的意思):
_T(__FUCTIO__),__FUCTIO__是一个预定义的宏,它代表了当前函数的名字,
这个展开会是什么呢?L__FUCTIO__。为什么间接调用wxCOCAT_HELPER就能得
到正确的结果呢?因为当我们调用wxCOCAT_HELPER的时候,__FUCTIO__已经被
_T展开成了函数名。
说多了说多了,如果你觉得复杂可以暂时跳过这些东西,我只是顺便说说。

重定义的编译错误和链接错误


让我们在项目里面再添加一个Test.h头文件,方法是右击解决方案中的项目,添加,新
建项,C++头文件,名称输入test.h。然后我们在test.h中输入:
*#pragma once*
void print()
{
}
回到中:
#include
using namespace std;
#include
#include
int main()
{
return 0;
}
编译一下我们会得到重定义的编译错误:
error C2084: 函数“void print(void)”已有主体
或许你会说,你引用(#include)了两次,我没你那么傻,我只引用一次不就好了么?是的。
你聪明,但是是小聪明哈,因为你不能保证每个人都不去引用它。
这个问题演示的是#pragma once的用处,让我们解开它的注释。编译成功!#pragma
once的作用就在于防止头文件被多次引用。你或许见过
#ifndef __TEST_H__
#define__TEST_H__
代码
#endif
这样的代码,它们的作用是一样的,如果你跟我一样懒,那么就用#pragma once,如果
你打算去没有这个指令的编译器上编译代码,那么还是用后面一种方式吧。
现在让我们来见识一个对初学者稍微复杂一点的链接错误,用创建的方法再
添加一个test.h头文件,输入#include 即可。



让我们再编译一次。
1> : error LK2005: 已经在
中定义
1>e:documentsvisual studio 2010ProjectsHelloWorldDebug : fatal
error LK1169: 到一个或多个多重定义的符号
如果说编译错误好的话,链接错误对于初学者来说就有点麻烦了,聪明的初学者会
去Google、百度寻答案,笨的初学者就会所谓的高手、前辈问,而这些高手Or前辈
未必有心情为你解释。要解决这个错误有无数种方法。
1.内联,把print声明为内联函数。
inline void print()
{
}
这个方法的好处是简单,坏处是局限性太强,意味着你总是需要公开print的实现,
因为内联函数必须在编译时就知道实现才行。
,把print声明为static函数:
static void print()。
这便告诉编译器,哥是唯一的,而且哥只能被本编译单元的代码调用,这和extern
是对应的。简单来说,想要哥帮你做事,请先include哥声明的头文件,也就是#include

3..h头文件中只放声明,实现放到.cpp中去。
现在test.h中只有void print();,而实现在中:


#include
void print()
{
int a = 1;
cout<< a++ << endl;
}
这个时候有意思的是我们在无需包含test.h头文件也可以引用print函数,
因为print并非static的函数:
void print();
int main()
{
print();
print();
return 0;
}
但是声明一下是必须的。
由于百度空间的帖子的篇幅是有限制的,因此今天只好就说这么几点了。新的内容请
大家等候下一章。
合理组织项目、使用外部工具让工作更...
这一章跟大家分享一些与c++项目管理、VAX、SV、VS快捷键等方面的东西。
有效的在项目中组织C++文件,分配各种文件的目录对以后的维护会有好处的,至少
不会出现不知道什么东西在什么地方,特别是大的项目,这里用TextSearcher来做例子。
使用SV来管理项目会让我们的工作更轻松,工作也会更简单容易。
掌握常用的快捷键和常用的VS功能让我们的工作更有效。

合理的组织文件体系

首先说在IDE中为我们的文件分类组织,如下图所示:



我把不同功能的代码和文件放在不同的Filter下面,如何添加这样的Filter呢?



这样就可以添加筛选器了,默认情况下VS为我们创建三个筛选器:头文件、源文件和
资源文件,实际上我们可以再增加很多。这样区分开的好处就是各个功能的代码被分开了,
在文件很多的情况下不会造成混乱。如TextSearcher,它的搜索算法、软件控制逻辑、自
定义控件、GUI模块、线程化操作都是分开的,这样我可以很容易到我想的文件,而且
还可以检视自己的模块划分是否合理等等。
接下来推荐大家在项目资源浏览器中为不同的文件划分目录。


比如上图将头文件和源文件、资源图标文件、本地化文件和配置文件分开组织,这样也是为
了防止混乱。值得注意的是当我们把文件用文件分开的时候,需要在项目属性设置里面包含
我们的子目录,否则我们无法在源文件中直接用#include指令包含我们的头文件。如下图所
示这样的情况,如果不添加,无法到头文件。

如下图所示,到项目属性中,C++,常规中把我们的子目录作为附加路径添加到“附
加包含目录”中。



使用SV或其它源代码管理工具管理我们的项目

如果你打算写一个比较大一点的项目,我推荐你使用源代码管理工具来管理你的C++
项目,你可以选择SV,也可以选择其它的,我推荐SV,因为简单容易上手。
当你在做一个很复杂的东西的时候,花了两三天的时间去做修改,不过后来发现这个
修改并不合适,想还原到三天以前,如果你没有用源代码管理工具管理自己的项目也没有自
己手动的备份,那恭喜你,你得开始人肉还原了,这是多么悲剧的一件事情啊,然而如果你
使用了SV管理的话,只需要在三天前开始修改前的最后一次稳定版本Commit一次,三
天之后如果要还原,只需要使用工具Revert就好了,而且不但可以回到三天前的版本,你
甚至可以回到以前每一次Commit的版本,( ⊙o⊙ )哇,这是多么好的工具啊!


要使用SV,首先需要SV客户端,SV服务器是可选的。我推荐大家使用
TortoiseSV这个SV客户端,因为它简单易用、免费,支持Windows32Bit、64Bit,你
可以去他们的下载,地址点我。有了这个工具当然还不够,为了让我们的SV跟
VS2010结合的更紧密,我们需要再下载一个SV For VS的插件,我强烈推荐你使用它,
因为它也非常简单易用,下载地址点我。最新版是支持VS2010的。当你装了这个插件的
时候,如果你的项目是在SV的管理之下,那么你的项目看起来会一些不同:

看到文件左边的勾了吗?灰的勾表示正常,而橙的勾表示已经更改了,而
PendingChanges则告诉我们哪些文件时新加的,哪些文件被改过了,如果要还原的话,只


需要选择该文件,右键点击,Revert就好了:

如果你已经安装好了AnkhSV插件但是又看不到的话,那么请检查下系统选项卡里面
是否选择了它作为默认的源代码管理工具:




回过头去继续说SV,当我们安装好TortoiseSV之后(安装后可能需要重启),我们在资
源管理器中点击右键的时候就能看到它的菜单了:

虽然TortoiseSV有中文语言包,但是我推荐大家使用英文的,就像古诗一定要用中文
来表达一样,没有比英语单词表达SV项目管理更恰当的词了。
SV CheckOut可以让你获取其它地方SV服务器上面的某个项目的源码,当然,前


提是你要有权限才行,现在让我们试试。随便个盘符如F盘,点右键,选择 SV
CheckOut,然后Url of Repository中输入svn:TextSearcher这个地址,
其它的不变,点击OK。如图所示:

如果不出意外你能看到:




如果你看到这个画面说明你已经CheckOut成功了,那么恭喜你,你已经取到了
TextSearcher的源码,当然要说一点的是,这个源码可能你取到之后编译不了,因为还有


另外一些依赖项如dbsoft、boost、wxWidgets并不在这个SV上面。
这样大家就可以去一些开源的网站上面Check你想要的东西了,哈哈。推荐大家去这
个网站自己感兴趣的代码CheckOut:http:
现在我们说如何管理自己的项目,大家可以像我一样去一些提供免费SV服务器服务
的网站上面注册一个账号建立项目就好了,比如说我使用的这个,这个毕
竟是国内的,另外上面的也可以。当你注册建立项目成功之后就可以通过
菜单Import把需要导入的东西导入到SV服务器了:

导入界面的地址栏输入我们的SV服务器地址即可,类似于:
svn:TextSearcher。导出的时候记得输入日志。除了可以导入SV服务
器之外,我们还可以使用文件协议在自己的电脑上管理我们的代码,如果你不需要在多台电
脑上面共同维护这个项目的话。
让我们随便个地方新建一个文件夹,如D:TestSVServer这个文件夹,然后对着这
个新建的文件夹点右键,选择SV>Create repository here,OK,你的本地SV服务器已
经建好了。如果创建成功,你会发现这个文件夹里面多了好多东西:



没关系,这是SV服务必须要的一些东西,现在让我们使用文件协议导入我们的项目
到该SV服务器中,到我们要导入的项目,跟导入网络上的SV服务器一样,右击项
目文件夹,SV>Import。在Import界面中这样填:

不出意外你会导入成功,那么现在我们需要去其它地方重新获取这些东西了,换个地方,
比如F盘根目录,选择SV CheckOut,然后地址输入刚才导入的地址:



注意如上图这样是不行的,因为我们没办法在F盘根目录下面创建一个
D:TestSVServer文件夹,把D:这个SV帮我们自己填充的路径删掉然后点确定。

现在我们已经CheckOut了刚才导入的项目了,Planet文件夹已经带上了一个绿的勾。
点击这个Planet目录,选择SV>Show Log,你会看到:




第一章: 关于Visual Studio、VC和C++的那些事

首先,这三个东西有什么区别呢?VC和C++是相同的吗,有什么区别呢?我刚开始学C++的时
候也有这样的问题,在这里我来替大家解释一下他们到底是什么。
Visual Studio,我们一般都简称为VS,VC全称是Visual C++,C++就不用解释了吧?Visual
Studio其实是微软开发的一套工具集,它由各种各样的工具组成,这就好像Office 2007是由Word
2007、Excel 2007、Access 2007等等组成的一个道理。其中Visual C++就是Visual Studio的一
个重要的组成部分。Visual Studio可以用于生成Web应用程序,也可以生成桌面应用程序,在
Visual Studio下面,除了VC,还有Visual C#,Visual Basic,过去还有Visual J#,现在还有
Visual F#等等组件工具,使用这些工具你可以使用C++语言、C#语言或者Basic语言(微软改进版)
进行开发。这就好比桌上放着刀、叉、筷子,你可以用它们来吃饭,无论你用什么工具都可以,因
为它们都是餐具的一种。
VC,全称是Visual C++,它只是一个工具而已。
C++是一门和C、Basic、C#、Java一个概念的东西,它是一门语言,这个概念就同汉语、英语、
法语之间的关系一样。语言的可以不同,他们有的复杂有的精简,比如汉语,我个人认为这是这个
星球上最复杂的语言;又比如电影《阿凡达》中外星人使用的语言,不过100都个单词而已。当然,
语言并没有高低贵贱之分,而对语言掌握的好不好,说的好不好是有高下之别的。
一个语言都有哪些要素呢?语法就是其中一个重要的方面,比如你要对你所喜欢的人表达爱
慕之情,那么你应该说“我爱你”,你不能说“你爱我”,因为这搞错了主谓宾关系,因此我们通
常都需要按照一定的规矩和原则表达才会让别人正确理解我们真正的含义。在我们的汉语中有一些
成语,它们通常都比较简单短小,但是却能表达非常强烈的感情,而且效果非常好。比如你想骂一
个坏人“你实在是太变态了,这种事情都干得出来。”你可以这样说:“你也太禽兽不如了!”对
于编程的语言来说,其实也是有成语的,在我看来,这就是库函数。通常我们在编程的时候都推荐
选择库函数,因为它通常会比较快一些。
一直以来都有不少人混淆Visual C++和Visual Studio,其实最初Visual C++发布的时候还没
有Visual Studio这个东西,Visual C++是一个独立的开发工具,与Visual Basic等并列,最后
微软将它们整合在一起组成了Visual Studio。
Visual C++从发布起到现在已经有10个大版本了,我们这里介绍的Visual C++ 2010就是
Visual C++ 10,简称VC10。上朔10多年,Visual C++ 6.0发布了,这个被称为史上最经典的VC,
现在有很多企业还在用它,大量的教材基于这个版本的VC来写的。然而实际上VC6并没有想象中
的那么美好,孱弱的IDE,不完善的STL等等让它越来越不适应时代的发展,同时由于后来的版本
和它的差别越来越大,让很多习惯于VC6教材的人在新版本上无所适从。VC6走向历史的终结点其
实是必然的,只在于时间问题罢了,况且大部分人都有追求最新的“嗜好”,所以这里也选择最新
版的VC来做入门教程。


下面来介绍下这个VC版本和VS版本的对应关系:
Visual Studio .net (2002) --> Visual C++ .net (2002) --> Visual C++ 7.0 -> _MSC_VER
值1300
这个是微软推出.net战略之后的最早的一个版本的VC,这个版本相对VC6来说变化并不是
很大,一些不标准的语法依然得到支持,不过IDE界面已经出现了VS时代的雏形。
Visual Stuido .net 2003 -> Visual C++ .net 2003 -> Visual C++ 7.1 -> _MSC_VER值1310
这个版本我觉得只能算是一个对.net 2002的一个Patc本,解决了一些Bug,不规范的
语法依然得到支持,比如for循环变量作用域的问题。
Visual Studio 2005 -> Visual C++ 2005 -> Visual C++ 8.0 -> _MSC_VER 1400
这个版本算是一个比较符合C++标准的VC版本了,微软为这个版本的VC加入了大量的增强
版的C库函数(CRT函数),如strcpy_s之类,当然,这部分并不是C和C++标准所要求的。
Visual Studio 2008 -> Visual C++ 2008 -> Visual C++ 9.0 -> _MSC_VER 1500
这个版本应该是在Vista发布之后出的,如果你是在Vista或者Win7下面使用,那么应该选
择这个版本。这个版本与VC2005变化并不大,不过它的SP1为C++带来一些新的STL库组件(tr1
部分),以及MFC下面的Ribbon界面。
Visual Studio 2010 -> Visual C++ 2010 -> Visual C++ 10.0 -> _MSC_VER值1600.
这个就是我们即将要介绍的版本,那么让我们来看一下它的启动画面吧。



这个是Visual Studio 2010中文旗舰版的启动画面。下一章中,我将教大家安装、配置
VS2010VC2010,以及如何使用它来创建第一个C++程序。
如果你没有下载过Visual Studio 2010的话,那么请你提前下载好它吧:
http:_%E2d_%B7%B3_%DE%B2%C2%D2blogitem
《Visual C++ 2010入门教程》


第二章 安装、配置和首次使用VS2010

本章将帮助大家安装Visual C++ 2010,帮助大家做一些常见的配置,以及第一次使用
它来写HelloWord程序。

安装

Visual C++ 2010是属于Visual Studio 2010的一部分,这个在前一章中已经讲解过,
实际上Visual C++ 2010也有更多的子版本,正如Windows7有旗舰版、家庭高级版、家庭
初级版一样。在上一章的下载地址中有两个版本可以选择,我选择的时候旗舰版,这个功能
最全面。
如果你下载完毕了,应该有一个ISO镜像文件,如果你是从我给的地址下载的,那么
那个序列号已经被 替换成正版序列号,直接安装即可。下面是ISO文件截图:



这就是光盘镜像文件,我们有多种方式可以安装它,你可以把它烧录成光盘,也可以
用虚拟光驱软件安装它,由于这个ISO已经被修改过了,你甚至可以直接解压它,然后运
行里面的进行安装。
这里我使用虚拟光驱进行说明,首先我假设你已经安装好了虚拟光驱软件DAEMO
Tools Lite,如果你还没有安装,请去游侠补丁网下载,因为在那里你总是能到最新的免
费版本。
接下来我们通过虚拟光驱加载刚才下载好的ISO镜像:



在弹出的对话框中选择我们下载好的ISO文件。这个时候,虚拟光驱里面已经替我们
打开了ISO文件,有的机器可能会自动弹出安装提示,有的不会。如果自动弹出安装提示,
那么直接通过即可,如果没有弹出,那么用资源管理器方式进入虚拟光驱点击
即可开始安装。

由于我已经安装好了VS2010,所以接下来无法给大家截图了,我就直接用文字描述吧。
当弹出VS2010安装程序之后点下一步,然后我们可能会看到 完全 最小 自定义 这
样的选项,我推荐大家选择自定义,因为只有这样我们才可以自定我们安装的目录。接下来
会选择安装的组件。这个时候我们会看到大量的VS2010的组件,这里我们可以选择是否


安装Basic是否安装C#等等,我在网上到一些图片,虽然跟中文版2010不一样,大家
大概的样子是一样的,大家就凑合着看看吧。
下面是开始的界面,我们应该选择安装VS2010.




上面这个时候选择同意。然后安装包会开始搜集信息:



选择目录:



然后就是开始安装了,注意安装的时候可能需要重启一两次。



最后安装成功:




配置

当安装成功之后,我们就可以开始使用了,这里我先教大家做一些常见的配置,当然
大家也可以直接用默认的设置,我这样配置主要是为了方便。
下面通过开始菜单来启动VS2010吧:



如果你是第一次开始,那么可能会让你选择默认的环境设置,我们要使用VC当然选
择VC的配置:




出现下面的画面表示已经成功安装和运行了。这是起始页面,以后你会经常见到它。




注意,你可能会没有VAssistX这个菜单,因为这个是个外部工具,以后会给大家解释它的
用处,现在暂时忽略。接下来让我们来做一些常见的设置。通过菜单工具》选项调出配置对
话框,下面是一些常见的设置:
调处行号,选择文本编辑器,所有语言,把行号打成勾。


如果你想调整字体或者颜,那么可以在这里选择:



单击工具栏的空白区域,让我们把生成工具栏调出来:



这样我们就可以直接在工具栏上面选择编译项目、编译整个解决方案、运行程序和调
试程序了。选择生成工具栏旁边的小三角形可以自定,我们还可以添加一些按钮:



单击自定义界面下面的添加按钮就可以添加新的按钮了,现在我们把开始执行(不调试)
添加工具栏中:



以前经常有人问我为什么我的程序闪一下就没了,这就是因为它们把调试(F5,那
个实心的三角形)当成了运行(不调试,Ctrl+F5,空心带尾巴的三角形)了。当然是一闪
而过啦。关于调试以后说到。


HelloWorld.

下面让我们用VC++ 2010也就是VC10来做一个控制台的HelloWorld程序吧。
VC2010里面不能单独编译一个.cpp或者一个.c文件,这些文件必须依赖于某一个项
目,因此我们必须创建一个项目。有很多种方法都可以创建项目,可以通过菜单:文件,新
建,项目;也可以通过工具栏点击新建项目进行创建。这里我们点击起始页面上面的新建项
目:




点击之后进入新建项目向导:


上面选择Win32控制台应用程序,名称中输入HelloWorld点确定,至于是否为解决方案创
建目录我们暂时不管,那主要区别在于解决方案是否和项目文件在同一目录。




接下来进入创建页面,在Win32应用程序向导的第一个页面直接点下一步即可:



下个页面记得选择空项目,我们不需要预编译头:



点击完成。
这时候一个空的项目编译成功了,我们不妨编译一些试试。点击刚才添加的生成工具
栏的生成按钮:


这时候我们会遇到编译错误,为什么呢?因为我们还没有Main函数,对于一个C++
项目来说,一定要有一个且仅有一个main函数(Windows程序需要WinMain,区别以后再
讲),可以是隐式提供也可以是显式提供,至于区别以后会讲到。现在让我们记住这个错误,
以后遇到这个错误的时候一定要想想,我们项目中是否有Main函数。注意这时候即使你托
一个有Main函数的文件到VC10中进行编译也是没有意义的,因为那个文件并不是我们项
目的一部分。

现在我们可以添加一个代码文件进来了,这个代码文件可以是已经存在的也可以是新
建的,这里新建一个。右键单击项目名称,选择添加,新建项:




在向导中选择代码、C++文件(.cpp),名称输入Main,确定。

这时候已经成功添加了一个Main文件,注意添加新文件的时候要防止重名:


然后我们输入最简单的几行代码,然后编译它吧,编译方法和上面一样。





如果编译成功你会看到上面的画面,如果失败会有错误提示,那么你可以根据提示
去修改项目配置或者代码。然后让我们用Ctrl+F5或者点那个空心三角形运行一下吧:


OK了,接下来你可以通过更改这个程序去练习C++教材上面的程序了。
这一章的内容就是这么多了,下一章中我们将讨论以下内容:什么是C++?什么是编程
等等。

第三章
关于C++的一些问题
这一回我自己都不知道应该写点什么好,或许今天的篇幅会比往常短很多。我说过,
这不是C++的教程,因为我还没有那个能力来教大家C++,我能做的,是分享一些学习的
经验,以及教新手如何使用VC2010这个工具去练习和实践其它C++教材上面的程序,如
《C++Primer》等。


今天说的是我学习和使用C++这些年来对C++的一些理解,这样的日志其实是最难写
的,因为众口难调,为什么这么说呢?同样的一段音乐不同的人去倾听都会有不同的感受,
不同的心境去听也会有不同的感觉。记得当年我在听雅尼的《If I could tell you》听到的是
无尽的伤感和无奈,而我的朋友却怎么也听不出来,呵,你去听听之后会有什么感觉?
好,回归正题吧。

什么是编程

下面这段话我是从百度百科“编程”词条复制过来的,不敢掠人之美:

编程就是让计算机为解决某个问题而使用某种程序设计语言编写
程序代码,并最终得到结果的过程。为了使计算机能够理解人的意图,
人类就必须要将需解决的问题的思路、方法、和手段通过计算机能够理
解的形式告诉计算机,使得计算机能够根据人的指令一步一步去工作,
完成某种特定的任务。这种人和计算机之间交流的过程就是编程。

这段话说的比较明白,我们如果想让计算机按照我们想要的方式工作,那么我们必须
给它命令,有的常见的任务已经由操作系统帮助我们提供了,操作系统将一些简单的指令封
装成一个简单的操作,使得我们的操作更容易更简单,然而操作系统提供的操作始终是有限
的,如果要扩展计算机的软件系统,就需要编程了。

什么是编程语言

如上所说,编程语言就是人类与计算机交流的桥梁。首先编程语言必须是计算机可以
理解的或者是可以间接转换成计算机可以理解的指令的东西。打个比方,如果你在一台普通
电脑面前站着,大叫道:“电脑,给哥把C盘根目录下面的A文件拷贝到D盘根目录下面去”。
我猜想你就算叫上一天也没用,因为普通的电脑无法识别你的指令,这就算是对“机”弹琴吧。

什么是编译器

如上所说,编程语言是计算机可以直接理解的如机器码或者可以间接转换成计算机可
以理解的指令的东西。那么C++就属于后者,那么是什么把C++翻译成计算机可以识别的
指令的呢?这就是编译器。

什么是C++

我不想说C++的历史了,我想说,它是一门编程语言,它可以通过编译器的翻译成为


计算机可以识别的指令。比如我们常见的C++代码:
int a = 3 + 1;
cout<< a << endl;
这翻译成机器码或者计算机可以理解的指令大概可以是这样的:
现在请为我准备一个变量a,请用3+1的和去初始化它,然后请加它的值输出到控制
台上并追加上一个空格。
关于C++的更多东西,建议大家去看专门的C++教材或者、百度百科等相关
词条。

学C++学的是什么?

学C++学的是什么?可以说C++是很复杂的,因为要实现一些在其它语言中很简单的
任务,在C++中通常都需要更多的代码和时间,以创建一个窗口为例,其它语言由于有内
置的支持,甚至当我们创建一个HelloWorld程序时候就已经创建了一个窗口。而在纯粹的
C++环境中,这是做不到的,因为C++并没有提供GUI的内置支持,如果要用C++创建窗
口,我们需要使用到系统API或者使用封装了这些API的一些库,前者如Win32程序设计
后者如MFC、wxWidgets。
但是这些并不能代表C++不好,反而C++是很强大的,我们学习C++学得不仅仅是
C++的语法,因为仅仅懂得C++的一些语法又能怎么样呢?演示算法么?其实我认为学习
C++的初期当然是熟悉C++的语法,中期当然是学习STL等库、系统API以及熟悉C++的
面向对象的思想和一般的设计方法;后期是伴随着你C++生涯的一生的,因为它没有终点
的,这时候除了要继续加深对C++的理解之外,还需要去学习各种各样的基于C++的库,
因为你需要在这些库的帮助下使用C++去实现更具体的东西,比如一些GUI库如QT、
wxWidgets,一些游戏引擎如Ogre、Unreal、Bigworld等,一些网络库如ASIO、Raket、
ACE等。这些库大多有一个特点就是他们是基于C++,封装了底层的API使得我们可以不
必每次多去使用繁杂的API来实现我们想要的功能。当然,你也可以用C++去封装这些API,
让自己成为一个库作者,方便他人。
学习C++,学习C和C++的库,学习其它各领域的C++库,好好的使用这些库或者
自己写一些库,其它一些你能想到的与C++相关的事情。

怎样才能用C++来做事情

通常我认为如果只使用最基本的C++以及其内置库来做事情,那么能做的事情始终是
有局限的,因为C++的库毕竟是有限的,我们能用它来写一些核心代码,因为这部分代码
通常都不需要与具体的应用关联起来。使用C++以及C++继承的C库我们能做一些简单的
文件操作,因此还可以写一些与此相关的处理程序。其实不仅仅是C++,比如C#,加入你
在应用中不引入.net Framework下面提供的大量的其它的类(指除了最基本的如
e等之外的类),你又能用C#做什么呢?我们在做C#的时候通常要引入一


些新的类,引用一些新的命名空间,其实C++也是这样的,要做更具体的事情,就需要除
C++本身之外的更多东西才行。
因此,要用C++来做事情,除了C++的基本语法之外,还需要学习一些其它一些内容
如Windows API、MFC、DirectX 3D API等。

C++、C#、Java到底谁好?

对于这个问题,我想说的是:语言无贵贱,技术有高低。其实无论什么语言,它们在
这里都是编程语言,也许它们看起来不一样,它们用起来也不一样,它们的“翻译”编译器不
一样,但是它们的本质作用就是要用它们自己的方式将我们人类的解决问题的方法、思路和
流程告知给计算机。这也就是为什么C++、C#、Java可以相互交互的原因。
每个语言就像江湖上的各门派的武功一样,其实真的没有高下之分,只有个人的修为,
少林武功就一定强于武当么?《碧血剑》中袁承志不也用普普通通的五行拳击溃了荣彩么?
只是不同的武功在不同的条件下表现不同,他们各自占据了自己有利的地位罢了,以杨家
法为例,或许二人比武它不厉害,但是征战沙场估计是再适合不过了。
因此不要再纠结什么语言好,什么语言流行了,选择一个自己喜欢的方向,然后调查
好那个方向最常用最适合的语言,然后集中注意力坚持的去学习它,这就好了。

今天的内容就是这些,希望对大家有帮助。请大家务必好好学习C++教材,并使用
VC2010好好演练,最好能够举一反三自己创造问题自己解决!多看看百度知道CC++下面
的那些问题,每解决一个那样的问题,你自己也会进步。
第四章VC2010中初学者常见错误、警告和问题
这一章将帮助大家解释一些常见的错误、警告和问题,帮助大家去理解和解决一些常
见问题,并了解它的根本原因。

iostream.h与

下面的代码为什么在VC2010下面编译不过去?
#include
int main()
{
cout<<

return 0;
}


错误信息:fatal error C1083: 无法打开包括文件:“iostream.h”: o such file or
directory
造成这个错误的原因在于历史原因,在过去C++98标准尚未订立的时候,C++的标准
输入输出流确实是定义在这个文件里面的,这是C风格的定义方法,随着C++98标准的确
定,iostream.h已经被取消,至少在VC2010下面是这样的,取而代之的是我们要用
头文件来代替,你甚至可以认为是这样定义的:
namespace std
{
#include
}
因此我们可以简单的修改我们的Hello World。
#include
using namespace std;
int main()
{
cout<<

return 0;
}
iostream.h是属于C++的头文件,而非C的,因此标准订立的时候被改成了
而C的头文件stdio.h等依然可以继续使用,这是为了兼容C代码。但是它们依然有对应的
C++版本,如 等。记住,在VC2010上面采用C++风格的头文件而不是C
风格的头文件,除非你是在用C。

warning C4996

这是一个警告,请看下面的代码:
#include
using namespace std;
int main()
{
char sz[128] = {0};
strcpy( sz,
cout<< sz << endl;
return 0;
}


上面的strcpy会产生这个警告:
warning C4996: 'strcpy': This function or variable may be unsafe. Cider using
strcpy_s instead. To disable deprecation, use _CRT_SECURE_O_WARIGS. See
online help for details.
这是因为VC从2005版本开始,微软引入了一系列的安全加强的函数来增强CRT(C
运行时),这里对应的是strcpy_s。_s意为safe的意思,同样的道理,strcat也是同样。
因此要解决这个问题,我们可以用strcpy_s来替换strcpy,但是注意strcpy_s并非所有编
译器都提供,因此如果要跨编译器,请采用错误信息中所提示的方式,定义
_CRT_SECURE_O_WARIGS宏来掩耳盗铃吧。另外注意并非所有的加强函数都是在
屁股后面加_s,比如stricmp这个字符串比较函数的增强版名字是_stricmp。下面,用
strcpy_s来更改程序:
int main()
{
char sz[128] = {0};
strcpy_s( sz,
cout<< sz << endl;
char* pSz2 = new char[128];
strcpy_s( pSz2, 128,
cout<< pSz2 << endl;
delete pSz2;
return 0;
}
注意,strcpy_s有两个版本,一个可以帮助我们自动推断缓冲区的大小,而另外一个
不能帮助我们推断,因此在编译器不能推断缓冲区大小的时候,我们需要自己指定缓冲区的
大小,如上面的程序所演示的那样,关于增强版的函数请参考我写的《深入学习C++
String2.1版》。

TCHAR、wchar_t、char

请大家看下面这个程序:
#include
#include
#include
using namespace std;
int main()
{
MessageBox( ULL, 你好HelloWorld!


return 0;
}
貌似没什么问题吧?错了,如果你是按照我教你的方法创建的控制台空工程的话,那
么会有编译错误:
error C2664: “MessageBoxW”: 不能将参数 2 从“ct char [17]”转换为
“LPCWSTR”
这个问题太普遍了,几乎所有的初学者都会遇到而且感到难以应付,因为按照提示使
用(LPCWSTR)强制转型貌似并不能帮助我们解决问题,而且这个程序在VC6下面应该是没
有任何问题的,那问题出现在哪里呢?问题在这里,请右键单击解决方案浏览器下面的项目,
属性,


问题的根本就是字符集问题,在VC6中,我们默认使用的是多字节字符集,而现在我
们默认需要的是UICODE字符集,简单的,我们把这个字符集改成多字节字符集这个问
题就解决了:


再试试应该就可以了吧?但是我并不推荐大家这么做,因为让自己的程序适应各种
字符集是我们写代码的人义不容辞的义务。
我们把程序改成下面这样:
#include
#include
#include
using namespace std;
int main()
{
MessageBox( ULL, TEXT(你好HelloWorld!
MessageBox( ULL, _T(你好HelloWorld!
return 0;
}
用两个宏TEXT或者_T都可以解决这个问题,它们两个并没有太大区别,也许区别在
于前者是通过windows.h头文件引入的,而_T是通过tchar.h引入的,我推荐大家使用_T
和tchar.h,因为tchar.h还帮助我们引入了其它一些很有用的宏,比如_tcscpy_s,这个宏
在使用UICODE字符集的时候被替换成wcscpy_s,在使用多字节字符集的使用被替换成
strcpy_s。关于这部分的内容,请大家不要错过《Windows核心编程》的第二章(第四版或
第五版都可以),以及《深入学习C++ String2.1版》。 它们都有提到。
有人听说_T可以把多字节字符串转换成UICODE,因此他写了如下的代码:
ct char* pStr = 哈哈
MessageBox( ULL, _T(pStr), _T(
当然,除非你运气好的抓狂,否则你是编译不过去的,为什么呢?我们现在应该知道对
于这样的字符串,VC2010会默认的将它视为ct char*,即多字节字符串,而


L前面有个L前缀的被视为UICODE字符串,这和C#是有区别的,因为C#的字符
串总是被视为UICODE,C++CLI下面编译器也会帮助我们做到这件事情,所以它们不需
要L(C++CLI兼容L这种写法)。
让我们看看_T的定义吧:
#define wxCOCAT_HELPER(text, line) text ## line
* could already be defined by tchar.h (it's quasi standard) *
#ifndef _T
#if !wxUSE_UICODE
#define _T(x) x
#else * Unicode *
* use wxCOCAT_HELPER so that x could be expanded if it's a macro *
#define _T(x) wxCOCAT_HELPER(L, x)
#endif * ASCIIUnicode *
#endif * !defined(_T) *
_T在UICODE下面最终会被替换成L ## x。 ##是一个编译预处理指令,意味着让L
和x贴在一起,比如L ## 最终就是L,因此它可以把转换成UICODE
字符串。那为什么上面的程序不行呢?让我们看看_T(会被替换成什么:L ## pStr ->
LpStr,哦,LpStr是一个新的标识符,如果你没有定义过它,你当然不能通过编译啦。
因此我们可以了解到_T这样的宏只能处理直接的常量字符串,不能处理其它的情况。
而我们上面演示的那种情况需要我们动态的去转换编码,Windows有API可以帮助我们做
到,C库也有函数可以帮助我们。恰好我曾经写过这样的代码,欢迎大家参考:
ASCIIUICODEUTF8字符串互相转换的C++代码
对于_T宏,再说一点东西,或许你会感到奇怪为什么_T不直接定义成#define _T(x) L ##
x,而要绕个圈子去调用wxCOCAT_HELPER呢?这实际上涉及到宏展开顺序和截断的问
题。在这里,我们需要说一个宏参数的概念,这很函数的参数是类似的,这里_T(x)的x就
是宏参数,好,记住下面一句话:
如果你定义的宏中使用了#或者是##的话,宏参数将不会被展开,也就是说_T(x)如果直
接定义成L##x那么在下面这种情况就会出错( PS: #是给参数加引号的意思):
_T(__FUCTIO__),__FUCTIO__是一个预定义的宏,它代表了当前函数的名字,
这个展开会是什么呢?L__FUCTIO__。为什么间接调用wxCOCAT_HELPER就能得
到正确的结果呢?因为当我们调用wxCOCAT_HELPER的时候,__FUCTIO__已经被
_T展开成了函数名。
说多了说多了,如果你觉得复杂可以暂时跳过这些东西,我只是顺便说说。

重定义的编译错误和链接错误


让我们在项目里面再添加一个Test.h头文件,方法是右击解决方案中的项目,添加,新
建项,C++头文件,名称输入test.h。然后我们在test.h中输入:
*#pragma once*
void print()
{
}
回到中:
#include
using namespace std;
#include
#include
int main()
{
return 0;
}
编译一下我们会得到重定义的编译错误:
error C2084: 函数“void print(void)”已有主体
或许你会说,你引用(#include)了两次,我没你那么傻,我只引用一次不就好了么?是的。
你聪明,但是是小聪明哈,因为你不能保证每个人都不去引用它。
这个问题演示的是#pragma once的用处,让我们解开它的注释。编译成功!#pragma
once的作用就在于防止头文件被多次引用。你或许见过
#ifndef __TEST_H__
#define__TEST_H__
代码
#endif
这样的代码,它们的作用是一样的,如果你跟我一样懒,那么就用#pragma once,如果
你打算去没有这个指令的编译器上编译代码,那么还是用后面一种方式吧。
现在让我们来见识一个对初学者稍微复杂一点的链接错误,用创建的方法再
添加一个test.h头文件,输入#include 即可。



让我们再编译一次。
1> : error LK2005: 已经在
中定义
1>e:documentsvisual studio 2010ProjectsHelloWorldDebug : fatal
error LK1169: 到一个或多个多重定义的符号
如果说编译错误好的话,链接错误对于初学者来说就有点麻烦了,聪明的初学者会
去Google、百度寻答案,笨的初学者就会所谓的高手、前辈问,而这些高手Or前辈
未必有心情为你解释。要解决这个错误有无数种方法。
1.内联,把print声明为内联函数。
inline void print()
{
}
这个方法的好处是简单,坏处是局限性太强,意味着你总是需要公开print的实现,
因为内联函数必须在编译时就知道实现才行。
,把print声明为static函数:
static void print()。
这便告诉编译器,哥是唯一的,而且哥只能被本编译单元的代码调用,这和extern
是对应的。简单来说,想要哥帮你做事,请先include哥声明的头文件,也就是#include

3..h头文件中只放声明,实现放到.cpp中去。
现在test.h中只有void print();,而实现在中:


#include
void print()
{
int a = 1;
cout<< a++ << endl;
}
这个时候有意思的是我们在无需包含test.h头文件也可以引用print函数,
因为print并非static的函数:
void print();
int main()
{
print();
print();
return 0;
}
但是声明一下是必须的。
由于百度空间的帖子的篇幅是有限制的,因此今天只好就说这么几点了。新的内容请
大家等候下一章。
合理组织项目、使用外部工具让工作更...
这一章跟大家分享一些与c++项目管理、VAX、SV、VS快捷键等方面的东西。
有效的在项目中组织C++文件,分配各种文件的目录对以后的维护会有好处的,至少
不会出现不知道什么东西在什么地方,特别是大的项目,这里用TextSearcher来做例子。
使用SV来管理项目会让我们的工作更轻松,工作也会更简单容易。
掌握常用的快捷键和常用的VS功能让我们的工作更有效。

合理的组织文件体系

首先说在IDE中为我们的文件分类组织,如下图所示:



我把不同功能的代码和文件放在不同的Filter下面,如何添加这样的Filter呢?



这样就可以添加筛选器了,默认情况下VS为我们创建三个筛选器:头文件、源文件和
资源文件,实际上我们可以再增加很多。这样区分开的好处就是各个功能的代码被分开了,
在文件很多的情况下不会造成混乱。如TextSearcher,它的搜索算法、软件控制逻辑、自
定义控件、GUI模块、线程化操作都是分开的,这样我可以很容易到我想的文件,而且
还可以检视自己的模块划分是否合理等等。
接下来推荐大家在项目资源浏览器中为不同的文件划分目录。


比如上图将头文件和源文件、资源图标文件、本地化文件和配置文件分开组织,这样也是为
了防止混乱。值得注意的是当我们把文件用文件分开的时候,需要在项目属性设置里面包含
我们的子目录,否则我们无法在源文件中直接用#include指令包含我们的头文件。如下图所
示这样的情况,如果不添加,无法到头文件。

如下图所示,到项目属性中,C++,常规中把我们的子目录作为附加路径添加到“附
加包含目录”中。



使用SV或其它源代码管理工具管理我们的项目

如果你打算写一个比较大一点的项目,我推荐你使用源代码管理工具来管理你的C++
项目,你可以选择SV,也可以选择其它的,我推荐SV,因为简单容易上手。
当你在做一个很复杂的东西的时候,花了两三天的时间去做修改,不过后来发现这个
修改并不合适,想还原到三天以前,如果你没有用源代码管理工具管理自己的项目也没有自
己手动的备份,那恭喜你,你得开始人肉还原了,这是多么悲剧的一件事情啊,然而如果你
使用了SV管理的话,只需要在三天前开始修改前的最后一次稳定版本Commit一次,三
天之后如果要还原,只需要使用工具Revert就好了,而且不但可以回到三天前的版本,你
甚至可以回到以前每一次Commit的版本,( ⊙o⊙ )哇,这是多么好的工具啊!


要使用SV,首先需要SV客户端,SV服务器是可选的。我推荐大家使用
TortoiseSV这个SV客户端,因为它简单易用、免费,支持Windows32Bit、64Bit,你
可以去他们的下载,地址点我。有了这个工具当然还不够,为了让我们的SV跟
VS2010结合的更紧密,我们需要再下载一个SV For VS的插件,我强烈推荐你使用它,
因为它也非常简单易用,下载地址点我。最新版是支持VS2010的。当你装了这个插件的
时候,如果你的项目是在SV的管理之下,那么你的项目看起来会一些不同:

看到文件左边的勾了吗?灰的勾表示正常,而橙的勾表示已经更改了,而
PendingChanges则告诉我们哪些文件时新加的,哪些文件被改过了,如果要还原的话,只


需要选择该文件,右键点击,Revert就好了:

如果你已经安装好了AnkhSV插件但是又看不到的话,那么请检查下系统选项卡里面
是否选择了它作为默认的源代码管理工具:




回过头去继续说SV,当我们安装好TortoiseSV之后(安装后可能需要重启),我们在资
源管理器中点击右键的时候就能看到它的菜单了:

虽然TortoiseSV有中文语言包,但是我推荐大家使用英文的,就像古诗一定要用中文
来表达一样,没有比英语单词表达SV项目管理更恰当的词了。
SV CheckOut可以让你获取其它地方SV服务器上面的某个项目的源码,当然,前


提是你要有权限才行,现在让我们试试。随便个盘符如F盘,点右键,选择 SV
CheckOut,然后Url of Repository中输入svn:TextSearcher这个地址,
其它的不变,点击OK。如图所示:

如果不出意外你能看到:




如果你看到这个画面说明你已经CheckOut成功了,那么恭喜你,你已经取到了
TextSearcher的源码,当然要说一点的是,这个源码可能你取到之后编译不了,因为还有


另外一些依赖项如dbsoft、boost、wxWidgets并不在这个SV上面。
这样大家就可以去一些开源的网站上面Check你想要的东西了,哈哈。推荐大家去这
个网站自己感兴趣的代码CheckOut:http:
现在我们说如何管理自己的项目,大家可以像我一样去一些提供免费SV服务器服务
的网站上面注册一个账号建立项目就好了,比如说我使用的这个,这个毕
竟是国内的,另外上面的也可以。当你注册建立项目成功之后就可以通过
菜单Import把需要导入的东西导入到SV服务器了:

导入界面的地址栏输入我们的SV服务器地址即可,类似于:
svn:TextSearcher。导出的时候记得输入日志。除了可以导入SV服务
器之外,我们还可以使用文件协议在自己的电脑上管理我们的代码,如果你不需要在多台电
脑上面共同维护这个项目的话。
让我们随便个地方新建一个文件夹,如D:TestSVServer这个文件夹,然后对着这
个新建的文件夹点右键,选择SV>Create repository here,OK,你的本地SV服务器已
经建好了。如果创建成功,你会发现这个文件夹里面多了好多东西:



没关系,这是SV服务必须要的一些东西,现在让我们使用文件协议导入我们的项目
到该SV服务器中,到我们要导入的项目,跟导入网络上的SV服务器一样,右击项
目文件夹,SV>Import。在Import界面中这样填:

不出意外你会导入成功,那么现在我们需要去其它地方重新获取这些东西了,换个地方,
比如F盘根目录,选择SV CheckOut,然后地址输入刚才导入的地址:



注意如上图这样是不行的,因为我们没办法在F盘根目录下面创建一个
D:TestSVServer文件夹,把D:这个SV帮我们自己填充的路径删掉然后点确定。

现在我们已经CheckOut了刚才导入的项目了,Planet文件夹已经带上了一个绿的勾。
点击这个Planet目录,选择SV>Show Log,你会看到:

-

VS2010学习教程

发布时间:2022-03-28 13:01:52
文章版权声明:除非注明,否则均为IT技术网-学习WEB前端开发等IT技术的网络平台原创文章,转载或复制请以超链接形式并注明出处。

发表评论

评论列表 (有 5 条评论,515人围观)

最近发表

随便看看

热门文章

标签列表