C++面向对象(一):面向对象程序设计概述

C++面向对象:面向对象程序设计概述

会有点长,不过读过就全学会喽!!!!!!
会有点长,不过读过就全学会喽!!!!!!
会有点长,不过读过就全学会喽!!!!!!

1.什么是面向对象程序设计

面向对象程序设计方法是通过增加软件的可扩充性和可重 性来提高程序员的编程能力的 。

1.1 面向过程程序设计的基本概念

面向过程的程序设计思想的核心是功能的分解。数据结构和过程的这种分离, 给软件人员 造成沉重的负担。

1.2 面向对象程序设计的基本概念

在面向对象的程序设计 中,着重点在那些将要被操作的数据, 而不是在实现这些操作的过程。数据构成了软件分 解的基础,而不是功能。
不能将数据和相应操作看成两个分离的实体, 而是要把它们作为一个完 整的实体来对待。数据与定义在它上面的用户需要的操作构成一个整体。同时, 数据本身不能被外部程序和过程直接存取。
面向对象程序设计的最大优点就是软件具有可重用性。当人们对软件系统的要求有 所改变时,并不需要程序员做大量的工作, 就能使系统做相应的变化。
类与对象是面向对象程序设计中最重要的概念

2.对象与类

2.1 对象与类的概念

在日常生活中对象就是我们认识世界的基本单元, 它可以是人,也可以是物, 还 可以是一件事。整个世界就是由形形色色的“对象”构成的。例如一辆车、一个球、一个小 学生、一次演出。对象既可以很简单, 也可以很复杂, 复杂的对象可以由若干简单的对象 构成。
对象是现实世界中的一个实体,其特性是:

  1. 每一个对象必须有一个名字以区别于其它对象;
  2. 用属性( 或叫状态)来描述它的某些特征;
  3. 有一组操作,每一个操作决定对象的一种行为。

在日常生活中“, 类”是对一组具有共同的属性特征和行为特征的对象的抽象。例如, 由一个个的人构成人类,而一个人是人类的一个实例。
类和对象之间的关系是抽象和具体的关系。类是对多个对象进行综合抽象的结果, 对象又是类的个体实物,一个对象是类的一个实例。

以面向对象程序设计的观点看, 一个对象是由描述其属性的数 据和定义在其上面的一组操作组成的实体, 是数据单元和过程单元的组合体。类是对一 组对象的抽象,这组对象具有相同的属性结构和操作行为, 在对象所属的类中要说明这些 结构和行为。一个对象是类的一个实例。有了类,才可以创建对象。
现在我们给出类的更精确的定义:类是创建对象的样板, 它包含对创建对象的状态描 述和对操作行为的说明。

在面向对象程序设计中,一个类只在源程序的代码中出现, 而并不会在一个正在内存 运行的程序中出现,即类只是在编译时存在; 对象作为类的实例在运行的程序中出现, 并 占有内存空间,它是在运行时存在的实体。所以一个类实际上是一种新的数据类型, 当我 们要使用一个新的数据类型时,首先要在源程序中说明, 而说明部分的代码是不在内存中 运行的。在程序中运行的是该类的对象,对象在内存中分配空间, 程序的计算任务由对象完成。注意,我们在此必须严格区分说明和定义。

2.2 对象的状态

在面向对象程序设计中,对象是类的实例。对象给类以生命, 类想要做的事必须通过 建立对象和在对象上进行操作而实现。创建类的对象的过程也叫实例化对象。对象知道 什么能做和什么不能做,并且有能力修改和维护定义在对象上的数据。
我们可以将对象看成是一个带有状态和行为的活的实体。
对象的状态通常不仅仅是初等的数据类型 (整型、实型、字符型等 ) , 而且许多对象将 另一个对象作为它们状态的一部分。例如,一辆车有发动机、车轮、座位, 发动机是另外一 个对象, 它可以作为车的状态的一部分
C++面向对象(一):面向对象程序设计概述_第1张图片

在面向对象程序设计中,对象之间也需要联系, 我们称为对象的交互。面向对象程序设计技术必须提供一种机制,允许一个对象与另一个对象的交互。这种机制叫消息传递

一般情况下,我们称发送消息的对象为发送者或请求者, 接收消息的对象为接收者或 目标对象。对象中的联系只能通过消息传递来进行。接收者只有在接收到消息时, 才能 被激活,被激活的对象会根据消息的要求完成相应的功能。
消息具有三个性质:

  1. 同一个对象可以接收不同形式的多个消息, 做出不同的响应;
  2. 相同形式的消息可以传递给不同的对象,所做出的响应可以是不同的;
  3. 消息的发送可以不考虑具体的接受者, 对象可以响应消息,也可以不响应。

