收藏 分享(赏)

计算机语言与程序设计 (15).ppt

上传人:wspkg9802 文档编号:8241154 上传时间:2019-06-16 格式:PPT 页数:83 大小:193.50KB
下载 相关 举报
计算机语言与程序设计 (15).ppt_第1页
第1页 / 共83页
计算机语言与程序设计 (15).ppt_第2页
第2页 / 共83页
计算机语言与程序设计 (15).ppt_第3页
第3页 / 共83页
计算机语言与程序设计 (15).ppt_第4页
第4页 / 共83页
计算机语言与程序设计 (15).ppt_第5页
第5页 / 共83页
点击查看更多>>
资源描述

1、1,第十五讲 面向对象程序设计与C+,2,内 容,程序设计方法概述 面向对象程序设计方法 C+语言,3,一、程序设计方法概述,4,程序设计方法,早期的程序设计方法 结构化程序设计方法 面向对象程序设计方法,5,早期的程序设计方法追求程序的高效率,编程过份依赖技巧,而不注重所编写程序的结构,也就是没有固定程序设计方法的时期。程序的可读性、可重用性都很差。其中一个典型问题是频繁使用goto语句。虽然这种方法存在很多问题,但对于单人完成较为简单的任务,事实上还是经常被采用的。,早期的程序设计方法,6,结构化方法出现在70年代中期,我们可以这样理解它:结构化程序设计方法是从程序要实现的功能的角度出发的

2、。一般按照自顶向下、逐步求精的方式,将程序要完成的功能逐级划分成许多小的功能模块,象搭积木一样搭起来。这些小的功能模块最终都可以转化成三种基本控制结构的组合。所谓的功能可以理解为对数据的操作。在程序实现中,特定的功能或功能模块一般用函数来实现,它们要对特定的数据进行操作。,结构化程序设计方法,7,结构化设计方法的特点,结构化程序设计方法的主要技术是自顶向下、逐步求精,采用单入口、单出口的控制结构 自顶向下是一种分解问题的技术,逐步求精指结构化程序的连续分解,最终成为下面三种基本控制结构的组合 三种基本控制结构:顺序、分支、循环,8,分支结构,语句1,语句2,语句3,条件,语句2,语句1,语句1

3、,语句2,顺序结构,循环结构,9,例:从键盘输入一个学生的信息(包括姓名、年龄、性别、学号等)和一个老师的信息(包括姓名、年龄、性别、是否授课等),然后将信息输出到屏幕。,一个简单的例子,10,分析:根据需求(题目要求),我们可以把问题划分为两个功能模块,一个是输入模块,一个是输出模块,做完了输入模块,再做输出模块。再具体考虑每个模块如何实现(逐步求精)。我们用C语言来写,参看下面的代码:,11,/ void main() / 主函数开始 / 声明用于存储学生信息的变量char strStudentName20; / 学生姓名int nStudentAge; / 学生年龄char cStude

4、ntSex; / 学生性别int nStudentNumber; / 学生学号/ 声明用于存储老师信息的变量char strTeacherName20; / 老师姓名int nTeacherAge; / 老师年龄char cTeacherSex; / 老师性别int nIsTeaching; / 是否授课/ 输入模块GetStudentInfo(); / 输入学生信息GetTeacherInfo(); / 输入老师信息/ 输出模块 PrintStudentInfo(); / 输出学生信息PrintStudentInfo(); / 输出老师信息 ,描述学生的数据,描述老师的数据,函数,函数,12

5、,上面的例子中,我们可以进一步将属于学生和老师的变量放入结构中。这样可以在一定程度上完成对数据的封装。但在结构化程序设计中,数据与对其进行操作的函数仍是分离的。,/ 声明学生结构Student struct Student char strStudentName20; / 学生姓名int nStudentAge; / 学生年龄char cStudentSex; / 学生性别int nStudentNumber; / 学生学号 ; / 声明老师结构Teacher struct Teacher char strTeacherName20; / 老师姓名int nTeacherAge; / 老师年龄

