09_Class

面向对象基础 {面向对象的基本特点\类和对象的基本操作\ 构造函数和析构函数\ 类的组合\ 结构体与联合体\ 类的 UML 描述} 类和对象基本操作 {类的声明\类的成员:数据与函数\对象的创建\ 对象成员的访问\ 成员函数的定义,内联成员函数} 构造函数和析构函数 {构造函数:数据初始化\ 构造函数的重载\匿名对象\对象作为函数参数\ 复制构造函数\析构函数} 类 的 组 合 {组合类的初始化\常量和引用的初始化\ 前向引用声明} 结构体与联合体 {结构体\ 联合体} 类的 UML 描述 {UML:Unified Modeling Language 面向对象建模语言,通过图形的方式描述面向对象程序设计}
展开查看详情

1.第九讲 类与对象 ( I ) 面向对象基础

2.2 面向对象基础 面向对象的基本特点 类和对象的基本操作 构造函数和析构函数 类的组合 结构体与联合体 类的 UML 描述

3.3 高级语言发展 第一代:对数学表达式有很强的运算处理能力 代表有 Fortran , Algol 60 第二代:重点是如何有效地表达算法 代表有 Pascal , C 第三代:引入抽象数据类型的程序设计语言 代表有 Ada 第四代:面向对象程序设计语言 代表有 Simula67 , Smalltalk80 、 C++ 、 Java

4.4 为什么面向对象 出发点: 更直观 地描述客观世界中存在的事物(对象) 以及它们之间的关系 面向对象基本特点 是高级语言 将客观事物看作具有 属性 (数据)和 行为 (函数)的 对象 通过抽象找出同一类对象的共同属性和行为,形成 类 通过类的继承与多态实现 代码重用 目的:通过提高代码的 可重用性 ,降低软件的开发成本和 维护成本,从而大大提高程序员的生产力 面向对象的几个主要特征: 抽象、封装、继承和多态

5.5 抽象 抽象 :对具体问题(对象)进行概括,抽出这一类对象的公共性质并加以描述的过程。 首先注意的是问题的 本质及描述 ,其次是 实现过程或细节 抽象包括: 数据抽象 和 行为抽象 - 数据抽象: 描述某类对象的属性或状态(对象相互区别的物理量) - 行为抽象(功能抽象、代码抽象): 描述某类对象的共同行为或功能特征 抽象的实现: 类

6.6 例:时钟的抽象 例: 时钟的描述 数据抽象: int hour , int minute , int second 行为抽象: showTime (), setTime ()

7.7 封装 封装 :将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,即将数据与操作数据的函数进行有机结合,形成 “ 类 ”,其中数据和函数都是类的 成员 。 封装可以增强数据的安全性,并简化编程。用户不必了解具体的实现细节,而只需要通过外部接口,以特定的访问权限,来使用类的成员。

8.8 class Clock { public: void setTime (int NewH, int NewM, int NewS); void showTime (); private: int hour , minute , second ; }; 例:时钟的抽象 例: 时钟的描述 数据抽象: int hour , int minute , int second 行为抽象: showTime(), setTime() 时钟类 public 和 private 用于指定成员的不同访问权限 此处的分号不能省略!

9.9 继承 与多态 继承 : C++ 提供了继承机制,允许程序员在保持原有类特性的基础上,进行更具体、更详细的说明。 多态 :同一段程序能处理多种类型对象的能力。在 C++ 中,多态性是通过强制多态(如类型转换)、重载多态(如函数重载、运算符重载)、类型参数化和包含多态(如虚函数、模板)。

10.10 类的声明 类的成员:数据与函数 对象的创建 对象成员的访问 成员函数的定义,内联成员函数 类和对象基本操作

11.11 类和对象 类 是 C++ 面向对象程序设计的核心! 类与函数的区别 函数 是 结构化(过程式) 程序设计的基本模块,用于完成特定的功能。 类 是 面向对象 程序设计的基本模块,类将逻辑上相关的 数据 与 函数 封装,是对问题的抽象描述。 类 的集成程度更高,更适合大型复杂程序的开发 类的使用:先声明(定义)后使用