实际上, 对象之间的消息传递机制对应于面向过程程序设计的过程调用。消息传递并非真的传递信息,它的实质就是方法的调用。只不过方法的调用受到消息的控制, 而过程调用是直接的。
在面向对象程序设计中,消息分为两类: 公有消息私有消息。假设有一批消息同属 于一个对象,其中一部分消息是由其它对象直接向它发送的, 称为公有消息; 另一部分消 息是它向自己发送的,称为私有消息

公有消息私有消息的确定, 与消息要求调用的方法有关。如果被调用的方法在对象所属的类中是在 public 下说明的, 则为公有; 是在 private 下说明的 , 即为私有。当然, 私有消息只能发送调用属于它自己的方法

2.4 类的确定与划分

类的确定与划分是非常重要的, 是软件开发中关键的一步, 划分的结果直接影响到软件系统的质量。如果划分得当,既有利于对程序进行扩充, 又可提高代码的可重用性。

值得注意的是,类的确定和划分并没有统一的标准和固定的方法, 基本 上依赖设计人员的经验、技巧以及对实际问题的把握。一个基本的原则是: 寻求一个大系 统中事物的共性,将具有共性的系统成分确定为一个类。
不能把一组函 数组合在一起构成类。也就是说, 不能把一个面向过程的模块直接变成类。如果简单地 将模块中的函数变成成员函数而使其成为类是错误的。类不是函数的集合
例如,考虑一个包含一组数学函数的模块, 现在我们定义一个类 Mathhelper:

class Mathelper{ 
	public: 
		double sqrt( double aNumber) ; 
		double Power( double aNumber, int raiseto ) ; 
		double Inverse ( double aNumber) ; 
	private : 
	// 任何数据项,也可能没有 
};

确定 Mathelper 为一个类是错误的。问题在于该类中没有需要管理的私有数据。用 户只需要提供参数对成员函数进行调用。这与面向过程的程序设计的函数调用没有根本的区别。

设计类要有一个明确的目标。一个好的类应该是容易理解和使用的。我们不能设计 一个 Color 类来表示鲜花的颜色,但是可以在图形处理系统中将颜色 Color 设计为类。因 为在两个系统中对颜色的要求不同。

3.数据的抽象与封装

面向对象系统中最突出的特性是封装性、继承性和多态性。我们首先来讨论封装性。 封装与数据抽象的概念密切相关。

3.1 现实世界中的抽象与封装

以录音机为例,录音机上有若干按键, 当人们使用录音机时,只要根据自己的需要, 如 放音、录音、停止、倒带等, 按下与之对应的键, 录音机就会完成相应的工作。这些按键安 装在录音机的表面,人们通过它们与录音机交互。我们无法( 当然也没必要) 操作录音机 的内部电路,因为它们被装在机壳里, 录音机的内部情况对于用户来说是隐蔽的, 不可见 的。这就是所谓封装的原理。

以一般观点而言,抽象是通过特定的实例或例子抽取共同性质以后形成概念的过程。 抽象是对系统的简化描述或规范说明, 它强调了系统中的一部分细节和特性, 例如做什 么,而忽略了其它部分, 例如如何做。抽象的描述被称为它的规范说明, 例如录音机的操 作说明书,而对抽象的解释称为它的实现。

3.2 数据的抽象与封装的基本概念

将数据结构和作用于 数据结构上的操作组成一个实体,数据的表示方式和对数据的操作细节被隐藏起来, 用户 通过操作接口对数据进行操作。对于用户来说, 只知道如何通过操作接口对该数据进行操作,而并不知道是如何做的, 也不知道数据是如何表示的。这就是数据的封装。

  1. 数据的抽象是在确定类时强调对象的共同点而忽略它们的 不同点的结果。也可以说,在一个类的说明中我们只表示那些主要特性, 而忽略次要的、 引不起我们兴趣的东西。
  2. 数据的封装则是隐藏了抽象的内部实现细节的结果。封装是将数据抽象的外部接口 与内部的实现细节清楚地分离开。抽象和封装是互补的。

好的抽象有利于封装, 封装的 实体则帮助维护抽象的完整性。重要的是抽象先于封装
可以从下面几点来理解对象的封装:

  1. 对象具有一个清楚的边 界, 对 象的私有数据、成员函数的 细节被封装在该 边 界内;
  2. 具有一个描述对象与其它对象如何相互作用的接口, 该接口必须说明消息传递 的使用方法;
  3. 对象内部的代码和数据应受到保护,其它对象不能直接修改。