6、char cTeacherSex; / 老师性别int nIsTeaching; / 是否教书 ;,13,14,问题:函数用于完成一定的功能,它们都是针对特定的数据进行操作的。那么我们能不能以特定的数据为中心,将数据与对其进行操作的函数封装起来呢?,15,面向对象程序设计方法,面向对象程序设计出现在80年代中后期 面向对象程序设计是建立在结构化程序设计基础上的,但它不再是从功能入手,而是从对象(人、地方、事情等)入手 面向对象程序设计以类作为构造程序的基本单位,它具有封装、数据抽象、继承、多态等特点,16,简单地说,对象就是现实世界中的各种实体,包括人、地点和事物等。例如,桌子、椅子、教室、学

7、生、老师、电话、汽车等等。一般都要从属性和行为两个方面来对它们加以描述。在这里,我们认为对象和对象的实例是同一个概念。,什么是对象?,17,对象具有的一些特征称为属性,以一个人为例,他的姓名、年龄、身高、体重等可以作为他的属性。这些属性会有其对应的值,一般至少会有一项区别于其它对象,它们在程序设计中对应的是一定的数据。为了达到目的,对象必须提供的功能(或必须提供的服务)称为对象的行为,在程序设计中对应一定的方法(函数)。,属性和行为,18,类描述了一组具有相同属性(数据元素)和相同行为(函数)的对象。类的数据成员是对对象属性的抽象,类的函数成员是对对象行为的抽象,而类本身就是对对象的抽象。,什

8、么是类?,19,class Student / Student类的声明 public: / 公有成员Student(); / 构造函数Student(); / 析构函数char* GetName(); / 查询姓名int GetAge(); / 查询年龄char GetSex(); / 查询姓名int GetNumber(); / 查询学号bool SetName(char* n); / 设置姓名bool SetAge(int age); / 设置年龄bool SetSex(char* s); / 设置性别bool SetNumber(int num);/ 设置学号 protected: /

9、保护成员char m_strName20; / 姓名,字符串数组int m_nAge; / 年龄,整型char m_cSex; / 性别,字符型int m_nNumber; / 学号,整型 ;,例:C+中类的声明Student类,成员函数,成员函数,成员变量,20, Student A; / 声明Student的对象A A.SetName(“张三”); / 设置A的名字 A.SetAge(20); / 设置A的年龄 ,例:C+中类使用,21,22,总的来说, 结构化程序设计方法是一种模块化程序设计方法,它在解决问题时是以功能为中心的,一定的功能模块虽然也作用于特定的数据,但它们并没有被封装在一

10、起。 面向对象程序设计方法则是以对象为中心来解决问题的。属于同种对象的属性(数据)和服务(功能)被抽象出来封装到一起。,23,二、面向对象程序设计方法,24,数据抽象封装继承多态动态绑定,面向对象方法的主要特点,25,数据抽象,类是一组相似对象的抽象描述,它抽取了这些对象的共性组成了一个共同的概念。抽象数据类型(Abstract Data Type,ADT)是一组相似的类的抽象,而一个类又是ADT的具体实现。,26,封装是指软件的组成部分(模块、子程序、方法等)应该互相独立,或者隐藏设计的细节。在传统的方法中,封装通常局限于将功能和数据分开封装;而在面向对象方法中,封装将功能和数据同时装入对象

11、中。参看Student类的例子,封 装,27,class Student / Student类的声明 public: / 公有成员Student(); / 构造函数Student(); / 析构函数char* GetName(); / 查询姓名int GetAge(); / 查询年龄char GetSex(); / 查询姓名int GetNumber(); / 查询学号bool SetName(char* n); / 设置姓名bool SetAge(int age); / 设置年龄bool SetSex(char* s); / 设置性别bool SetNumber(int num);/ 设置学

12、号 protected: / 保护成员char m_strName20; / 姓名,字符串数组int m_nAge; / 年龄,整型char m_cSex; / 性别,字符型int m_nNumber; / 学号,整型 ;,例:C+中类的声明Student类,28,如果类与类之间有is-a(是一种)的关系,那么可以采用继承机制来表示。子类可以自动继承父类中的一些属性和行为,而不必再进行定义,从而实现了代码的复用。同时,继承也是产生新类的方法之一。,继 承,29,从上图可以看出,学生和教师都是人的一种,所以,学生类和教师类可以从人类继承而来,从而实现了代码的共享。,30,class People

