编程基础新手入门.docx
- 文档编号:9646166
- 上传时间:2023-02-05
- 格式:DOCX
- 页数:17
- 大小:129.45KB
编程基础新手入门.docx
《编程基础新手入门.docx》由会员分享,可在线阅读,更多相关《编程基础新手入门.docx(17页珍藏版)》请在冰豆网上搜索。
编程基础新手入门
Windows编程基础
基于Windows的编程方式有两种。
一种是使用Windows的API(ApplicationProgrammingInterface,应用程序编程接口)函数,通常用C/C++语言按相应的程序框架进行编程。
这些程序框架往往就程序应用提供相应的文档、范例和软件开发工具包(SoftwareDevelopmentKit,SDK),所以这种编程方式有时又称为SDK方式。
另一种是使用“封装”方式,例如VisualC++的MFC方式,它是将SDK中的绝大多数函数、数据等按C++“类”的形式进行封装,并提供相应的应用程序框架和编程操作。
事实上,无论是哪种编程方式,人们最关心的内容有三个:
一是程序入口,二是窗口、资源等的创建和使用,三是键盘、鼠标等所产生的事件或消息的接收和处理。
本章就来讨论这些内容。
从main到WinMain
学习编程往往从简单的例子入手,例如一个C程序常有下列简单的框架代码:
#include<>
intmain()
{
printf("HelloWorld!
\n");/*输出*/
return0;/*指定返回值*/
}
事实上,该程序已包括C程序中最常用的#include指令、必须的程序入口main函数、库函数printf调用和return语句。
由于此程序是在早期的DOS(DiskOperatingSystem,磁盘操作系统)环境的字符模型下运行的,因而printf函数所输出的都是字符流,也就是说,它在屏幕上输出一行文本“HelloWorld!
”。
在Windows环境下,这里的屏幕就由控制台窗口来兼作,而基于Windows的上述C程序代码框架肯定是有所不同的。
特别地,由于目前所在的Windows环境基本上都是32位,所以这里的Windows程序平台就是Win32,Windows编程可直接理解为是Win32编程。
1.1.1Windows等价程序
等价的Windows程序可以写成:
#include<>
intWINAPIWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,
PSTRszCmdLine,intnCmdShow)
{
MessageBox(NULL,TEXT("Hello,World!
"),TEXT("Hello"),0);
return0;
}
在深入剖析上述程序之前,先来看一看在VisualC++中的编辑、连接和运行的过程:
图“每日提示”对话框
①选择“开始”→“程序”→MicrosoftVisualStudio→MicrosoftVisualC++,运行VisualC++。
第一次运行时,将显示如图所示的“每日提示”对话框。
单击“下一条”按钮,可看到有关各种操作的提示。
如果在“启动时显示提示”复选框中单击鼠标,去除复选框的选中标记“
”,那么下一次运行VisualC++,将不再出现此对话框。
单击“关闭”按钮关闭此对话框,进入VisualC++开发环境。
②选择“文件”→“新建”菜单命令,打开应用程序向导,显示出“新建”对话框,如图所示。
选择“工程”选项卡,从列表框中选中Win32Application(Win32应用程序)项(图中的标记1)。
③单击“位置”编辑框右侧的“浏览”按钮
(图中的标记2),从弹出的“选择目录”对话框指定项目所在的文件夹,如图所示(图中的数字标记表示最经常的操作次序,下同)。
单击“确定”按钮,退出“选择目录”对话框,回到“新建”对话框中。
需要说明的是,为了便于程序的管理和查找,本书所涉及的程序均放入VisualC++的工作文件夹“VisualC++程序”中,第1章程序放入子文件夹“第1章”中,第2章程序放入子文件夹“第2章”,依此类推。
④在“新建”对话框的“工程名称”编辑框(图中的标记3)中,输入项目名称Ex_HelloMsg,保留“平台”下Win32复选框的默认“选中
”状态,单击“确定”按钮进入下一步。
⑤出现Win32Application向导的“步骤1共1步”对话框,从中可选择要创建的应用程序类型:
“一个空工程”、“一个简单的Win32程序”和“一个典型的"HelloWorld!
"程序”,如图所示。
它们的区别在于:
“一个空工程”仅创建Win32应用程序文件框架,不含任何代码;“一个简单的Win32程序”是在“一个空工程”基础上添加了程序框架(有入口函数、#include指令等);“一个典型的‘HelloWorld!
’程序”在“一个简单的Win32程序”基础上增加了MessageBox函数调用,用来输出“HelloWorld!
”。
图“新建”对话框“工程”选项卡图“选择目录”对话框
⑥选中“一个空工程”,单击“完成”按钮,弹出“新建工程信息”对话框,如图所示。
单击“确定”按钮,系统将按前面的选择自动创建此应用程序。
图应用程序的向导对话框图“新建工程信息”对话框
⑦再次选择“文件”→“新建”菜单命令,VisualC++将打开“新建”对话框并自动切换到“文件”选项卡,如图所示。
在左侧的文件类型列表中选中C++SourceFile(C++源文件),在右侧的“文件名”编辑框中输入“”或输入“”(文件扩展名也可不输入,系统会自动添加cpp扩展名,cpp是CPlusPlus的缩写,是C++的意思)。
⑧单击“确定”按钮,系统将在创建的Win32项目工程Ex_HelloMsg中创建并添加一个新的文件,同时打开该文件窗口。
现在可以在中输入前面例中的代码了。
输完后,单击编译工具条上的“生成工具”按钮
或直接按F7键,系统开始对Ex_HelloMsg项目工程中的文件进行编译、连接,同时在输出窗口中观察出现的内容,当出现
error(s),0warning(s)
表示可执行文件已经正确无误地生成了。
同时也可看到在文档窗口中所有代码的颜色都发生改变,这是VisualC++的文本编辑器所具有的语法颜色功能(绿色表示注释,蓝色表示关键字等)。
⑨单击编译工具条上的“运行工具”按钮
或直接按Ctrl+F5键,就可以运行刚刚生成的,结果如图所示。
单击“确定”按钮,Hello对话框退出。
图创建并添加程序文件图开发环境和运行结果
1.1.2头文件
是一个#include预处理指令开始,实际上在用C/C++编写的Windows应用程序的头部都可以看到这样的指令:
#include<>
头文件是最主要的包含头文件,它还包含了其他一些Windows头文件。
例如:
:
基本类型定义
:
内核函数
:
用户接口函数
:
图形设备接口函数
这些头文件定义了Windows的所有数据类型、函数调用、数据结构和符号常量,它们是Windows应用程序文档中的一个重要部分。
1.1.3程序入口函数
在C/C++程序中,其入口函数都是main。
但在Windows程序中,这个入口函数由WinMain来代替。
该函数是在中声明的,其原型如下:
int
WINAPI
WinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,LPSTRlpCmdLine,
intnShowCmd);
可以看出,这个WinMain函数除了形参名、个数与main函数不同外,类型名也有了新的变化。
下面就来分析:
WinMain函数被声明成为返回一个int值,同时WinMain函数名前还有WINAPI标识符的修饰。
WINAPI是一种“调用约定”宏,它在中有如下定义:
#defineWINAPI__stdcall
所谓“调用约定”,就是指程序生成机器码后,函数调用的多个参数是按怎样的次序来传递,同时函数调用结束后堆栈由谁来恢复,以及编译器对函数名的修饰约定等的协议。
函数调用约定“协议”有许多,其中由WINAPI宏指定的__stdcall是一个常见的协议,内容包括:
参数从右向左压入堆栈;函数自身修改堆栈;机器码中的函数名前面自动加下划线,而函数后面接@符号和参数的字节数。
特别地,VisualC++的MFC方式却采用了__cdecl调用约定:
参数从右向左压入堆栈;传递参数的内存栈由调用者来维护(正因为如此可实现变参函数);机器码中的函数名只在前面自动加下划线。
WinMain函数的第一个和第二个参数都是HINSTANCE(实例句柄)类型。
HINSTANCE中,H表示Handle,是“句柄”的意思。
在Windows编程中,句柄是一个应用程序用来识别某些资源、状态、模块等的数字。
由于句柄唯一标识着对应的资源、状态、模块等,因而使用句柄就是使(调)用相应的资源、状态、模块。
当应用程序运行多次时,每一次都是应用程序的“实例”。
由于同一个应用程序的所有实例都共享着应用程序的资源,因而程序通过检查hPrevInstance参数就可确定自身的其他实例是否正在运行。
WinMain函数的第三个参数lpCmdLine用来指定程序的命令行,其参数类型为LPSTR。
但在中,却将其改为PSTR。
这两种数据类型都是合法的,也都是指向字符串的指针类型。
其中的STR是“STRING,字符串”的含义,是指以\0结尾的字符串,LP前缀表示“长指针”,在Win32中它与“P”前缀表示的“指针”含义相同。
WinMain函数的第四个参数nShowCmd用来指定程序最初显示的方式,它可以是正常、最大化或最小化来显示程序窗口。
纵观上述参数和类型名可以发现它们的命名规则:
C/C++的类型名仍保留其小写,但新的类型都是用大写字母来命名。
参数名(变量名)都是采用“匈牙利表示法”的命名规则来定义的。
它的主要方法是将变量名前后加上表示“类型”和“作用”的“前缀(小写)”,而变量名本身由“状态”、“属性”和“含义”等几个部分组成,每一个部分的名称可以是全称,也可以是缩写,但通常只有第一个字母是大写。
例如,hPrevInstance则是由前缀h(表示“句柄”类型)+状态Prev(表示“以前的”)+属性Instance(表示“实例”)组成的。
1.1.4MessageBox函数
MessageBox是一个Win32API函数,用来弹出一个对话框窗口,显示短信息。
该函数具有下列原型:
intMessageBox(HWNDhWnd,LPCTSTRlpText,LPCTSTRlpCaption,UINTuType);
其中,第一个参数hWnd用来指定父窗口句柄,即对话框所在的窗口句柄。
第二、三个参数分别用来指定显示的消息内容(lpText)和对话框窗口的标题(lpCaption),最后一个参数用来指定在对话框中显示的预定义的按钮和图标标识,它们是在定义的一组以MB_开始的常数组合。
例如,下面是在中改变MessageBox的第四个参数。
#include<>
intWINAPIWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,
PSTRszCmdLine,intnCmdShow)
{
MessageBox(NULL,TEXT("Hello,World!
"),TEXT("Hello"),
MB_ICONQUESTION|MB_ABORTRETRYIGNORE);
return0;
}
图第四个参数的作用
程序运行后,结果如图所示。
可见,MB_ICONQUESTION用来指定在对话框中显示图标,而MB_ABORTRETRYIGNORE用来指定“终止”、“重试”和“忽略”按钮,类似这样的预定义标识还有很多,在以后讨论到MFC中的CWnd:
:
MessageBox函数时还要讨论,故这里不再赘述。
在程序中,调用MessageBox的实参中还涉及TEXT宏。
在Windows编程中,TEXT宏是用来对UNICODE编码的字符串的支持。
UNICODE是使用两个字节表示一个字符,这样单字节的ANSI字符和双字节的“汉字”的表示就统一起来了。
在程序中使用TEXT文本,无论在何Windows环境下均可显示正确的内容,而不会出现乱码的情形。
另外,还有_TEXT和_T宏等,在VisualC++中,它们的作用是等同的。
窗口和消息
MessageBox是通过创建的默认“窗口”来显示简单的信息:
窗口标题、一行或多行文本、图标和按钮等。
在Windows环境中,一个“窗口”就是屏幕上的一个矩形区域,它接收用户的输入,并以文本或图形方式来显示内容。
事实上,“窗口”就是用户操作的区域界面,在编程中除创建等操作外,还要处理用户输入、窗口本身事件所产生的“消息”。
1.2.1程序框架代码
为了能处理上述两个部分的内容:
窗口创建和消息处理,Windows提供了相应的程序框架,如下面的例子。
#include<>
LRESULTCALLBACKWndProc(HWND,UINT,WPARAM,LPARAM);
1.2.21.2.31.2.41.2.51.2.6
1.3C1.3.1文件中,而将类的实现保存在同名的.cpp文件中,这也是VisualC++的一种规范。
2.对象的定义和初始化
同变量一样,类声明后,就可以定义该类的对象。
类的对象也有好几种定义方式。
但由于“类”比任何数据类型都要复杂得多,为了提高程序的可读性,真正将“类”当成一个密闭、“封装”的盒子(接口),在程序中应尽量使用对象的声明之后定义方式,即按下列格式进行:
<类名><对象名表>;
其中,类名是已声明过的类的标识符,对象名可以有一个或多个,多个时要用逗号隔开。
被定义的对象既可以是一个普通对象,也可以是一个数组对象或指针对象。
例如:
CStuscoreone,*Stu,Stus[2];
这时,one是类CStuscore的一个普通对象,Stu和Stus分别是该类的一个指针对象和对象数组。
若对象是一个指针,则还可像指针变量那样进行初始化,例如:
CStuscore*two=&one;
可见,在程序中,对象的使用和变量是一样的,只是对象还有成员的访问等手段。
3.对象成员的访问
一个对象的成员就是该对象的类所定义的数据成员和成员函数。
访问对象的成员变量和成员函数与访问一般结构的变量的方法是一样的。
对于普通对象,其访问格式如下:
<对象名>.<成员变量>
<对象名>.<成员函数>(<参数表>)
例如,()用来调用对象one中的成员函数getName,Stus[0].getNo()用来调用对象数组元素Stus[0]中的成员函数getNo。
要注意,由于类的封装性,每个成员均有声明的访问属性,一个类对象只能访问该类的公有型成员,而对于私有型成员则不能访问,例如getName和getNo等公有成员可以由对象通过上述方式来访问,但strName、strStuNo、fScore等私有成员不能被对象来访问。
若对象是一个指针,则对象的成员访问格式如下:
<对象名>-><成员变量>
<对象名>-><成员函数>(<参数表>)
“->”是另一个表示成员的运算符,它与“.”运算符的区别是:
“->”用来表示指向对象的指针的成员,而“.”用来表示一般对象的成员。
需要说明的是,下面的两种表示是等价的(对于成员函数也适用):
<对象指针名>-><成员变量>
(*<对象指针名>).<成员变量>
例如,(*two).getName()与two->getName()等价。
可见,在C++中,类实际上是一种新的数据类型,它是对某一类对象的抽象。
如同变量一样,用“类”也可定义一个对象,此时的对象称为类的实例。
1.3.2构造函数和析构函数
事实上,一个类总有两种特殊的成员函数:
构造函数和析构函数。
构造函数的功能是在创建对象时,给数据成员赋初值,即给对象初始化。
析构函数的功能是用来释放一个对象,在对象删除前,用它来做一些内存释放等清理工作,它与构造函数的功能正好相反。
1.构造函数
C++规定,在类的定义中是不能对数据成员进行初始化的。
为了能给数据成员设置某些初值,这时就要使用类的特殊成员函数——构造函数。
构造函数的最大特点是在对象建立时它会被自动执行,因此用于变量、对象的初始化代码一般放在构造函数中。
C++规定,一个类的构造函数必须与相应的类同名,它可以带参数,也可以不带参数,与一般的成员函数定义相同,可以重载,也可以有默认的形参值。
例如:
#include<>
classCPerson
{
public:
CPerson(char*str,floath,floatw)//A:
构造函数
{
strcpy(name,str);height=h;weight=w;
}
CPerson(char*str)//B:
构造函数
{
strcpy(name,str);
}
CPerson(floath,floatw=120);//C:
构造函数
public:
voidprint()
{
cout<<"姓名:
"< "< "< } private: charname[20];//姓名 floatheight;//身高 floatweight;//体重 }; CPerson: : CPerson(floath,floatw) { height=h;weight=w; } intmain() { CPersonone("DING"); (); CPersontwo(170,130); (); CPersonthree("DING",170,130); (); return0; } #include后面的是C++编译器自带的文件,称为C++库文件,它定义了标准输入/输出流的相关数据及其操作。 cout表示标准输出流对象(屏幕),“<<”是插入符,它将后面的内容插入到cout中,即输出到屏幕上。 程序运行的结果为: 姓名: DING身高: –+008体重: –+008 姓名: 烫烫烫烫烫烫烫烫烫烫身高: 170体重: 130 姓名: DING身高: 170体重: 130 分析和说明: 类CPerson定义了3个重载的构造函数(程序中用A、B、C标明),这些构造函数的重载必须按其规定进行定义,要么参数个数不同,要么参数个数相同,但参数类型不相同。 其中,构造函数CPerson(floath,floatw=120),不仅设置了形参w的默认值,而且还将该构造函数的声明在类中进行,其定义在类体外实现。 在主函数main中,对象one的初始化等价于("DING"),因而调用的是B构造函数,此时对象的私有数据成员name设定了初值“DING”,而height和weight初值没有指定,它们的初值取决于对象的存储类型,可能是默认值或无效值。 对象two的初始化等价于(170,130),因而调用的是C构造函数,此时对象的私有数据成员height和weight初值分别设定为170、130,而name初值没有指定,它可能是默认值或无效值。 对象three的初始化等价于("DING",170,130),因而调用的是A构造函数,此时对象的私有数据成员name、height和weight初值分别设定为"DING"、170和130。 可见,构造函数提供了对象的初始化方式。 若没有定义任何构造函数,则编译自动为类隐式生成一个不带任何参数的默认构造函数,由于函数体是空块,因此默认构造函数不进行任何操作,仅仅为了对象创建时的语法需要。 例如,对于CPerson类来说,默认构造函数的形式如下: CPerson()//默认构造函数的形式 {} 默认构造函数的目的是使下列对象定义形式合法: CPersonone;//即: ();会自动调用默认构造函数 此时,由于对象one没指定任何初值,因而编译会自动调用类中隐式生成的默认构造函数对其初始化。 若当类定义中指定了构造函数,则隐式的默认构造函数不再存在,因此,若对于前面定义的CPerson类来说,若有: CPersonfour;//错误 则因为找不到默认构造函数而出现编译错误。 此时,在类中还要给出默认构造函数的具体定义,即定义一个不带任何参数的构造函数,称为显式的默认构造函数,这样才能对four进行定义并初始化。 另外,构造函数的访问属性必须是公有型(public),否则上述的类对象定义也是错误的。 2.析构函数 与构造函数相对应的是析构函数(Destructor)。 析构函数是C++类中另一个特殊的成员函数,它只是在类名称前加上一个“~”符号(逻辑非),以与构造函数功能相反。 其格式如下: <~类名>() {…} 当对象的生存期结束后,或者当使用delete释放由new来分配动态内存的对象时,析构函数会被自动调用。 这样,数据成员(尤其是用new为其开辟的内存空间)的释放代码就可放入析构函数的函数体中,以便对象消失后自动调用。 需要说明的是: 每一个类最多只能有一个析构函数,且应为public,否则类实例化后无法自动调用析构函数进行释放,但不能被重载,没有任何参数,也不返回任何值,函数名前也不能有任何关键词(包括void)。 例如: classCPerson { public: … ~CPerson(){}//析构函数 … }; 与类的其他成员函数一样,析构函数的定义也可在类体外进行,但必须指明它所属的类,且在类体中还必须有析构函数的声明。 例如:
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编程 基础 新手入门