从用户(或应用程序员) 的观点看,对象提供了一组服务, 并提供了请求服务的接口。从系统设计员的角度看,封装能够清楚地标明对象提供的服务界面, 而对象的行为和数据 是隐蔽的,看不见的。

3.3 对象的特性

(1 ) 封装性
对象将私有元素和实现操作的内部细节隐藏起来, 并能管理自己的内部状态。外部 只能从对象所表示的具体概念、对象提供的服务和对象提供的外部接口来认识对象。通 过向对象发送消息来激活对象的自身动作,达到施加特定操作的目的。
(2 ) 模块独立性
一个对象是一个独立存在的模块,具有独立的计算能力; 并且其自身的变化不受外界 的干扰,也不会涉及到其它的模块; 模块间的依赖性极小或几乎没有; 各模块可以独立地 成为软件系统的组件,也可以被程序员重用。
(3 ) 动态连接性
对象的动态连接性是指对象通过消息传递机制将对象动态地联系在一起的特性。对 象能接收其它对象发送的消息,也能向其它对象发送消息。通过这种联系, 若干对象可协 同完成某项任务
(4 ) 易维护性
由于对象的功能被“隐蔽”,所以修改和完善的工作都被局限于对象的内部, 不会涉及 到外部,因此使得对象和整个系统变得非常容易维护。

4.继 承 性

4.1 继承的概念

继承在现实生活中是一个很容易理解的概念。例如, 我们每一个人都从我们的父母 身上继承了一些特性,例如种族、血型、眼睛的颜色等, 我们身上的特性来自我们的父母, 也可以说,父母是我们所具有的属性的基础。
以面向对象程序设计的观点来看, 继承所表达的是对象类之间相关的关系。这种关 系使得某类对象可以继承另外一类对象的特征和能力。
若类之间具有继承关系,则它们之间具有下列几个特性:

  1. 类间具有共享特征( 包括数据和程序代码的共享) ;
  2. 类间具有差别或新增部分( 包括非共享的数据和程序代码) ;
  3. 类间具有层次结构。

具体地说,继承机制允许派生类继承基类的数据和操作( 即数据成员和成员函数) , 也 就是说,允许派生类使用基类的数据和操作。同时, 派生类还可以增加新的操作和数据。 例如,子女类可以从父母类继承房子和汽车, 当然可以使用房子和汽车, 还可以对房子进 行再装修

面向对象程序设计为什么要提供继承机制 ? 也就是说, 继承的作用是什么 ?
继承的作用有两个:

  1. 避免公用代码的重复开发, 减少代码和数据冗余;
  2. 通过增强 一致性来减少模块间的接口和界面

继承机制为程序员们提供了一种组织、构造和重用类的手段。

继承机制以相关的关系来组织事物,可以减少我们对相似事物进行说明和记忆的规 模,为我们提供了一种简化的手段。

4.2 继承的分类

继承有两种分类方法,一种是从继承源上分, 另一种是从继承内容上分。
继承源上分,继承分为单继承多继承

  • 单继承是指每个派生类只直接继承了一个基类的特征。
  • 多继承是指多个基类派生出一个派生类的继承关系, 多继承的派生类直接继承了不止一个基类的特征。

继承内容上划分,继承可分为取代继承、包含继承、受限继承、特化继承。

  • 取代继承:例如徒弟从师傅那里学到的所有技术, 在任何需要师傅的地方都可以由徒 弟来替代,这就属于取代继承。
  • 包含继承:例如“柯利狗”继承了“狗”的所有特征, 任何一条“柯利狗”都是一条“狗”, 这就属于包含继承。
  • 受限继承:例如“鸵鸟”尽管继承了“鸟”的一些特征, 但不能继承鸟会飞的特征, 这就 属于受限继承。
  • 特化继承: 例如“运动员”是一类特殊的人, 比一般人具有更多体育特长, 这就属于特 化继承。

4.3 继承与封装的关系

在面向对象程序设计中, 对象具有封装性, 对象之间的联系只能通过消息传递来完 成,对象的私有数据和行为是被隐藏起来的。
继承与封装不但没有实质性的冲突, 而且还 有一定的相似性。