12.12 类的声明 类的声明(定义) class 类的名称 { public: // 访问属性 公有成员(外部接口) private: 私有成员 protected: 保护型成员 } ;

13.13 类的声明 class Clock { public: void setTime (int NewH, int NewM, int NewS); void showTime (); private: int hour , minute , second ; }; Clock x; // 声明对象 Clock y;

14.14 类的成员 类 的成员: 数据成员(描述问题的属性) 函数成员(描述问题的行为 / 操作 / 功能 ) 成员的访问属性(权限控制): public , private , protected public (公有类型、外部接口) : 任何外部函数都可以访问公有类型的数据和函数 private (私有类型) : 只能被本类中的函数成员访问,任何来自外部的访问都非法 protected (保护类型) : 与私有类似,区别在于继承过程中的影响不同

15.15 class Clock { public: void setTime ( int NewH , int NewM , int NewS ); private: int hour , minute , second ; public: void showTime (); }; 几点说明 如果没有指定访问属性,则缺省为私有类型 一般情况下,数据成员建议声明为私有类型 一个类如果没有任何外部接口,则无法使用 在定义类时,不同访问属性的成员可以按任意顺序出现,修饰访问权限的关键字也可以多次出现,但一个成员只能有一种访问属性! 一般将公有类型的成员放在最前面,便于阅读 例: 注:声明并没有为 Clock 分配内存,只是告诉编译器 Clock 是什么: 包含哪些数据,有什么功能。

16.16 对象的创建 对象的声明 类的名称 对象名 例: 对象所占的内存空间 只用于存放数据成员 ,函数成员在内存中只占一份空间,不会在每个对象中存储副本 Clock x; Clock y; 声明一个类后,便可将其作为新数据类型来创建变量,即 对象

17.17 对象成员的访问 访问对象的成员的一般方式 对象名 . 数据成员名 对象名 . 函数成员名 ( 参数列表 ) 例: 注: ① 类的成员函数可以访问所有数据成员; ② 外部函数 只能访问公有成员。 myclock.showTime(); myclock.setTime(16,10,28);

18.18 成员函数 类的成员函数的定义 注意:在外部定义时需加上 类的名称 和 两个连续冒号 (作用域分辨符) 例: 数据类型 类的名称 :: 函数名(形参列表) { 函数体 ; } void Clock::setTime(int newH, int newM, int newS) { hour=newH; minute=newM; second=newS; } 可以直接在类内部定义(一般适合简短函数) 也可以在类内部声明,然后在类外部定义(适用复杂函数)

19.19 目的对象 调用成员函数时,需用“ . ” 操作符指定调用所针对的对象,此时,该对象就称为本次调用的 目的对象 。 成员函数可以直接引用 目的对象 的所有数据成员,而无需使用 “ . ” 操作符。 在成员函数中,引用 其它对象 的数据成员和函数成员时,必须使用 “ . ” 操作符。 成员函数既可以访问目的对象的私有成员,也可以访问当前类的其它对象的私有成员。

20.20 形参带缺省值 形参的缺省值 只能在类内部设置 , 不能在类外部的函数定义中设置。 成员函数的形参可以带缺省值 class Clock { public: void setTime (int NewH=0 , int NewM=0 , int NewS=0 ); ... ... };

21.21 内联成员函数 内联成员函数的定义:隐式方式和显式方式 隐式方式:将函数体直接放在类的定义中 class Clock { public: void setTime (int NewH=0, int NewM=0, int NewS=0); void showTime () { cout<<hour<<“:”<<minute<<“:”<<second<<endl; } ... ... };

22.22 内联成员函数 使用内联函数可以减少调用开销,提高效率,但只适合相当简单的函数; 使用显式方式定义内联函数可以保持类定义的简洁 内联成员函数的定义:隐式方式和显式方式 显式方式:在定义函数时加上关键词 inline class Clock { public: void setTime (int NewH=0, int NewM=0, int NewS=0); void showTime (); ... ... }; inline void Clock:: showTime () { cout<<hour<<“:”<<minute<<“:”<<second<<endl; }

23.23 例:类与对象 #include <iostream> using namespace std; class Clock // 时钟类的声明 { public: // 外部接口,公有成员函数 void setTime(int NewH=0, int NewM=0, int NewS=0); void showTime(); private: // 私有数据成员 int hour, minute, second; }; // 成员函数的定义(时钟类成员函数的具体实现) void Clock::setTime(int NewH, int NewM, int NewS) { hour=NewH; minute=NewM; second=NewS; } inline void Clock::showTime() // 内联成员函数 { cout<<hour<<":"<<minute<<":"<<second<<endl; }

24.24 // 主函数 int main() { Clock myClock ; // 定义对象 myClock cout <<"First time: "<< endl ; myClock.setTime (); // 设置时间为默认值 myClock.showTime (); // 显示时间 cout <<"Second time: "<< endl ; myClock.setTime (16,10,28); // 设置时间为 16:10:28 myClock.showTime (); // 显示时间 return 0; } 例:类与对象 ex09_class_Clock01.cpp

25.25 构造函数和析构函数 构造函数:数据初始化 构造函数的重载 匿名对象 对象作为函数参数 复制构造函数 析构函数

26.26 构造函数与析构函数 构造函数: 负责对象初始化 类与对象的关系类似于基本数据类型与普通变量之间的关系 不同对象之间的主要区别:名称与数据 对象的初始化:定义对象时,设置数据成员的值 析构函数: 在特定对象使用结束后,经常需要进行一些清理工作,这部分工作就有析构函数负责 构造函数 与 析构函数 是对象的两个特殊的成员函数

27.27 构造函数 构造函数 构造函数的函数名与类的名称相同; 构造函数没有返回类型,不要带任何数据类型声明; 构造函数在对象创建时会被系统自动调用。 若没有定义构造函数,系统会自动生成一个构造函数 (形参和函数体都为空,如: Clock() { } ) 可以是内联函数, 形参可以带缺省值,也可以 函数重载 对象创建的过程 — 申请内存空间 (只存放数据成员) — 初始化:调用构造函数

28.28 class Clock { public: Clock (int x, int y, int z); // 构造函数 void setTime(int NewH=0, int NewM=0, int NewS=0); void showTime(); private: int hour, minute, second; }; // 构造函数的定义 Clock:: Clock (int x, int y, int z) { hour=x; minute=y; second=z; } ... ... 例:构造函数 构造函数前不能加数据类型或 void !

29.29 int main() { Clock c1(0,0,0); // 声明对象并初始化 c1.showTime(); c1.setTime(16,10,28); Clock c2; // ERROR return 0; } 例:构造函数 ex09_class_Clock02.cpp