版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
学习情境二培养面向对象编程思想任务一通过案例学习面向对象编程的基础知识任务二从面向对象的角度分析Windows应用程序的运行原理返回任务一通过案例学习面向对象编程的基础知识子任务1了解面向对象编程知识点详解面向对象编程(ObjectOrientedProgramming,OOP)是一种计算机编程架构。OOP的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组合而成的。OOP达到了软件工程的三个主要目标:重用性、灵活性和扩展性。为了实现整体运算,每个对象都能够接收信息、处理数据和向其他对象发送信息。下一页返回任务一通过案例学习面向对象编程的基础知识1.历史计算机科学中对象作为编程实体最早是于20世纪60年代由Simula67语言引入思维。Simula这一语言是奥利-约翰·达尔和克利斯登·奈加特在挪威奥斯陆计算机中心为模拟环境而设计的。这种办法是分析式程序的最早概念体现。在分析式程序中,人们将真实世界的对象映射到抽象的对象,这叫作“模拟”。Simula不仅引入了“类”的概念,还应用了“实例”这一思想。上一页下一页返回任务一通过案例学习面向对象编程的基础知识面向对象程序设计在20世纪80年代成为一种主导思想,这主要应归功于C++———C语言的扩充版。1983年,贝尔实验室的BjarneStroustrup在C语言的基础上推出了C++。C++进一步扩充和完善了C语言,是一种面向对象的程序设计语言。同时,在图形用户界面(GUI)日渐崛起的情况下,面向对象程序设计很好地适应了潮流。GUI和面向对象程序设计的紧密关联在MacOSX中可见一斑。MacOSX是由Objective-C语言写成的。正如面向过程程序设计使得结构化程序设计的技术得以提升,现代的面向对象程序设计方法使得设计模式的用途、契约式设计和统一建模语言(如UML)技术也得到了一定提升。上一页下一页返回任务一通过案例学习面向对象编程的基础知识比较面向对象程序设计和面向过程程序设计,可以得到面向对象程序设计的其他优点:(1)数据抽象的概念可以在保持外部接口不变的情况下改变内部实现,从而减少甚至避免对外界的干扰;(2)通过继承大幅减少冗余的代码,并可以方便地扩展现有代码,提高编码效率,这也降低了出错概率和软件维护的难度;(3)结合面向对象分析、面向对象设计,允许将问题域中的对象直接映射到程序中,减少软件开发过程中中间环节的转换过程;(4)通过对对象的辨别、划分,可以将软件系统分割为若干相对独立的部分,在一定程度上更便于控制软件复杂度;(5)以对象为中心的设计可以帮助开发人员从静态(属性)和动态(方法)两个方面把握问题,从而更好地实现系统;上一页下一页返回任务一通过案例学习面向对象编程的基础知识(6)通过对象的聚合、联合可以在保证封装与抽象的原则下实现对象在内在结构以及外在功能上的扩充,从而实现对象由低到高的升级。2.主要特征面向对象有继承、封装和多态三个主要特征。继承是指可以从一个类派生一个子类,子类通过继承具有父类的特征和行为,并且人们可以在子类中添加其自身的特征和行为。封装是指将事物的特征和行为抽象为一个类。封装实际上是对事物的抽象过程,依据实际应用,按照主观意识将事物的特征和行为描述为类。多态是指对于相同的调用或操作,作用于不同的对象,而导致其行为也不同,它增强了软件的灵活性和重用性。下面详细介绍。上一页下一页返回任务一通过案例学习面向对象编程的基础知识1)封装性面向对象编程的核心思想之一就是将对象的属性和方法封装起来,使用户只需要知道并使用对象提供的属性和方法等接口即可,而不需要知道对象的具体实现。2)继承性面向对象程序设计中,允许通过继承原有类的某些特性或全部特性而产生新的类,这时,原有的类称为父类(或超类),产生的新类称为子类(或派生类)。子类不仅可以直接继承父类的共性,而且也被允许创建其特有的个性。上一页下一页返回任务一通过案例学习面向对象编程的基础知识3)多态性多态是指在基类中定义的属性和方法被子类继承后,可以具有不同的数据类型或表现出不同的行为。这使得同一属性和行为在基类和派生类中具有不同的语义。多态性丰富了对象的内容,扩大了对象的适应性,改变了对象单一继承的关系。上一页下一页返回任务一通过案例学习面向对象编程的基础知识子任务2类的概念及应用知识点详解在现实世界中,随处可见的一种事物就是对象,对象是事物存在的实体,比如赵刚、李四、苹果、书、水杯、电脑、汽车等。人类解决问题的方式总是将复杂的事物简单化,于是人们就会思考这些对象都是由哪些部分组成的。通常将对象划分为两个部分,即静态部分与动态部分。静态部分,顾名思义,就是不能动的部分,这个部分被称为“属性”,任何对象都会具备其自身的属性,例如一个人有高矮、胖瘦、性别及年龄等属性。而与人这个对象相关的“行为”,即动态部分,有哭泣、微笑、说话、行走和学习等。人类通过探讨对象的属性和观察对象的行为来了解对象。上一页下一页返回任务一通过案例学习面向对象编程的基础知识在计算机世界中,面向对象程序设计思想是以对象的思想来思考问题,首先要将现实世界的实体抽象为对象,然后考虑这个对象具备的属性和行为。例如,现在面临一辆汽车要启动并开向马路这样一个实际问题,试着以面向对象的思想来解决这一实际问题,步骤如下所示:(1)可以从这一问题中抽象出对象,这里抽象出的对象为汽车。(2)识别这个对象的属性。对象具备的自身属性都是静态属性。例如,汽车有四个轮子、一个发动机及机身等。(3)识别这个对象的动态行为,即这辆汽车可以做出的动作,例如启动、奔跑和停止等,这些行为都是这个对象基于其属性而具有的动作。(4)识别出这些对象的属性和行为后,这个对象就定义完成了,然后可以根据这辆汽车具有的特性制定其启动开向马路的具体方案以解决问题。上一页下一页返回任务一通过案例学习面向对象编程的基础知识任务实施(1)提出任务:请各位同学编写一个“动物类”,动物都有姓名、性别、年龄,同时都可以发音、吃饭和睡觉。(2)解决任务,步骤如下:①新建工程ex02_07,选择“Win32控制台应用程序”,单击“确定”按钮。②在应用程序向导中,选择“控制台应用程序”,单击“完成”按钮。③打开ex02_07.cpp,输入如下代码:上一页下一页返回任务一通过案例学习面向对象编程的基础知识classCAnimal{stringname;stringsex;intage;voidSay(){}voidEat(){}voidSleep(){}}上一页下一页返回任务一通过案例学习面向对象编程的基础知识子任务3对象的概念及应用在上一个子任务中,我们已经了解到对象是指现实世界中各种各样的实体,即可以指具体的事物,也可以指抽象的事物,比如张三、苹果,飞机、火车、法律、法规等。而且每个对象都有本身的属性和行为,比如张三、李四具有名字、身高、体重等基本属性,具有吃饭、睡觉、学习、看书、运动等行为。在面向对象的编程思想下,该如何使用对象去解决实际问题呢?知识点详解1.对象的定义在声明一个类之后,并不能够直接使用类,需要定义一个类的对象,这通常也称为类的实例化。可用下面两种方法定义对象:上一页下一页返回任务一通过案例学习面向对象编程的基础知识(1)在声明类的同时直接定义,其方法是,在类声明的右花括号的后面直接写出该类的对象名表。(2)声明了类以后,到使用时再定义,定义的格式与一般变量的定义格式相同,例如:Pen
pen1,pen2;其定义了类Pen的两个对象pen1、pen2。2.对象的引用对象的引用是指对象成员的引用。只要是对象的公有成员,在类的外部可以通过类的对象进行成员的访问,访问对象中的成员可以有两种方法:(1)通过对象名和成员运算符访问对象中的成员,一般格式是:对象名.成员变量;上一页下一页返回任务一通过案例学习面向对象编程的基础知识或对象名.成员函数(实参表);其中的“.”称为成员运算符。(2)通过指向对象的指针访问对象中的成员。访问对象中的成员的一般格式是:指向对象的指针->数据成员名或指向对象的指针->成员函数名(实参表)上一页下一页返回任务一通过案例学习面向对象编程的基础知识3.对象的赋值属于同一个类的对象,由于它们的数据类型完全相同,所以可以相互赋值。不属于同一个类的对象之间是不能相互赋值的。一个对象赋值给另一个对象时,所有的数据成员都会逐位拷贝,这两个对象只是数据成员的值相同,彼此仍是独立的,各自都有自己的内存空间。赋值运算符仍然是“=”。示例ex02_09:对象的赋值。上一页下一页返回任务一通过案例学习面向对象编程的基础知识子任务4构造函数与析构函数知识点详解当建立一个对象时,对象的初始状态即成员变量的取值是不确定的。C++为类专门设计了一个特殊的成员函数来完成初始化对象的工作,这就是构造函数。当不再使用对象或者对象离开其作用域时,希望释放类的对象中申请的内存或者在退出前设置某些变量的值时,C++为类专门设计了一个特殊的成员函数来完成“清理善后”的工作,这就是析构函数。那么这两个函数如何使用?上一页下一页返回任务一通过案例学习面向对象编程的基础知识1.构造函数构造函数和一般成员函数的不同之处在于,构造函数并不是由用户来调用的,而是在建立对象的同时自动执行。构造函数的名称与类的名称必须一致,而不是由用户任意命名。可以将参数传递给构造函数,进行成员变量的初始化工作。(1)构造函数的定义。①在类中声明并定义构造函数。②在类中声明,在类外定义构造函数。上一页下一页返回任务一通过案例学习面向对象编程的基础知识(2)构造函数的调用。示例ex02_13:演示类Pen的构造函数调用的方法。intmain(){
Penpen1;//定义类的实例,不显式初始化
Penpen2(18);//定义类的实例,显式初始化
//pen2.pen(12);//不能显式调用构造函数
pen1.Show();
pen2.Show();
return0;}上一页下一页返回任务一通过案例学习面向对象编程的基础知识(3)拷贝构造函数。拷贝构造函数是一种特殊的构造函数,即复制另一个对象的构造函数。一般在下述三种情况下会用到拷贝构造函数:①用一个类对象显式初始化另一个类对象;②把类对象作为实参传递给函数;③把类对象作为函数的返回值。在这些情况下,系统就会自动调用拷贝构造函数,将参数代表的对象中的属性逐个拷贝到新创建的对象中。上一页下一页返回任务一通过案例学习面向对象编程的基础知识2.析构函数析构函数也是一种特殊的成员函数。其功能与构造函数的功能正好相反,是用来释放一个对象,在对象删除前,用它来做一些清理工作。析构函数具有以下一些特点:(1)析构函数名与构造函数名相同,但它前面必须加一个波浪号(~),以与构造函数相区别。析构函数的声明格式:~<函数名>();(2)在定义析构函数时,不能指定任何返回类型,也没有参数,而且不能重载。因此,在一个类中只能有一个析构函数,而且必须为public,否则类实例化后无法自动调用析构函数进行释放。上一页下一页返回任务一通过案例学习面向对象编程的基础知识(3)在一般情况下,调用析构函数的次序正好与调用构造函数的次序相反:最先被调用构造函数,其对应的析构函数最后被调用。(4)每个类若没有显式地为一个类定义析构函数,编译系统会自动地生成一个默认的析构函数。(5)析构函数可能会在程序的许多退出点被调用,所以尽量不要将它定义为内联函数,否则会导致程序代码的膨胀,降低程序执行效率。上一页下一页返回任务一通过案例学习面向对象编程的基础知识任务实施(1)提出任务:请同学们构造函数实例化两个“动物类”,即定义两个动物对象,分别是考拉(阿美,雌,2岁,“我是一只可爱的树袋熊”,“我爱吃桉树叶”,“我每天睡22个小时”)和人(小明,男,8岁,“我是一名小学生”,“我爱吃蔬菜”,“我每天睡8个小时”)。(2)解决任务,步骤如下:①打开工程ex02_16。②打开ex02_16.cpp文件。③编辑ex02_16.cpp,输入如下代码:上一页下一页返回任务一通过案例学习面向对象编程的基础知识classCAnimal{public:stringname;stringsex;intage;CAnimal();//无参构造函数声明CAnimal(stringca_name,stringca_sex,intca_age);//有参构造函数声明~CAnimal();//析构函数声明voidSay(char*say_content){cout<<say_content<<endl;}上一页下一页返回任务一通过案例学习面向对象编程的基础知识voidEat(char*eat_content){cout<<eat_content<<endl;}voidSleep(char*sleep_content){cout<<sleep_content<<endl;}};CAnimal::CAnimal()//无参数构造函数的定义{}CAnimal::CAnimal(stringca_name,stringca_sex,intca_age)//有参数构造函数的定义,初始化各属性{
name=ca_name;
sex=ca_sex;
上一页下一页返回任务一通过案例学习面向对象编程的基础知识
age=ca_age;}CAnimal::~CAnimal(){cout<<"调用了构造函数"<<endl;}int_tmain(intargc,_TCHAR*argv[])CAnimalca1(“阿美”,“雌”,2),ca2(“小明”,“男”,8);//实例化对象ca1.Say(“我是一只可爱的树袋熊”);//调用对象的方法ca1.Eat("我爱吃桉树叶");ca1.Sleep("我每天睡22个小时");
上一页下一页返回任务一通过案例学习面向对象编程的基础知识ca2.Say("我是一名小学生");ca2.Eat("我爱吃蔬菜");ca2.Sleep("我每天睡8个小时");}④程序运行结果如图2-3所示。子任务5构造函数的重载知识点详解在一个类中可以定义多个构造函数,以便提供不同的初始化的方法,供用户选用。这些构造函数具有相同的名字,而参数的个数或参数的类型不相同。这称为构造函数的重载。上一页下一页返回任务一通过案例学习面向对象编程的基础知识关于构造函数的重载的几点说明:(1)调用构造函数时不必给出实参的构造函数,称为默认构造函数(defaultconstructor)。显然,无参的构造函数属于默认构造函数。一个类只能有一个默认构造函数。(2)如果在建立对象时选用的是无参构造函数,应注意正确书写定义对象的语句。(3)尽管一个类可以包含多个构造函数,但是对于每一个对象来说,建立对象时只执行其中一个构造函数,并非每个构造函数都被执行。上一页下一页返回任务一通过案例学习面向对象编程的基础知识任务实施(1)提出任务:请同学们编写一个程序,以实现求和运算,要求:可以求2个数的和,也可以求3个数的和。(2)解决任务,步骤如下:①打开工程ex02_19。②打开ex02_19.cpp。③编辑ex02_19.cpp,输入如下代码:上一页下一页返回任务一通过案例学习面向对象编程的基础知识classCSum{public:intnum1;intnum2;intnum3;CSum(inta,intb);CSum(inta,intb,intc);voidShowSum();};CSum::CSum(inta,intb)//构造函数的定义上一页下一页返回任务一通过案例学习面向对象编程的基础知识num1=a;num2=b;num3=0;}CSum::CSum(inta,intb,intc)//构造函数的定义{num1=a;num2=b;num3=c;}上一页下一页返回任务一通过案例学习面向对象编程的基础知识CSum::ShowSum(){cout<<"Sum:"<<num1+num2+num3<<endl;}voidmain(){CSumcs1(2,4),cs2(3,5,7);//实例化对象cs1.ShowSum();cs2.ShowSum();}(4)程序运行结果如图2-4所示。上一页下一页返回任务一通过案例学习面向对象编程的基础知识子任务6类的继承知识点详解在现实世界中,能看到很多哺乳动物,它们的特点都是具有高而恒定的体温,都可以觅食和运动。人类是一种特殊的哺乳动物,人类除了具有哺乳动物的基本特性之外,还可以说话、学习等。狗也是哺乳动物,它除了具有哺乳动物的基本特性之外,还具有接受训练等特性。所以,可了解到,在现实世界中,事物之间有着复杂的联系,除了相似性、多样性等之外,还有遗传性或继承性。上一页下一页返回任务一通过案例学习面向对象编程的基础知识在C++中,当一个新类从一个已定义的类中派生后,新类不仅继承了原有类的属性和方法,并且还可以拥有自己的新的属性和方法,这称为类的继承和派生。被继承的类称为基类(Baseclass)或超类(Superclass),又称为父类,在基类或父类上建立的新类称为派生类(Derivedclass)或子类(Subclass)。一个基类可以有多个派生类。一个派生类还可以作为基类,继续派出新的类来,这样的派生方式称为多层派生或多重派生。从继承的角度来看,其可称为多重继承。所以,哺乳动物是基类,人类、狗等是派生类。上一页下一页返回任务一通过案例学习面向对象编程的基础知识1.派生类的定义在C++中,一个派生类的定义格式如下:Class<派生类名>:[<继承方式1>]<基类名1>,[<派生方式2>]<基类名2>,…{[<派生类的成员>]};上一页下一页返回任务一通过案例学习面向对象编程的基础知识2.派生数据成员初始化C++中规定,派生类中对象成员初值的设定应在初始化列表中进行,因此一个派生类的构造函数的定义可有下列格式:上一页下一页返回任务一通过案例学习面向对象编程的基础知识说明:(1)在成员初始化列表中,多个成员初始化之间必须用逗号分隔。(2)在派生类构造函数的成员初始化列表中,既可有基类的数据成员的初始化,也可有派生类中对象成员的初始化。派生类的数据成员也可在成员初始化列表中进行初始化,但数据成员的初始化形式必须使用“数据成员名(参数)”的形式。(3)派生类中的各数据成员的初始化次序总体是:首先是基类成员的初始化,然后才是派生类的数据成员初始化。(4)基类成员的初始化次序与它在成员初始化列表中的次序无关。在单继承中,它取决于继承层次的次序,即优先初始化上层类的对象。而在多继承中,基类成员的初始化次序取决于派生类声明时指定继承时的基类的先后次序。上一页下一页返回任务一通过案例学习面向对象编程的基础知识(5)派生类自身数据成员的初始化次序也与其在成员初始化列表中的次序无关,它们取决于在派生类中声明的先后次序。任务实施(1)提出任务:假设有一个动物类,静态信息为名称和颜色,动态信息为设置姓名、设置颜色、移动。还有一个小狗类,它除了具有动物的基本信息外,还具有静态信息:分类,动态消息:吠叫。请同学们编写一个程序,通过继承的方式,实现信息的复用。(2)解决任务,步骤如下:①新建工程ex02_21。②打开ex02_21.cpp。③编辑ex02_21.cpp,输入如下代码:上一页下一页返回任务一通过案例学习面向对象编程的基础知识classCAnimal{protected:stringname;//颜色stringcolor;//名称public:CAnimal()//构造函数{name="";color="";}上一页下一页返回任务一通过案例学习面向对象编程的基础知识voidSetName(stringst_name){name=st_name;}voidSetColor(stringsc_color){color=sc_color;}voidMove(){printf("Animalismoving!\n");}};classCDog:publicCAnimal{protected:上一页下一页返回任务一通过案例学习面向对象编程的基础知识stringkind;public:CDog(){kind="";}voidSetKind(stringsk_kind){kind=sk_kind;}voidYelp(){printf("Dogcanyelp!");}};intmain(intargc,char*argv[])上一页下一页返回任务一通过案例学习面向对象编程的基础知识{CDogdog;dog.SetName("狗");dog.SetColor("白色");dog.Move();//调用基类的方法dog.Yelp();//调用自身的方法return0;}④运行效果,如图2-6所示。上一页下一页返回任务一通过案例学习面向对象编程的基础知识子任务7类的多态知识详解多态(Polymorphism)是指不同类型的对象接收相同的消息时产生不同的行为。多态是面向对象开发过程中一个非常重要的概念,可以说是面向对象的核心。只有体现出多态的特征,一个程序才称得上是面向对象的程序。在C++中,多态可分为两种:编译时的多态和运行时的多态。编译时的多态是通过函数的重载来实现的。运行时的多态是通过继承和虚函数来实现的,它是指在程序执行之前,根据函数和参数还无法确定应该调用哪一个函数,必须在程序的执行过程中,根据具体的执行情况动态地确定。上一页下一页返回任务一通过案例学习面向对象编程的基础知识虚函数是实现运行时多态的一个重要方式,是重载的另一种形式,实现的是动态的重载,即函数调用与函数体之间的联系是在运行时建立的,也就是动态联编。在使用虚函数时,要注意以下几点:(1)虽然虚函数定义只是在一般函数定义前添加了关键字virtual,但虚函数必须使类中的成员函数。(2)可把析构函数定义为虚函数,但不能将构造函数定义为虚函数。通常在释放基类及其派生类中的动态申请的存储空间时,也要把析构函数定义为虚函数,以便实现撤销对象时的多态性。(3)虚函数在派生类重新定义时参与的个数和类型以及函数类型必须与基类中的虚函数完全匹配,这一点和函数重载完全不同,并且虚函数派生下去仍是虚函数,且可省略关键字virtual。上一页返回任务二从面向对象的角度分析Windows应用程序的运行原理子任务1Windows编程基础知识点详解窗口应用程序的开发一般采用可视化的面向对象的开发,可选择的窗口应用程序开发语言有VisualC++、VisualBasic、Java、Delphi等。无论采用哪一种开发语言,首先要了解窗口应用程序的基本机制。窗口应用程序运行于Windows操作系统。Windows操作系统是一个多任务操作系统,因此窗口应用程序的组成、支持技术、基本运行机制等与DOS应用程序有着本质的区别。在学习开发窗口应用程序之前,先要对窗口应用程序有一个概念上的了解。下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理1.窗口窗口是应用程序与用户进行交互的界面,应用程序通过窗口传递信息给用户,同样用户通过窗口输入数据,发布命令给应用程序。Windows界面包含了丰富的标准用户界面元素,包括窗口、图标、菜单、滚动条、对话框、控件和消息框等。用户使用这些界面元素可以方便地与应用程序进行交互,一个典型的窗口外观如图2-8所示。上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理在Windows编程中,各种窗口、菜单、按钮、对话框及程序模块等Windows的规范部件是按“对象”来组织的。为了提高开发窗口应用程序的效率,微软公司为用户提供了大量能创建上述标准元素的API函数和C++类,并且以WindowsAPI函数库和C++类库的形式提供给用户,以充分满足构成应用程序操作界面的需要。2.消息和消息队列窗口应用程序是利用消息(Message)与其他窗口应用程序和操作系统进行信息交换的。消息的作用是通知一个应用程序某个确定的事件的产生,应用程序会对该事件产生响应,响应的方式已预先在应用程序中定义,即编写了相应的消息处理代码。例如当按下鼠标左键时,系统会产生WM_LBUTTONDOWN消息,并通知应用程序窗口,应用程序接到该消息后,会检查是否已定义消息处理函数并作出响应。上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理Windows操作系统内核基本元件USER为所有的用户界面元素提供支持,它用于接收和管理所有输入消息、系统消息,并把它们发送给相应应用程序的消息队列。消息队列是一个系统定义的内存块,用于临时存储消息,或把消息直接发给窗口过程。每个应用程序都维护着自己的消息队列,并从中取出消息,利用窗口函数进行处理,如图2-9所示。窗口应用程序接受系统队列传递过来的消息的步骤如下:(1)每个窗口应用程序都有一个WinMain()函数,在该函数中会定义一个窗口句柄,当窗口应用程序启动时,会使用窗口句柄注册,操作系统使用窗口句柄与窗口应用程序通信。(2)窗口应用程序创建一个或多个窗口,每个窗口都有一个窗口处理函数(WndProc),负责窗口显示和响应用户输入。上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理(3)消息映射(MessageLoop)负责从消息队列中取消息,并送回窗口,由窗口处理函数选择合适的消息处理函数响应消息。若窗口处理函数中没有给出该消息的处理代码,将由DefWindowProc函数进行默认处理。Windows应用程序的消息来源有以下4种:(1)输入消息。由键盘和鼠标操作产生输入消息。这一类消息首先放在系统消息队列中,然后由Windows操作系统将它们送入应用程序消息队列中,由应用程序来处理消息。上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理(2)控件消息。用户操作窗口的控件对象时产生控件消息,例如当用户在列表框中改动当前选择或改变了复选框的状态时就会发出控件消息。这类消息一般不进入应用程序消息队列,而是直接发送到控件对象所属的对话框窗口。(3)系统消息。其对程序化的事件或系统时钟中断作出反映。一些系统消息,像DDE消息(动态数据交换消息)要通过Windows的系统消息队列,而另一些系统消息则不通过系统消息队列,而直接送入应用程序的消息队列,如创建窗口消息。上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理(4)用户消息。这是程序员自己定义并在应用程序中主动发出的,一般由应用程序的某一部分内部处理。3.事件驱动的程序设计Windows操作系统下的窗口应用程序采用事件驱动的程序设计,与DOS操作系统下的面向过程的程序设计有着明显的不同。在DOS操作系统下,用户在DOS提示符后输入一行命令及参数,启动应用程序并按程序指定运行。一个程序是一系列预先定义好的操作序列的集合。程序直接控制程序事件和过程的顺序,并按照某种不可改变的模式进行工作。上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理在窗口应用程序下,用户首先启动应用程序,然后窗口等待用户通过对图形界面上的元素的操作,传递信息和命令,如选择一个菜单项或者单击一个按钮。窗口应用程序不是按事先安排好的顺序来执行的,而是由事件的发生来控制逻辑。事件的发生是随机的、不确定的,这就允许用户按各种合理的顺序来安排程序的流程。在过程驱动的程序中,程序执行的顺序是确定的,如图2-10所示。在这种过程驱动的程序中,首先按事先安排好的顺序把所有的成绩输入,然后再计算每一个运动员的总分,再进行成绩排名。事件驱动的程序的逻辑顺序是按事件的产生而决定的,事件的产生不是预先定义的,有着随机性。图2-11给出了事件驱动程序的流程示意。上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理4.资源管理资源可分为用户自定义资源和系统资源两种。用户自定义资源是指窗口可视元素的映像,即在前面所提及的窗口所包含的标准元素。例如菜单、对话框、工具栏等,是由每一个应用程序各自定义的。系统资源是由系统提供给各个应用程序共享的,常见的系统资源包括设备上下文、画刷、画笔、字体、通信端口等。上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理子任务2Windows应用程序的组成知识点详解这一部分将分析一个简单的Win32窗口应用程序,MFC应用程序是建立在Win32应用程序设计的基础上的,这将帮助读者更好地理解一个MFC应用程序是如何初始化的、窗口是如何创建的、消息是如何处理的。所有的窗口应用程序必须包含两个基本函数:(1)应用程序主函数WinMain()。WinMain函数定义了窗口句柄,创建初始化窗口并启动一个消息循环。上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理(2)窗口处理函数WinProc()。WinProc函数处理所有从操作系统传递到窗口的消息。每一个窗口,无论是简单的或复杂的,都要有一个窗口处理函数。1._tWinMain函数和C语言中的main()函数一样,Windows程序是从_tWinMain()函数开始的,并随着_tWinMain函数的结束而结束。_tWinMain()函数是在WINBASE.H中定义的,定义如下:intAPIENTRY_tWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理LPSTRlpCmdLine,intnCmdShow);参数说明如下:(1)hInstance。系统分配的窗口所属的应用程序的实例句柄,标识当前进程的实例,它实际上是进程所占据的地址空间的首地址,这个实例句柄是程序的唯一标识。(2)hPrevInstance。它用来检查是否有多个程序实例运行,这是16位Window的残留物,在Win32应用程序中,这个参数始终为NULL。上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理(3)lpCmdLine。这是一个指向字符串的指针,用来保存运行程序时的命令行参数,这同main()函数中的argv[]参数的作用类似。(4)nCmdShow。它用来指明应用程序的主窗口的显示方式(最大化显示、最小化显示、一般化显示)。该参数经常被ShowWindow()函数作为显示窗口的参数。上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理2.窗口处理函数注册窗口类的一个主要目的就是将一个窗口和一个窗口处理函数联系起来,窗口处理函数决定窗口在它的客户区中显示什么,和窗口如何响应用户输入。窗口处理函数能够按程序员预先定义的代码处理消息,如果程序员没有对该消息的处理作定义,则把此消息交给默认窗口处理函数DefWindowProc()处理。函数DefWindowProc()是系统默认的处理过程,以保证所有发送到该窗口的消息均得到处理。窗口函数定义如下:LRESULTCALLBACKWndProc(HWNDhwnd,UNITmessage,WPARAMwParam,LPARAMlParam)上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理子任务3MFC程序框架知识点详解利用WindowsAPI函数编制Windows应用程序,程序员需要编写大量的程序代码。而利用MFC编写实现同样功能的程序,则要轻松得多。在学习情境一中我们学习了使用App⁃Wizard创建一个MFC单文档应用程序,不需要做任何额外的工作,直接运行程序,一个具备常用工具栏、菜单栏、状态栏的标准窗口应用程序就已经出现的屏幕上。1.MFC类简介MFC类库中的各个类支持快速生成面向对象的应用程序,它们之间存在一定的关联,它们的集合构成MFC应用程序框架,如图2-13所示。上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理(1)CObject是MFC类库的根类。从CObject派生的类都具有以下特点:①在程序运行时,可获得对象的大小、类名、动态创建类的实例。②提供把对象状态转储给调试机制的能力,类似于判断当前对象的数据成员是否有效。③具有把对象的数据存进文件,或从文件中提取数据重建对象的能力。(2)命令类CCmdTarget:它是CObject的子类,它是MFC库中所有具有消息映射属性的基类。它的子类有CWinThread类、CWnd类、CDocument类,从CCmdTarget派生的类在程序运行时,能动态创建对象,并能处理命令消息。上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理(3)应用程序线程支持类CWinThread:MFC支持多线程,所有的应用程序至少有一个线程。CWinThread是所有线程类的基类,封装了操作应用程序的多线程功能。应用程序类CWinApp是CWinThread的子类,封装了初始化、运行、终止应用程序的代码。(4)窗口类CWnd:它提供MFC中所有窗口类的基本功能。从CWnd派生的类可以拥有自己的窗口,并能对它进行控制。框架窗口类CFrameWnd和视图类CView是CWnd类的两个子类,前者提供和维护窗口的边框、菜单栏、工具栏、状态栏,负责显示和搜索用户命令,后者负责为文档提供一个或几个视图。视图的作用是为修改、查询文档等任务提供人机交互的界面。(5)文档类CDocument:负责装载和维护文档。文档包括应用程序的工作成果、环境设置数据等,或程序需要保存的任何内容。上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理2.构建窗口应用程序的基本类利用VC++提供的AppWizard,可直接生成MFC应用程序,但无法看到Windows程序结构中的主函数WinMain和窗口函数WndProc,因为它们被封装在MFC类中了。在MFC类中,应用程序类CWinApp和框架窗口类CFrameWnd替代了主函数WinMain和窗口函数WndProc的功能,负责程序的初始化、退出时的必要清理、窗口的创建和销毁、消息循环等功能。上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理应用程序类CWinApp和框架窗口类CFrameWnd是MFC应用程序最基本的两个类,所有的MFC应用程序都必须包含这两个类。1)应用程序类在AppWizard生成的类中,Cex02_25App代表的是应用程序,它的基类CWinApp代表了Windows应用程序,并把每一个程序都看作一个对象。应用程序类将负责完成MFC应用程序的一些例行初始化工作。另外,CWinApp的基类是CWinThread,因此它也要负责管理程序主线程的运行。AppWizard声明一个由CWinApp继承的类Cex02_25App,在生成的实现文件中包含:上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理(1)应用程序类的消息映射。(2)一个空的应用程序类的构造函数。(3)一个Cex02_25App类的全局对象theApp。(4)一个InitInstance函数的标准定义。全局对象theApp在WinMain()函数执行之前初始化,在进入MFC版本的WinMain()函数之后,theApp很快就获得了管理权,进行Windows程序的一些例行初始化工作。CWinApp提供了四个函数管理实现MFC应用程序的生命期,函数功能见表2-1。这四个函数都能被CWinApp的派生类Cex02_25App重载,其中只有InitInstance()函数是必须被重载的。上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理2)主框架类CMainFrameCMainFrame代表的是程序的主框架窗口,一个窗口应用程序除了白色部分的视图(View)外,程序主窗口的其他部分都归CMainFrame管理。视图实际上是主框架窗口的子窗口,它的大小正好等于主框架窗口的客户区的大小,当运行一个多文档程序时,例如Word,将所有的文档窗口最小化,就会留下一个灰色背景的客户区,它也是主框架窗口的一部分。单文档程序的主框架窗口是在调用ProcessShellCommand()函数时创建的,在主框架窗口被创建之前,CMainFrame::PreCreateWindow()函数将被自动调用。在这个函数中可以更改主框架窗口的风格,或者对窗口类的一些属性进行修改,此时窗口句柄还不可用。上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理3.文档/视图结构文档/视图结构是MFC应用程序最核心的概念,它将应用程序的数据和浏览、操纵数据的方法分离。简单地说,文档对象通常代表一个已经打开的文件,而视图对象表示文档中数据的可视化表示,并提供可视化交互界面供用户查看、编辑数据。图2-15演示了一个MFC应用程序中各个主要对象在文档/视图结构中交互的途径。应用程序的数据存储在文档对象中,并可以显示在视图中。文档与视图的关系是一对多的关系,也就是说文档中的数据可以以不同的方式显示。例如:在一个Excel文件中,同样的数据可以以表格的形式表示,也可以图表的形式表示。在一个视图中修改数据,首先反映到文档对象,刷新视图,在各个视图中反映所作的修改。上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理1)文档类应用程序中的文档类是CDocument类的派生类,CDoument类主要的成员函数及功能见表2-2。AppWizard默认重载了两个虚函数OnNewDocument()和Serialize()。初始化文档有两种途径:一是执行菜单File下的菜单命令New,二是执行菜单File下的菜单命令Open,前者调用OnNewDocument()函数,后者调用OnOpenDocument()函数。此时,在SDI应用程序中,打开的文档将被关闭,一个新的空文档将加载到文档对象中;在MDI应用程序中,除了已打开的文档外,一个空文档将被打开。上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理2)视图类视图类显示存储在文档类对象中的数据,并允许用户编辑这些数据。应用程序中视图类是CView类的派生类,CView类的主要成员函数及功能见表2-3。GetDocument()函数是很重要的一个成员函数,用于视图类与文档类的通信,OnDraw()是实现视图输出的关键函数,绝大多数的视图输出工作都在这个函数中完成。当程序窗口创建、移动、改变大小或窗口覆盖时,窗口都需要重绘,系统会自动调用视图类的OnDraw(CDC∗pDC)成员函数。其参数pDC是指向CDC类对象的指针,负责文档显示的设备环境,设备环境对象与特定的设备相关联,并有一组相应的成员函数。上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理3)文档模板类AppWizard除了生成可在工作区中展示的应用程序类、窗口框架类、文档类和视图类以外,还生成了文档模板类CDocTemplate。文档模板类定义了文档模板的基本功能,是抽象基类,通常不需要程序员干涉它的运行,所以在工作区中没有列出文档模板类。文档模板把文档类、主框架类和视图类联系在一起。MFC提供了它的两个派生类:单文档界面的文档模板CSingleDocTemplate和多文档界面的文档模板CMultiDocTemplate,如图2-16所示。上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理子任务4消息映射知识点详解1.消息的类别及其描述在Win32的窗口函数中,采用switch-case结构进行消息处理。而在MFC应用程序中,采用消息映射的方法,将消息映射到各个消息处理函数。MSG结构用于描述消息。区别消息的一般方法是:对结构中的主消息message、附加参数wParam和lParam这三个字段进行判断。在MFC应用程序中,消息分为窗口消息、命令消息和控件消息三种类型。上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理1)窗口消息系统可以产生窗口消息,与窗口交互也能产生窗口消息。窗口消息只能被窗口或者窗口对象处理。在MFC应用程序中,CView和CFrame及其派生类及自定义窗口类能够处理窗口消息。窗口消息的字段格式为:message:WM_XXX。wParam和lParam:随WM_XXX而变。2)命令消息选择菜单项、单击工具按钮、按加速键及程序中的命令等都可以产生命令消息。在MFC应用程序中,凡是从基类CCmdTarget派生的类都能处理命令消息。上一页下一页返回任务二从面向对象的角度分析Windows应用程序的运行原理命令消息的字段格式如下:message:WM_COMMANDwParam:低16位为命令ID、高16位为0lParam:0L3)控件消息当控件事件发生时,改变文本框控件的内容、选择列表框控件中的某一选项等,都会产生控件消息。控件消息的字段格式如下:message:WM_NOTIFY。wParam:控件ID。lParam:指向NMHDR的指针
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年度重庆市风景园林专业职称(风景园林)练习题及答案
- 2026年北京市思想政治工作人员专业职务评定考试(专业课高级)综合练习题及答案
- 河南省新乡市第七中学2026届高三第四次四校联考化学试题试卷含解析
- 2025年中国维生素C单磷酸钠市场调查研究报告
- 2025年中国精密水准仪市场调查研究报告
- 2025年中国磺酸钠市场调查研究报告
- 2025年中国盘扣市场调查研究报告
- 2025年中国电能计量芯片市场调查研究报告
- 2025年中国棘轮式电缆剪市场调查研究报告
- 2025年中国K钉市场调查研究报告
- 2025年中国静音舱行业市场全景分析及前景机遇研判报告
- 2025年河北石家庄交通投资发展集团有限责任公司公开招聘操作类工作人员336人笔试参考题库附带答案详解
- 随车吊吊装安全知识培训课件
- 考核化验员管理办法
- 2025年北京朝阳社区工作者招聘考试笔试试题(含答案)
- 混凝土采购供货投标文件
- 水陆综合地形测量技术在无人船测深中的应用
- 《液压与气压传动》课件-第六章 基本回路
- 【TCP云运维】腾讯云运维高级工程师认证题库(附答案)
- DG-TJ08-108-2025 优 秀历史建筑保护修缮技术标准
- 保税货物考试题及答案
评论
0/150
提交评论