在面向对象系统中, 封装的单位是对象, 也就是说, 把一个属于某一类的对象封装起 来,使其数据和操作成为一个整体。如果该对象所属的类是一个派生类, 那么, 它只要把 从基类那里继承来的操作和数据与自己的操作和数据一并封装起来, 就可以了。对象依 然是封装好的整体,仍然只通过消息传递与其它的对象交互, 而不是直接调用。所以, 一 个对象,无论它是基类的实例, 还是派生类的实例,都是一个被封装的实体。因此, 我们得 出结论:继承机制的引入并不影响对象的封装性。

从另一角度看, 继承与封装还有相似性, 那就是它们都提供了共享代码的手段, 因而 增加了代码的重用性。


继承提供的代码共享是静态的,派生类对象在成为活动的实体以后, 自动地共享其基 类中定义的代码段,从而使基类对象与其派生类对象共享一段代码。
封装提供的代码共享是动态的,例如我们在一个类中说明了一段代码, 那么属于该类 的多个实例在程序运行时共享在类中说明的那段代码。

5.多 态 性

5.1 什么是多态性

多态性也是面向对象系统的重要特性。
现实世界的多态性在自然语言中经常出现。假设一辆 汽车停在了属于别人的车位,司机可能会听到这样的要求“: 请把你的车挪开”,司机在听 到请求后, 所做的工作应该是把车开走。在家里, 一把凳子挡住了孩子的去路, 他可能会 请求妈妈“: 请把凳子挪开”, 妈妈过去搬起凳子,放在一边。在这两件事情中, 司机和妈妈 的工作都是“挪开”一样东西,但是他们在听到请求以后的行为是截然不同的, 这就是多态性。对于“挪开”这个请求,还可以有更多的行为与之对应。“挪开”从字面上看是相同的, 但由于用的对象不同,操作的方法就不同。

**面向对象程序设计借鉴了现实世界的多态性。面向对象系统的多态性是指不同的对 象收到相同的的消息时产生多种不同的行为方式。**例如,我们有一个窗口 (Window)类对 象,还有一个棋子(ChessPiece )类对象, 现在我们来考虑对它们都发出“移动”的消息“, 移 动”操作在 Window 类对象和 ChessPiece 类对象上可以有不同的行为。
C + + 语言支持两种多态性, 即编译时的多态性和运行时的多态性。

  • 编译时的多态 性是通过重载来实现的
  • 运行时的多态性是通过虚函数来 实现的,程序运行的到底是哪个函数版本, 需要在运行时通过对象发送的消息来确定。

5.2 重载的概念

重载一般包括函数重载和运算符重载。函数重载是指一个标识符可同时用于为多个 函数命名,而运算符重载是指一个运算符可同时用于多种运算。也就是说, 相同名字的函 数或运算符在不同的场合可以表现出不同的行为。
下面我们给出一个函数重载的例子。

class A{
public: 
	void Print(int i) {语句段 1 ; } 
	void Print(float f) {语句段 2 ; } 
	void Print( const char * c) {语句段 3 ; } 
	// 其它语句 
} ;

在上面的类定义中我们重载了三个函数, 名字都是 Print 。它们有各自不同的功能, 分别用语句段 1、语句段 2、语句段 3 中的语句实现, 在此略去语句的细节。函数名相同, 而函数实现的功能不同。那么,当有要求使用 Print 函数的消息发送时, 到底应该执行函 数的哪一个呢 ? 这就要看消息传递的函数参数是什么,根据参数来调用不同的同名函数。 例如,发送的消息是 Print( 20 ) , 则执行的是语句段 1,而发送的消息是 Print (”welcome”) , 则执行的是语句段 3。

为什么要使用重载 ?
使用重载的目的是为了更好地表达行为共享, 这种行为共享就 像将相似的操作划分在一起。使用重载可以使程序员在只知道操作的一般含义, 而不知 道操作具体细节的情况下能正确地对某个对象使用一个操作。
另外,使用重载的直接益处是减少了程序员记忆操作名字的负担。

6.面向对象程序设计的语言

面向对象程序设计语 言应该具备下述特征:

  1. 它支持对象的概念( 包括对象所有的特性,如封装等) ;
  2. 它要求对象属于类;
  3. 它提供继承机制。

C + + 是对传统 C 语言进行面向对象的扩充, 是在 C 语言的基础上增加了对面向对 象程序设计的支持, 是在 80 年代早期由贝尔实验室设计的。C + + 又被称为混合型语 言,因为它可以支持传统的程序设计方法, 又支持面向对象程序设计方法, 有丰富的应用 基础和开发环境的支持,因而得到广泛的使用。

你可能感兴趣的:(#,C++面向对象程序设计教程,C++/C)