admin 管理员组

文章数量: 887039


2023年12月19日发(作者:php学习内容)

《Visual C++ 2010 入门教程》

写在前面

在我还在上学的时候,我选择了C++,最初我用VC6 作为我的

IDE,我看过很多本C++的教材,有的适合我,有的不适合我,其中有一本叫

《Visual C++ 2005 入门经典》的书帮了我不少的忙。因为通常的C++教材都只

会介绍C++的语法什么的,很少会告诉我们如何去编译、运行,告诉我们什么是

控制台程序,什么事Win 程序,什么是GUI 程序,C++能干什么,VC 和C++的区

别是什么。现在有很多的朋友应该也有这些问题吧?

学C++用C++也有几年了,算不上熟悉,算是初窥门径吧,我想我

应该做点什么帮助一下那些和曾经的我一样困惑的朋友,特别是学生朋友,告诉

他们他们所Щ蟮奈侍獾拇鸢浮<堑梦已++的时候,没有人教,有的时候也走

了不少弯路,甚至连调试也不会,也不知道可以通过看调用堆栈看调用次序,还

自己慢慢的去搜索,好傻啊。

接下来我会做一个《Visual C++ 2010 入门教程》系列,用来帮

助初学者。刚开始学的时候是很痛苦的,这个我深有体会,特别是身边还没有人

能够指导一二的。内容主要涵盖在Windows 下面使用C++进行开发的常见内容,

Visual Studio 2010 的使用,如何创建新项目,如何调试,如果配置项目属性

等等,另外还会介绍Visual C++ 2010 中新加如的一些内容,包括一些新的STL

组建,一些新的语法支持等等。

由于本人水平有限,其中难免有错误,希望大家谅解,如果大家

有发现问题还请务必及时指出来,否则误导了他人我就罪不容恕了。

注意,本教程非C++教程,不会教你

C++,只会教你如何使用 Visual C++ 2010 去练习去

学习其它C++教材上面的程序。因此建议大家认真的

去看其他的C++教程,在使用Visual C++ 2010 实践

的时候如果遇到问题可以到这里来参考。推荐《C++

Primer》、《C++程序设计语言》《Visual C++ 2008

入门经典》。

第一章: 关于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 的一个Patch 版本,解

决了一些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 中文旗舰版的启动画面。下一章中,我

将教大家安装、配置VS2010/VC2010,以及如何使用它来创建第一个C++程序。

如果你没有下载过Visual Studio 2010 的话,那么请你提前下载好

它吧:

/_%E2d_%B7%B3_%DE%B2%C2%D2/blog/item/bb0975dd80129

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

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

它来写HelloWord 程序。

安装

Visual C++ 2010 是属于Visual Studio 2010 的一部分,这个在前一章中已经讲解过,

实际上Visual C++ 2010 也有更多的子版本,正如Windows7 有旗舰版、家庭高级版、家庭

初级版一样。在上一章的下载地址中有两个版本可以选择,我选择的时候旗舰版,这个功能

最全面。

如果你下载完毕了,应该有一个ISO 镜像文件,如果你是从我给的地址下载的,那么

那个序列号已经被 替换成正版序列号,直接安装即可。下面是ISO 文件截图:

这就是光盘镜像文件,我们有多种方式可以安装它,你可以把它烧录成光盘,也可以

用虚拟光驱软件安装它,由于这个ISO 已经被修改过了,你甚至可以直接解压它,然后运

行里面的 进行安装。

这里我使用虚拟光驱进行说明,首先我假设你已经安装好了虚拟光驱软

件DAEMON

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》听到的是

无尽的伤感和无奈,而我的朋友却怎么也听不出来,呵,你去听听之后会有什么感觉?

好,回归正题吧。

什么是编程

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

编程就是让计算机为解决某个问题而使用某种程序设计语言编写

程序代码,并最终得到结果的过程。为了使计算机能够理解人的意图,

人类就必须要将需解决的问题的思路、方法、和手段通过计算机能够理

解的形式告诉计算机,使得计算机能够根据人的指令一步一步去工作,

完成某种特定的任务。这种人和计算机之间交流的过程就是编程。