13、 / People类的声明 public: / 公有成员People(); / 构造函数People(); / 析构函数char* GetName(); / 查询姓名int GetAge(); / 查询年龄bool SetName(char* n); / 设置姓名bool SetAge(int age); / 设置年龄 private: / 私有成员 protected: / 保护成员char m_strName20; / 姓名,字符串数组int m_nAge; / 年龄,整型char m_cSex; / 性别,字符型 ;,类的声明举例People类,31,class Teacher: pub

14、lic People / Teacher类的声明 public: / 公有成员Teacher(); / 构造函数Teacher(); / 析构函数bool IsTeaching(); / 查询是否授课 private: / 私有成员 protected: / 保护成员bool m_bIsTeaching / 是否授课 ;,类的声明举例Teacher类,32,class Student : public People public: Student(); / 构造函数Student(); / 析构函数int GetNumber(); / 查询学号bool SetNumber(int n); /

15、设置学号 private: protected: int m_nNumber; / 学号 ;,类的声明举例Student类,33,在程序中同一符号或名字在不同情况下具有不同解释的现象称为多态性(Polymorphism)。在面向对象程序设计语言中,由程序员设计的多态性由两种基本形式:编译时多态性和运行时多态性。许多程序设计语言都或多或少地支持多态性,但运行时多态性是面向对象程序设计语言的一大特点。,多 态,34,编译时多态性是指在程序编译阶段即可确定下来的多态性,主要通过使用重载(Overloading)机制获得,重载机制包括函数重载和运算符重载两大类。举一个C+中的例子:int Abs(in

16、t x); double Abs(double x);coutAbs(-4)endl; /调用int Abs coutAbs(3.2)endl;/调用double Abs,35,运行时多态性是指必须等到程序动态运行时才可确定的多态性,主要通过继承结合动态绑定获得。 动态绑定也称晚绑定,它也是面向对象的重要特点之一。动态绑定的使用可以提高程序的可用性和可扩展性。,36,八十年代末以来,由Booch,Coad,Yourdon,OMT,Jacobson等人提出的多种面向对象方法在已经得到了广泛的应用。面向对象方法中的三种基本活动就是:(1) 识别对象和类 (2) 描述对象和类之间的关系 (3) 通过

17、描述类的功能定义对象的行为,面向对象方法,37,科德将对象模型分为下面四个部件,也就是将对象分为了四组: (1)问题域PD(problem domain) (2)人机交互HI(human interaction) (3)数据管理DM(data management) (2)系统交互SI(system interaction),科德(Coad)方法,38,问题域问题(PD)通常最先考虑,因为用户往往最关心为自己的商业问题建模。问题域部件包含与需要建模的问题直接有关的对象。问题域部件的对象技术上呈现中型,它们几乎不了解或完全不了解人机交互、数据管理和系统交互部件的对象。 人机交互部件(HI)包含为

18、问题域对象和人们之间提供界面的对象。在对象模型中,人机交互部件的对象通常对应具体的窗口和报表。,39,数据管理部件(DM)包含为问题域对象和数据库系统或文件管理系统之间提供界面的对象。在对象模型中,数据管理部件的对象通常对应某些需要保存及搜索的问题域对象。 系统交互部件(SI)包含为问题域对象和其它系统或设备提供界面的对象。系统交互对象封装了通信协议,使得问题域对象不需要了解底层的实现细节。,40,科德的面向对象方法包括一下四个活动: (1)确定系统的目标和特点 (2)确定四种模型部件的对象和模式 (3)建立对象责任 (2)定义服务场景以完成特定服务责任,41,三、 C+语言,C与C+的比较

19、C+中的数据类型 C+程序框架 类和对象 类的声明、实现、继承、多态性 举例,42,C 语 言,C语言的优点: 与硬件无关,可移植性强 语言简洁,使用方便 丰富的运算符和数据类型 可直接访问内存地址 能进行位操作 目标代码质量高,运行效率高,43,C语言的弱点: 检查机制弱,编译时不能发现编程错误 面向过程的语言,没有支持代码复用的机制 很难控制大规模程序的复杂性,44,C+ 语 言,是C的超集,保持了与C的兼容性 继承了C语言高效性、灵活性的特点 扩充了对面向对象程序设计和高层次问题抽象方法的支持,是面向对象程序设计语言之一 完善了C语言的类型检查、代码重用、数据抽象机制,便于大规模软件开发

