C++ 语言 与 面向对象程序设计
description
Transcript of C++ 语言 与 面向对象程序设计
C++ 语言与
面向对象程序设计
贵州大学计算机科学系
课程安排课程安排上课:上课:第 第 1 ~181 ~18 周 星期三(单),五周 星期三(单),五 主讲教师:张永军主讲教师:张永军
上机:上机:第 第 3 ~183 ~18 周 星期四周 星期四 (( 晚晚 )) 指导教师:张永军指导教师:张永军
课程(综合)设计课程(综合)设计根据课程安排)根据课程安排)
教学目标教学目标 了解面向对象方法的基本概念了解面向对象方法的基本概念
了解面向对象程序设计方法的基本思想和特了解面向对象程序设计方法的基本思想和特
点点
能够利用面向对象技术,使用 能够利用面向对象技术,使用 C++C++ 语言工语言工
具进行面向对象编程具进行面向对象编程
C++ 语言与面向对象的设计
第 1 章 面向对象程序设计概论
1. 1 程序设计技术的发展
1.1.1 面向机器的语言
机器语言是硬件逻辑设计所实现的机器指令的集合,也就是由硬件所能实现的语义序列集合。其表现形式为能被机器直接接收的二进制代码序列。
汇编语言是机器语言的直接符号映射。它用人类能够理解的助记符号来表示机器指令、寄存器、存储器地址等物理概念,以提高程序的可读性。
早期的计算机应用以问题求解为主要目标,算法的设计和实现是程序设计活动的焦点。注重追求算法的效率,并不特别注意算法与数据结构的依赖关系,算法和数据处于相对独立的状态。
1.1.2 面向问题的语言
FORTRAN 语言 引入了程序设计语言中程序控制结构、符号命名机制等一些最重要的基本概念。例如:命名子程序、变量作为存储单元的抽象以及数组的概念等。
随着编译技术的突破产生的高级语言用接近人类习惯的自然语言或数学语言表达问题、编制程序。
高级语言通过引入一些抽象概念,屏蔽机器底层的差异,使它独立于机器,不但有效地提高了程序设计的效率,也带来了程序的可移植性。
由于算法总是以过程(子程序)的形式出现,面向问题的程序也叫做过程化程序设计。
模块化程序设计
FORTRAN 语言还引入了独立编译的模块和可重用子程序库的概念,这种技术后来被称为模块化程序设计。
模块化的思想是将应用程序划分若干个规模适度的模块,每个模块独立命名、独立编译,最后通过连接程序形成可招待的应用程序。
模块化程序设计带来了以下一些重要概念:
模块内信息隐藏,一个模块中的变量可以与其它模块中的变量同名而不至于产生混淆;
模块间通过全局环境共享数据;
模块间通过外部变量、公共变量实现通信。 模块化程序设计倡导的这些概念被证明是程序组织和管理有效的基本手段,在以后程序设计技术发展的各个阶段得以延续和发展。
1.1.3 面向数据结构的程序设计研究证明,仅用顺序,分支,循环三种
基本控制结构即能构造出任何单入口、单出口的程序块。
这些研究结果与模块化的概念相结合,形成了采用自顶向下、逐步求精的设计步骤和单入口单出口基本控制结构的结构化程序设计方法。
Pascal 语言和 C 语言都是结构化程序设计语言。同时它们也是过程化程序设计语言。 Pascal 语言用过程来组织程序。
C 语言用函数来组织程序。
过程 (Procedure) 和函数 (Function) 是子程序(Subroutine) 的两种具体形式。过程没有返回值。函数函数有且只有一个返回值。
结构化程序设计的研究中有一个重要的结论,表示为公式:程序 = 算法 + 数据结构,强调算法对数据结构的依赖性,体现了一种数据结构为中心的观念。
大多数结构化语言都具有定义新的数据类型的功能,如 C 语言中枚举 (enum) 、结构 (struct) 类型等。这有利于比较准确地描述待求解问题中的实体,并保证数据的一致性。
数据库技术和数据库管理语言也体现了程序设计以数据结构为中心的鲜明特色。
以数据结构为中心的蔽端:
整个程序中许多重要的过程和函数的实现依赖于一个或几个关键数据结构,如果关键数据结构中的一个或几个数据有所改变,则会波及到整个系统,许多过程和函数必须重写。这是不利于程序的维护和扩展的。
1.1.4 面向对象的程序设计
面向对象的程序设计方法继承了结构化、过程化、模块化等方法的所有积极成分,创造性地引入了“对象”这一构建程序的基本构件。
对象是由数据结构和对数据结构的操作或运算封装而成的一个整体。
封装使得算法和数据结构的关系由算法对数据结构单方面的依赖变成了相互依存的关系。
在面向对象的软件系统中,一个个不同类型的对象相互作用,自底向上构建起整个程序系统。
它以 “对象 = 数据结构 + 算法, 程序 = 对象 + 对象… + 对象”
取代了“程序 = 数据结构 + 算法”的传统程序设计模式。因而引起了一场程序设计观念的革命。
面向对象方法采用数据抽象与隐藏、层次结构体系,动态绑定等概念和措施,提供一种模拟人类认知方式的软件系统建模方法,带来了系统的安全性、可扩充性、代码重用、易维护等人们期待的特性。
OOPL 的来源与发展
OOPL ( Object Oriented Programming Lan
guage 面向对象程序设计语言)20世纪 60年代 , 由挪威计算中心 Ole Dahl 和 Kryste
n Nygaard. 主持开发的 Simula 67 被公认为是面向对象语言的先驱。
20世纪 70年代,由美国国防部资助开发的 Ada 语言,以它对抽象数据类型的支持,而在面向对象语言发展中占有重要地位。
Simula 67 和 Ada 被看作是 OOPL 的两个直接的“祖先”,一个引入“模拟”,一个引入“抽象”。
20世纪 70年代到 80年代 , 美国 Xerox 公司, Palo Alto 研究中心( PARC )的 Alan Kay, Adale Goldberg 和 Dan Ingans 等人主持开发的 Smalltalk 语言正式使用了“面向对象”这个术语。它的问世标志着面向对象程序设计方法的正式形成。
1981年推出的 Smalltalk-80 是 Smalltalk 语言最完善的版本。它是第一个能够实际应用的纯的面向对象语言。在Smalltalk_80 中类和对象不仅仅是语言成分,而且是交互式程序设计环境的组成部分。
80年代中期, Simular 67 、 Smalltalk_80 等语言的影响仅仅局限在学术界。面向对象语言对计算平台的特殊要求使这些语言难于被软件开发商和程序员接受。
贝尔实验室的 Bjarne Stroustrup 及其研究小组在当时最受欢迎的 C 语言基础上开发的 C++ 语言,引入了对面向对象概念的支持。
C++ 语言以其与 C 语言兼容、高运行效率等优良特性,使面向对象程序设计技术受到软件工业界的广泛关注,使之进入一个全面发展的时期。尽管 C++只能算作一种混合式面向对象语言。但是正是由于大量 C 程序员通过 C++的帮助才迅速掌握了面向对象的概念和方法,全面促进了面向对象技术的应用,从而使 C++ 成为最有影响的面向对象语言,甚至许多人把 C++当作面向对象的代名词。
面向对象技术的流行进一步促进了面向对象语言的繁荣。 90年
代涌现出了一大批实用的面向对象语言,如Object Pascal、 Eiffel 、 Java 等等。
Java 语言是由 Sun Microsystem 公司推出的一种纯面向对象语言。 Java从 C++ 语言中继承了大量的语言成分,抛弃了 C++ 语言中冗余的和容易引起问题的功能,它将面向对象、平台无关性、稳定性、安全性等集于一身,提供了一个良好的程序设计环境,因而成为适合于分布式计算的程序设计语言。
Java 语言于 90年代中期的迅速流行与它定位于当时迅速发展的Internet 的 WWW 应用开发有关。展示了面向对象技术与分布式计算结合的重大前景。
后面向对象时代的计算机语言
程序设计语言 : C++, Java
脚本语言 : Java Script , VBScript
标记语言 : SGML, HTML, XML
样式语言 : CSS, XSL
建模语言 : UML
1. 2 面向对象的基本概念
1.2.1 面向对象的目标
建立一个既能在计算机系统中自然地表示客观世界的问题、又能够超越程序复杂性障碍的程序设计模型。
面向对象方法通过对客观世界和问题世界的直接模拟,建立较为准确、自然的程序设计模型,从而获得信息处理的更高性能。
计算机世界(程序空间)
主观世界(问题空间)
客观世界(真实空间)
图 1.1 客观世界、主观世界和计算机世界
从计算机软件设计的角度,引入类和对象的概念,将客观世界和主观世界中的实体和问题直接映射到计算机世界的程序空间。这就是面向对象方法的基本出发点。
分类:从大量相似的实体中归纳、抽象出相同特征,为辨识新的个体形成参照模式。
对象和类的概念是面向对象技术中最重要的概念。对象和类分别对应认识论中实体和对实体的分类。
实体:客观世界或问题世界中可直接或间接观察的个体。
物理实体:一本书,一辆汽车观念实体:一笔帐, 2008 北京奥运会
抽象是对具体事物简化描述的过程,它强调了系统的某些主要特性面而忽略了其它特性。
一个分类至少应抽象出两个方面的特征,一是数据特征,一是行为特征。
比如人类,有年龄、性别、身高、体重,健康状态、所属工作单位等特征,这些特征可以用一些具体的数值来描述,属于数据特征。数据特征又称属性或状态,是区分不同个体的依据。
人类还有行为特征,如吃饭、走路、学习、成长等。行为特征是同一个类的所有个体共有的。
1.2.2 面向对象语言中的类和对象
在面向对象语言中通常以下面描述的方式来定义类:
类定义:类名 1{
私有数据: 数据类型 1 :属性数据 1; 数据类型 2 :属性数据 2; 数据类型 3 :属性数据 3; …
公有方法: 方法(行为) 1; 方法(行为) 2; …};
类是一个形体定义 , 它 对 一个 数 据特性 和 方 法 特性 的 封装体 进 行 说 明。 类 定义中 包 含 两 类成 员 :数据 成 员 和 方法 成 员。类 的 定 义 为该 类 的对象提供了创建的模式。
根据已定义的类,可以按下述方式创建对象:
类名 1:对象名 1,对象名 2;类名 2:对象名 3;…
对象是类的实例。
对象是按照类提供的模板进行的实体定义,它将为对象在内存中分配实际的存储空间。在程序中对象间相互通信和作用,共同完成程序功能。
类与对象的关系就是数据类型和该类型变量的关系。如:
int x. y; float f1, f2; clock t1, t2; Complex c1, c2, c3;
数据类型是不同形式的信息在内存中分配方式的基本约定,是构造程序的基础。
每种程序设计语言中都定义了自己的基本数据类型集合和利用基本数据类型定义的扩展数据类型。
常量、变量甚至函数都有自己的数据类型。
C 语言等结构化程序设计语言还为用户提供了自定义数据类型的手段。
从抽象数据类型的观点看类和对象
一个数据类型的定义包括一个值集和一个作用于该值集的操作集。
如 C 语言中的 int 型(整型),其值集为 A={ n| n N, -32768≤n≤+32767 }∈ , 其操作集是加、减、乘、整除、取模等等。
面向对象语言中的类是一种新的用户自定义数据类型—“类”类型。
类的所有数据成员形成类类型的值集,类的所有方法成员形成类类型的操作集。
以这个观点来看,对象就是“类类型”的一个实例,通常以变量的形式出现。
如果定义了一个类名为 book 的类,则创建 book 类的对象 b1, b2 的语法形式:
book b1, b2 ;
和声明基本数据类型变量的语法形式:
int a, b ;
double x;
完全一样。可以像使用整型变量 a 、 b ,双精度型变量 x 一样使用 book 型变量 b1 、 b2 。
类类型能像内部数据类型一样工作。区别在于程序员定义的类是为了描述具体问题,模拟问题空间中的对象。实际上,程序员通过增添自己所需要的新类对程序设计语言本身进行了扩展。
对象中所包含的方法实际上就是过程或函数,方法一定属于某个特定类的对象,是实现对象功能算法的代码块。
在编写方法实现代码时仍应遵循结构化的原则,使用单入口单出口的几种基本控制结构。
关于“方法”
在结构化程序设计中,过程是由使用者显式调用的独立实体,对于相同的输入参数,每次过程调用有相同的结果。
而在面向对象程序计中,过程作为对象的方法,不再是独立存在的实体,而是对象功能的体现。这使得对象可以理解为一台自动机。对象的私有数据可以看作自动机的状态。对象的状态只能由对象的方法改变。
对象状态的改变是通过向对象发送消息来实现的。所谓发送消息,就是从对象外部调用对象的公有方法。
发送消息不同于一般的过程调用,发送消息只是触发自动机,同样的输入参数时,可能因为自动机状态不同而有不同的输出结果。
1. 3 类的基本特性
1.3.1 封装性 (Encapsulate)
类的三大基本特性:封装性、继承性和多态性
类是数据成员和方法成员的封装体。封装不仅仅是将数据和方法这两种不同的语言成分捆绑在一起,它还具有数据隐藏的机制。
数据隐藏是通过限制数据的访问权限实现的。一个类中的数据通常被声明为私有的。不允许从类的外部直接访问。
封装和数据隐藏不仅防止了数据从外部破坏的可能性,更保证了对象对于其边界以外的外部世界作为一个自足的、透明的实体存在。
引入对象的封装机制的目的是将对象的使用者和设计者区分开来。
类的公有方法是对象向对象的使用者开放的接口( Interface )。
从对象与其外部世界的关系来看,对象是一个在系统中负有一定责任的服务器。外部世界的事件,如人机交互、其它对
象的状态改变等等,可以看作请求对象服务的客户。
对象通过公有方法,向外部声明自己提供哪些服务,每个方法的参数说明了怎样使用这些服务。
1.3.2 继承 性 (Inheritance)
人类对于客观事物的认识过程是没有止境的。在分类问题上也是这样,随着认识水平的提高,原有的类需要划分成若干个子类,子类又可以划分子类的子类,…。这种划分最终形成一个树状层次体系结构。
面向对象程序设计中通过类的继承性,能够很好地模拟这种分类方式。
面向对象中类的继承性描述两个类之间的一种特殊关系,即上面所说的“父 -子关系”。面向对象语言中允许利用一个已定义的类来定义一个新类,通过这种利用,形成两个类之间的继承关系。这个已定义的类称为基类,新定义的类则称为它的子类。子类除了包含基类的所有成员之外,又增加了自己特有的新成员。
特殊类
一般类一般类
特殊类
( b )类的特征集合( a )类的实例集合
图 1.2 一般类与特殊类的关系
在由一个类划分出子类的过程中,子类必须具有其父类的所有特征,同时又具有父类中其它成员所没有的新特征。从成员集合来看,父类包含了子类的所有成员。从各自信息量的多少来看,有“子大于父”的特点,因为要描述一个子类,必须添加有别于父类中其它成员的新的信息。类间的这种“父子关系”反映了类的一般性和特殊性,也称为“一般 -特殊关系”。
子类定义的伪代码形式如下:
新类声明:子类名 1 继承自: 基类名 1{ 数据成员; … 方法成员; …}
子类对象在内存中所占的存储空间一定大于其父类。继承机制使得子类对象创建时首先要拷贝父类对象的所有成员,既包括数据成员也包括方法成员,不管是公有的还是私有的。在为拷贝而来的成员分配内存储空间之后,再为子类的特有成员分配存储空间。一个子类对象的封装实体,在程序运行时与其父类对象是完全独立的。子类对象在创建时对父类对象的拷贝提供了一种高效的源代码级的软件重用方法。
继承又分为单继承和多继承。单继承指子类只由一个基类继承而来。
当一个子类有不止一个基类时则称为多继承。
多继承的例子在生活中并不少见。比如一个医学院的在职研究生可能既是医生又是学生,他既是医生类的实例又是学生类的实例。
1.3.1 多态 性 (Polymorphism)
多态性是面向对象技术真正的优势所在。关于多态性有以下几种等价描述:
多态性:指程序对同一名字或符号在不同情况下做出不同解释的能力。
多态性:为同一个函数和运算符定义多个不同的执行版本。
不同对象可以调用相同名称的函数,并导致完全不同的行为( behavior )的现象称为多态性。
程序编译时实现的多态性属于静态的多态性。静态的多态性又叫重载。
编译时如果遇到名称相同但参数不同的函数,编译系统把它们看作不同的函数,分别联系到不同的执行代码块的首地址。程序运行时根据同名函数的参数形式不同而知道应该执行哪一个代码块。
将程序名与其对应的代码块联系起来的行为称为绑定( binding )。编译时完成的绑定称为静态绑定。
程序运行时体现的多态性称为动态的多态性(动态绑定)。
在程序运行期才完成的绑定称为动态绑定。
动态绑定带来的多态性使不同对象中的同名函数在程序运行中遇到调用请求时自动选择正确的执行代码。动态绑定技术为程序对象通信提供了动态消息传递机制。动态实现的多态性使程序具有识别外部事件的智能,使面向对象的程序能够很好地模拟客观世界中各种真实事件随机发生的事实。
本章重要概念和单词:
重用( Reuse )类和对象( class & object )面向对象( object_oriented )封装( Encapsulate )继承( Inheritance )多态( Polymorphism )接口( Interface )绑定( binding )