这段话说的比较明白,我们如果想让计算机按照我们想要的方式工作,那么我们必须

给它命令,有的常见的任务已经由操作系统帮助我们提供了,操作系统将一些简

单的指令封

装成一个简单的操作,使得我们的操作更容易更简单,然而操作系统提供的操作始终是有限

的,如果要扩展计算机的软件系统,就需要编程了。

什么是编程语言

如上所说,编程语言就是人类与计算机交流的桥梁。首先编程语言必须是计算机可以

理解的或者是可以间接转换成计算机可以斫獾闹噶畹亩鳌4蚋霰确剑绻阍谝惶ㄆ胀?电脑面前站着,大叫道:“电脑,给哥把C盘根目录下面的A 文件拷贝到D盘根目录下面去”。

我猜想你就算叫上一天也没用,因为普通的电脑无法识别你的指令,这就算是对“机”弹琴吧。

什么是编译器

如上所说,编程语言是计算机可以直接理解的如机器码或者可以间接转换成计算机可

以理解的指令的东西。那么 C++就属于后者,那么是什么把 C++翻译成计算机可以识别的

指令的呢?这就是编译器。

什么是C++

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

计算机可以识别的指令。比如我们常见的C++代码:

int a = 3 + 1;

cout

下面的代码为什么在VC2010 下面编译不过去?

#include

int main()