20、 既反映了结构化程序设计方法,又反映了面向对象程序设计方法,45,#include / 预编译命令 void main() / 主函数开始 cout “Hello the world!” endl; / 主函数结束,一个简单的C+程序的例子,C+中提供的iostream库可以完成对输入输出流的操作,“流”(stream)就是简单的字符序列。在C+中用cin,cout和cerr来定义键盘输入类、屏幕输出类和错误信息输出类。endl用于换行并清空流。如: cin a; cout “输入的数据为” a endl;,46,基本数据类型,构造数据类型,整型(int) 实数型 字符型(char) 空类型(

21、void) 布尔型(bool),引申数据类型,结构化数据类型,指针(*) 引用(&),数组() 结构(struct) 联合(union) 枚举(enum) 类(class),浮点型(float) 双精度型(double),C+中的数据类型,47,引用 对形参a,b的操作等价与对实参的操作。,48,C+程序结构,C+源代码一般都由若干类或函数组成。为了便于管理,一般把不同的类放在不同的文件中,对于类的声明和实现也分别放在对应的.h(或.hpp)和.cpp文件中。由于文件较多,所以为了便于管理,一般的集成开发工具都会提供工程(Project)管理功能来管理这些文件,对源文件进行编译和链接。,49,

22、50,为防止重复包含(多次包含同一头文件,造成重复定义)和嵌套包含(互相包含)造成的错误,应该在头文件里加上如下预编译命令。例如,对于test1.h#ifndef _INCLUDE_TEST1_H_ #define _INCLUDE_TEST1_H_ / / test1.h的内容 #endif,说 明,51,class 类名 public: 公有数据和函数 protected: 受保护数据和函数 private: 私有数据和函数 ;,类的声明,注意要有分号,52,class People / People类的声明 public: / 公有成员People(); / 构造函数People(cha

23、r* name, int age, char sex);People(); / 析构函数char* GetName(); / 查询姓名int GetAge(); / 查询年龄char GetSex(); / 查询性别bool SetName(char *n); / 设置姓名bool SetAge(int age); / 设置年龄bool SetSex(char sex); / 设置性别 private: / 私有成员 protected: / 保护成员char m_strName20; / 姓名,字符串数组int m_nAge; / 年龄,整型char m_cSex; / 性别,字符型 ;,类

24、的声明举例People类,53,类名是有效的标识符,不能是关键字(保留字)数据成员在声明时不能进行初始化数据成员不能是正在声明的类,但可以用指针访问控制public, private, protected可以以任意次序出现,并可重复多次,有关类的声明,54,类的成员函数中有两个函数是特殊的,就是构造函数和析构函数,它们没有返回值,且一般不直接调用这些函数,而是在对象建立和撤销时分别被隐式调用的。 构造函数的函数名要与类名相同,在创建对象时被调用。可以不定义构造函数,编译程序会自动生成一个缺省的构造函数。 析构函数的函数名是在类名前加上一个“”。同上,也可以不定义析构函数,编译程序会自动生成一个

25、缺省的析构函数。,构造函数和析构函数,55,在类的构造函数中,一般要完成一些初始化的任务。例如将一些指针赋值为NULL,给一些变量赋初值,或者为一些指针分配空间等。还可以利用函数的重载,声明并实现多种构造函数,以完成不同的初始化任务。(参见People类) 在类的析构函数中,一般要进行一些收尾工作,如空间的释放。如对于为指针分配的空间,要加以释放,等。,构造函数和析构函数,56,public: 公有成员,可以被任何函数访问(即可以从类的外部进行访问)。 private: 私有成员,只有类成员函数和友员类可以访问。 protected: 保护成员,只有类成员函数、派生类、友员类可以访问。 缺省方