{

cout头文件来代替,你甚至可以认为是这样定义的:

namespace std

{

#include "iostream.h"

}

因此我们可以简单的修改我们的Hello World。

#include

using namespace std;

int main()

{

cout 等。记住,在VC2010 上面采用C++风格的头文件而不是C

风格的头文件,除非你是在用C。

warning C4996

这是一个警告,请看下面的代码:

#include

using namespace std;

int main()

{

char sz[128] = {0};

strcpy( sz, "Hello World!" );

cout

#include

using namespace std;

int main()

{

MessageBox( NULL, "你好HelloWorld!", "Information", 0 );

return 0;

}

貌似没什么问题吧?错了,如果你是按照我教你的方法创建的控制台空工程的话,那

么会有编译错误:

error C2664: “MessageBoxW”: 不能将参数 2 从“const

char [17]”转换为

“LPCWSTR”

这个问题太普遍了,几乎所有的初学者都会遇到而且感到难以应付,因为按照提示使

用(LPCWSTR)强制转型貌似并不能帮助我们解决问题,而且这个程序在VC6 下面应该是没

有任何问题的,那问题出现在哪里呢?问题在这里,请右键单击解决方案浏览器下面的项目,

属性,

问题的根本就是字符集问题,在VC6 中,我们默认使用的是多字节字符集,而现在我

们默认需要的是UNICODE 字符集,简单的,我们把这个字符集改成多字节字符集这个问

题就解决了:

再试试应该就可以了吧?但是我并不推荐大家这么做,因为让自己的程序适应各种

字符集是我们写代码的人义不容辞的义务。

我们把程序改成下面这样:

#include

#include

#include

using namespace std;

int main()

{

MessageBox( NULL, TEXT("你好HelloWorld!"), TEXT("Information"), 0 );

MessageBox( NULL, _T("你好HelloWorld!"), _T("Information"), 0 );

return 0;

}

用两个宏TEXT 或者_T 都可以解决这个问题,它们两个并没有太大区别,也许区别在

于前者是通过windows.h 头文件引入的,而_T 是通过tchar.h 引入的,我推荐大家使用_T

和tchar.h,因为tchar.h 还帮助我们引入了其它一些很有用的宏,比如_tcscpy_s,这个宏

在使用UNICODE 字符集的时候被替换成wcscpy_s,在使用多字节字符集的使用被替换成

strcpy_s。关于这部分的内容,请大家不要错过《Windows 核心编程》的第二章(第四版或

第五版都可以),以及《深入学习C++ String2.1 版》。 它们都有提到。

有人听说_T 可以把多字节字符串转换成UNICODE,因此他写了如下的代码:

const char* pStr = "haha 哈哈";

MessageBox( NULL, _T(pStr), _T("Information"), 0 );

当然,除非你运气好的抓狂,否则你是编译不过去的,为什么呢?我们现在应该知道对

于"Hello"这样的字符串,VC2010 会默认的将它视为const char*,即多字节字符串,而

L"Hello"前面有个L 前缀的被视为UNICODE 字符串,这和C#是有区别的,因为C#的字符

串总是被视为UNICODE,C++/CLI 下面编译器也会帮助我们做到这件事情,所以它们不需

要L(C++/CLI 兼容L 这种写法)。

让我们看看_T 的定义吧:

#define wxCONCAT_HELPER(text, line) text ## line

/* could already be defined by tchar.h (it's quasi standard) */

#ifndef _T

#if !wxUSE_UNICODE

#define _T(x) x

#else /* Unicode */

/* use wxCONCAT_HELPER so that x could be expanded if it's a macro */

#define _T(x) wxCONCAT_HELPER(L, x)

#endif /* ASCII/Unicode */

#endif /* !defined(_T) */

_T 在UNICODE 下面最终会被替换成L ## x。 ##是一个编译预处理指令,意味着让L

和x 贴在一起,比如L ## "Hello"最终就是L"Hello",因此它可以把"Hello"转换成UNICODE

字符串。那为什么上面的程序不行呢?让我们看看_T("pStr")会被替换成什么:L ##

pStr ->

LpStr,哦,LpStr 是一个新的标识符,如果你没有定义过它,你当然不能通过编译啦。

因此我们可以了解到_T 这样的宏只能处理直接的常量字符串,不能处理其它的情况。

而我们上面演示的那种情况需要我们动态的去转换编码,Windows 有API 可以帮助我们做

到,C 库也有函数可以帮助我们。恰好我曾经写过这样的代码,欢迎大家参考:

ASCII/UNICODE/UTF8 字符串互相转换的C++代码

对于_T 宏,再说一点东西,或许你会感到奇怪为什么_T 不直接定义成#define _T(x) L ##

x,而要绕个圈子去调用wxCONCAT_HELPER 呢?这实际上涉及到宏展开顺序和截断的问

题。在这里,我们需要说一个宏参数的概念,这很函数的参数是类似的,这里_T(x)的x 就

是宏参数,好,记住下面一句话:

如果你定义的宏中使用了#或者是##的话,宏参数将不会被展开,也就是说_T(x)如果直

接定义成L##x 那么在下面这种情况就会出错( PS: #是给参数加引号的意思):

_T(__FUNCTION__),__FUNCTION__是一个预定义的宏,它代表了当前函数的名字,

这个展开会是什么呢?L__FUNCTION__。为什么间接调用wxCONCAT_HELPER

就能得

到正确的结果呢?因为当我们调用wxCONCAT_HELPER 的时候,__FUNCTION__已经被

_T 展开成了函数名。

说多了说多了,如果你觉得复杂可以暂时跳过这些东西,我只是顺便说说。

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

让我们在项目里面再添加一个Test.h 头文件,方法是右击解决方案中的项目,添加,新

建项,C++头文件,名称输入test.h。然后我们在test.h 中输入:

/*#pragma once*/

void print()

{

}

回到 中:

#include

using namespace std;

#include "Test.h"

#include "Test.h"

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 "Test.h"即可。

让我们再编译一次。

1> : error LNK2005: "void __cdecl print(void)" (?print@@YAXXZ) 已经在

中定义

1>e:documentsvisual studio : fatal

error LNK1169: 找到一个或多个多重定义的符号

如果说编译错误好找的话,链接错误对于初学者来说就有点麻烦了,聪明的初学者会

去Google、百度寻找答案,笨的初学者就会找所谓的高手、前辈问,而这些高手Or 前辈

未必有心情为你解释。要解决这个错误有无数种方法。

1.内联,把print 声明为内联函数。

inline void print()

{

}

这个方法的好处是简单,坏处是局限性太强,意味着你总是需要公开print 的实现,

因为内联函数必须在编译时就知道实现才行。

,把print 声明为static 函数:

static void print()。


本文标签: 编译 选择 项目 使用