26、式为private,类成员访问控制,57,People:People() / 构造函数 / 函数体开始/ 初始化名字为空串memset(m_strName, 0, sizeof(m_strName);/ 初始化年龄为0m_nAge=0;/ 初始化性别为0m_cSex=0; / 函数体结束People:People() / 析构函数,类的实现People类,58,People:People(char* name, int age=0, char sex=0)/ 构造函数 / 函数体开始if (name!=NULL) / 初始化m_strnamestrcpy(m_strName,name);els

27、e / 如果name为空,则初始化m_strname为空memset(m_strName, 0, sizeof(m_strName);if(age=0) / 0表示未赋值 ,59,/ 查询姓名的成员函数 char* People:GetName() return m_strName; / 返回姓名 / 查询年龄的成员函数 int People:GetAge() return m_nAge; / 返回年龄 / 查询性别的成员函数 char People:GetSex() return m_cSex; / 返回性别 / 用于设置的成员函数的实现不在此列出 / ,60,void main() / 主

28、函数 People A; / 声明类People的对象APeople B(“Li Si“);/ 声明类People的对象B,参数“Li Si“/ 声明类People指针,并构造实例People* C = new People(“Zhang San“, 20, M);A.SetName(“Wang Wu”); / 对对象A设置名字cout GetName() GetAge() GetSex() endl endl;delete C; / 释放指针C所指的空间 ,61,As name:Wang Wu As age:0 As sex:0Bs name:Li Si Bs age:0 Bs sex:0C

29、s name:Zhang San Cs age:20 Cs sex:M,程序运行结果,62,/ 声明类People的对象A,调用没有参数的构造函数 People A;/ 声明类People的对象B,参数“Li Si“ People B(“Li Si“); / 声明类People指针,并动态构造实例 People* C = new People(“Zhang San“, 20, M); 或: People *C; C = new People(“Zhang San“, 20, M);,类对象的声明,63,People A(“Zhang San”),B; / 声明People的对象A和B B =

30、A; / 用A初始化对象B,对象的复制,说明:这种对象复制可以将A的所有数据成员的值赋给B,如果对象的数据成员中不存在指针,则没有问题,但如果其中含有指针,则这种方式只是简单地把指针所指向的内容的地址复制过来,并没有复制其所指的内容。这可能并不是用户所期望的。这要通过自定义的复制策略来实现:拷贝构造函数和重载运算符“=”。,64,继 承,继承是面向对象程序设计的重要特点之一。它描述了类之间的is-a的关系。如果类B继承类A,则称类A是类B的基类(或父类),类B是类A的派生类(或子类)。,65,class Student : public People public: Student(); /

31、构造函数Student(); / 析构函数int GetNumber(); / 查询学号bool SetNumber(int n); / 设置学号private: protected: int m_nNumber; / 学号 ;,举例Student类,类声明第一行后面的“: public People”指明了Student类继承自People类。public是继承访问控制,用于指明继承成员在子类中的访问控制。这样,类People中的一些成员就会被Student类自动继承了。,66,继承成员的访问控制,67,继承成员的访问控制,父类中的私有成员不能继承 继承访问控制为public时,继承父类的访

32、问控制继承访问控制不是public时,子类中继承成员的访问控制与继承访问控制相同,68,类型兼容性,C+语言中,允许且仅允许公有派生类兼容基类。这就是说,子类的对象可以赋值给父类的对象,指向父类的指针可以指向子类。反之则不正确。,例:class Child:public Father Father* father; / 声明Father对象指针 Child* child; / 声明Child对象指针 / 动态创建对象 / father = child; / 正确 child = father; / 错误,69,多态性,如前所述,在程序中同一符号或名字在不同情况下具有不同解释的现象称为多态性。在

33、面向对象程序设计语言中,由程序员设计的多态性由两种基本形式:编译时多态性和运行时多态性。运行时多态性是面向对象程序设计语言的一大特点。,70,编译时多态性,编译时多态性是指在程序编译阶段即可确定下来的多态性,主要通过使用重载机制获得,重载机制包括函数重载和运算符重载两大类。在声明函数原型时只要形式参数的个数或类型不同,就可以使用相同的函数名。只有返回值的不同同名函数,并不认为是不同的函数。运算符重载允许程序员重新定义C+语言已有的运算符。,71,函数重载,int Add(int a, int b); / 整数加法 float Add (float a, float b); / 单精度加法 do

34、uble Add (double a, double b);/ 双精度加法int Abs(int a); / 整数的绝对值 float Abs(float a); / 单精度数的绝对值 double Abs(double a); / 双精度数的绝对值,对于普通函数和类成员函数都可以进行函数的重载,构造函数也可以重载。,72,运算符重载,运算符可以理解为函数,一元、二元运算符分别认为是具有一个、两个参数的函数。那么,对一个n维矢量类,我们可以重载“”,“”运算符,以实现矢量的加减运算。例 class Vector: Vector operator+(const Vector/ 赋值,73,运行时

35、多态性是指必须等到程序动态运行时才可确定的多态性,主要通过继承结合动态绑定获得。这与类的继承密切相关。因为存在类型的兼容性,所以有些函数只有在运行时才能确定是调用父类的还是子类的函数。在C+中,使用虚函数(Virtual Functions)来实现。,运行时多态性,74,虚成员函数主要用于要在子类(派生类)中重新定义此函数。virtual只需要在父类中定义,子类中对应的函数会默认为虚函数。子类中重新定义的函数必须与父类中的函数参数和返回值相同。不过,只有返回值不同,不会被认为与原函数不同。,虚成员函数 virtual,75,class A / 声明类A public: / 公有成员virtua

36、l ShowData(); / 虚函数,显示数据 protected: / 保护成员int m_nData; / 数据成员 ;class B: public A / 声明类B,继承A public: / 公有成员virtual ShowData(); / 虚函数,显示数据 ;,76,void main() A* a = new A(), *c;/声明A类指针a,c,并创建a对象B* b = new B(); /声明B类指针b,并创建对象c = a; c-ShowData(); / 调用A类的函数 c = b;c-ShowData(); / 调用B类的函数 ,如果ShowData()不是虚函数,

37、则不管c指向父类还是子类的对象,所调用的都是父类的函数。,77,1 虚函数仅适用于有继承关系的类对象,所以只有类的成员函数才能说明为虚函数。 2 静态成员函数不能是虚函数 3 内联(inline)函数不能是虚函数 4 构造函数不能是虚函数 5 析构函数可以是虚函数,虚函数的限制,78,【1】面向对象系统分析与设计Ronald J. Norman著,周之英等译,2000 【2】面向对象程序设计基础,李师贤,李文军,周晓聪 编著,高等教育出版社,1998 【3】 C+语言和面向对象程序设计(第二版),宛延闿 【4】 C+讲义,徐玉华、殷人昆老师提供 【5】 http:/ 【6】面向对象方法综述,陈

38、小群,参考资料,79,举例:猴子选大王,包含以下文件: Monking.cpp 主程序 Mongkey.h Monkey类的声明 Mongkey.cpp Monkey类的实现 Ring.h Ring类的声明 Ring.cpp Ring类的实现,80,/* /* Monkey.h * /* #ifndef _INCLUDE_MONKE_H_ #define _INCLUDE_MONKE_H_ class Monkey public:Monkey(int n=8,int begin=1,int m=3) / 构造函数numofMonkey=n; / 猴子数目beginPos=begin; / 起始

39、位置interval=m; / 报数间隔void Initial(); / 初始化函数void Getking(); / 得到猴王 protected:int numofMonkey; / 猴子数目int beginPos; / 起始位置int interval; / 报数间隔 ; #endif,81,/* /* Ring.h * /* #ifndef _INCLUDE_RING_H_ #define _INCLUDE_RING_H_ struct Mon / 结构声明 int code; / 整型,猴子编号Mon *next; / 结构指针,指向下一只猴子 ; class Ring / Ri

40、ng类声明,循环链表 public:Ring(int n); / 构造函数void Count(int m); / 报数void PutMon(); / 输出当前猴子void ClearMon(); / 删除当前猴子Ring(); / 析构函数 protected:Mon *pBegin; / 链表头Mon *pivot; / 相邻的上一个猴子Mon *pCurrent; / 当前猴子 ; #endif,82,/* /* Monking.cpp * /*#include #include “Monkey.h“void main() / 主函数 / 主函数开始Monkey monkey; / 声明一个Monkey对象monkey.Initial(); / 初始化monkey.Getking(); / 得到猴王 / 主函数结束,83,结 束,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报