1 / 34

第 8 章:类和数据抽象 (I)

第 8 章:类和数据抽象 (I). 本章目标:. 1. 理解数据封装和数据隐藏的概念. 2. 学会建立 C++ 中的类(抽象数据类型). 3. 了解类的数据成员和成员函数的属性. 4. 掌握类的数据成员和成员函数的使用. §8.1 引言. 一、面向对象的概念. 面向对象的技术有三个方面:.  面向对象分析 (OOA) [Object_Oriented Analysis].  面向对象设计 (OOD) [Object_Oriented Design].  面向对象程序设计 (OOP) [Object_Oriented Programming].

Download Presentation

第 8 章:类和数据抽象 (I)

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第8章:类和数据抽象(I) 本章目标: 1. 理解数据封装和数据隐藏的概念 2. 学会建立C++中的类(抽象数据类型) 3. 了解类的数据成员和成员函数的属性 4. 掌握类的数据成员和成员函数的使用

  2. §8.1 引言 一、面向对象的概念 面向对象的技术有三个方面: 面向对象分析(OOA) [Object_Oriented Analysis] 面向对象设计(OOD) [Object_Oriented Design] 面向对象程序设计(OOP) [Object_Oriented Programming]

  3. 二、 对象的定义 1. 广义定义:一切事物都是对象 如:树、猫、飞机 问题:这些对象是否具有一种类在的相似? 树:有树枝,树干,树叶,…;可以净化空气,美化环境、… 猫:有毛,四只脚,…; 可以捉老鼠, … 飞机:有机翼,机身,…; 可以飞, …

  4. 2. 对象的定义: 对象是这样一种实体:它具有名字,自身状态,自身功能。 可表示成: OBJ=< ID . MS . DS . MI> 对象可受理的消息的集合 对象的数据结构 对象可受理的操作的集合 对象的标识

  5. 三、面向对象程序设计(OOP) 关键思想:模拟人类认识问题的过程 分类。 具体做法:把系统中的所有资源都看成对象,每个对象把一组数据和一组过程或函数封装在一起。 特点:具有信息隐藏(封装)的功能。

  6. 四、C/C++程序设计的风格差异 • C程序设计:以建立函数模块为主 • C++程序设计: 以建立类为主。(类中既有数据部分,也有函数部分) 类的设计是对象为核心。(从对象的角度来建立类)

  7. §8.2 回顾C语言中的结构数据类型 1. C语言中定义的结构类型,其成员不允许有函数,例如: struct Temp{ int num; float vol; char vh; }; 结构型变量的定义: 在C中:strut Temp exp, *expt; 在C++中:1. struct Temp exp, *expt; 2. Temp exp, expt;

  8. 结构成员的访问: exp.num; expt>num; (*expt).num; 等价的 • 2. C++中的结构类型,其成员允许有函数,例如: • struct Date{ • unsigned int day; • unsigned int month; • unsigned int year; • void plan(int d, int m, int y ); • }; 若有: Date myholiday;  则: myholiday.plan(d, m, y);

  9. 例1: 给定三角形的三条边,计算三角形的面积和周长。 分析:假定三角形的边长分别为:a、b、c。取s=(a+b+c)/2,则三角形面积为: 用两种不同的实现方法来实现: (1) 结构化方法(C/C++均适用) example8_1a.cpp(p.227) (2) 在结构类型中添加成员函数的方法(C++适用) example8_1b.cpp(p.228)

  10. 讨论 • 1.三角形面积的计算形式不同; • area=area(a,b,c); area=TriAng.area(TriAng.a,TriAng.b,TriAng.c); • 成员函数的定义形式:double Shape::area(double a,double b,double c){ ……} • 3. 成员函数area()不允许单独调用。

  11. 讨论 程序存在的问题: 1.对不合法的数据没有检验,有可能导致错误的结果; 例如:如果输入了不合法的值:负数、字符(如:5,t)等,程序仍然会使用不正确的值进行计算。 2.程序可直接修改成员的值; 改进方案: 1. 增加一个函数,用来检验输入数据的合法性。 2. 采用“类”数据类型,加强数据的封装性。

  12. §8.3 C++中的数据类型——类 在C++中,类是一种自定义的数据类型。 一、类型定义 class <类名> { public: //数据成员声明;//成员函数声明; protected: //数据成员声明;//成员函数声明; private: //数据成员声明;//成员函数声明; }; 一般形式:

  13. 例如:定义一个三角形类 class Triangle{ public: Triangle (); void setSide(float x,float y,float z); float area(); int isTriangle(); private: float a,b,c; };

  14. 几点说明 1. 类定义中的两个关键字:public、private实现了数据封装; 2. public: 提供给用户的接口。可以通过该类的对象直接引用。(其下的成员函数可以被本类中的数据成员和成员函数使用) 3. private:用来描述该类对象的属性,不允许直接访问,只有成员函数或经特殊说明的函数才可以引用它们,(其下的成员函数或数据成员只能被本类中所提供的成员函数使用)

  15. 几点说明 4. protected:主要是用于继承关系(略)。 5. public、private和protected代表访问权限。 与先后顺序无关,允许多次出现。

  16. 二、实现部分 对类中各成员函数进行定义。 一般形式: 函数返回值类型 类名:: 函数名(参数列表) { 函数语句体 } 例如,Triangle类中成员函数: Triangle:: Triangle () { a=b=c=0; }

  17. 二、实现部分 void Triangle::setSide(float x,float y,float z) { a=x;b=y;c=z; } float Triangle::area() { float s; s=(a+b+c)/2; //三角形周长的一半 return sqrt(s*(s-a)*(s-b)*(s-c)); //计算三角形面积 } int Triangle:: isTriangle() { if((a+b)>c && (b+c)>a && (a+c)>b)) //满足构成三角形的条件 return 1; else return 0; }

  18. 说明: • 与类同名的成员函数称为“构造函数”。 • 如:Triangle() • 2. 构造函数的一个重要作用:初始化类对象的数据成员。 • 构造函数的调用时机:对象生命开始的时候,由系统自动调用。 • 注:关于构造函数的性质将在后续章节(第9章)叙述。 注意: 1. 成员函数也可以在类声明中直接定义(p.231)。 2. 不建议这么做。

  19. §8.4 类成员的访问和作用域 一、类对象的定义 <类名> <对象名> 例如: Triangle triangle; //Shape类的对象 Triangle ArrTriangle[5]; //Shape类的对象数组 Triangle *PointTriangle; //Shape类的指针对象 Triangle &RefTriangle= triangle;//Shape类对象的别名 注意:对象不能直接使用private中的成员: triangle.a 是错误的。

  20. 二、类的作用域 1. 类中的成员函数可互相直接调用。 2. 类中的数据成员在类中各成员函数间属“ 公共变量”。 3. 成员函数中的变量若有与类中的数据成员同名同类,则类中的数据成员被隐藏。

  21. 例:数据成员的作用域。 //----examp2_3.cpp #include <iostream.h> class Date{ public: Date( ) {day=31; month=12; year=2000; } void getday( ); private: int day,month,year; }; void main( ) { Date myday; myday.getday( ); } void Date::getday( ) { int year=1999; cout<<"1: "<<year<<"-"<<month<<"- "<<day<<"\n"; cout<<"2: "<<Date::year<<"-"<<month<<"-" <<day<<"\n"; } 运行结果: 1: 1999-12-31 2: 2000-12-31

  22. 三、类成员的访问 两个要点: 1. 只有本类的对象可以访问本类的公有成员. 2. 本类对象不能直接访问本类中的私有成员.

  23. 例2:对【例1】提出的问题,用类来完成三角形面积的计算。(【例1】给定三角形的三条边,计算三角形的面积和周长)例2:对【例1】提出的问题,用类来完成三角形面积的计算。(【例1】给定三角形的三条边,计算三角形的面积和周长) example8_2.cpp 分析: 1. a、b、c属private,只能通过成员函数才能访问。 2. setShape() 完成对三角形边长的设置。 3. isTriangle()判断三条边长是否能合法。 4. area()计算三角形的面积。 5. 构造函数由系统自动调用。用于初始化数据成员的值。 请注意: 1. 函数isTriangle()和area()不需要参数,直接使用类中的私有数据。 设计概念: 1. 类的对象只需要通过发送消息来完成任务。 2. 类的实现过程对用户是隐藏的。

  24. §8.5 访问函数和工具函数的意义 访问函数和工具函数是一种称呼 意义:划分封装的程度 • 访问函数:对外接口函数(public成员函数) • 作用:设置私有数据成员值; • 读取、显示和返回私有数据成员值; • 进行各种类的操作; • 测试条件的真假等。 • 2. 工具函数:非接口函数(private成员函数) • 作用: • 支持类中其他函数的操作。

  25. 例3:实现一个销售统计问题。从键盘输入某商品每个月销售了多少件,统计该年度共销售了多少件,并计算总销售额。例3:实现一个销售统计问题。从键盘输入某商品每个月销售了多少件,统计该年度共销售了多少件,并计算总销售额。 • 分析:以销售的商品作为对象; • 对象的基本属性为:①价格;②每月的销售数量。 • 基本功能为:①输入每月的销售额; ②输出年度总销售量及总销售额; ③计算年度总销售量及总销售额。 • (因计算的功能不属于对象应具有的) • 访问函数: • void setSell(int month,double price); // ① • void printMonthSell(); // ② • 工具函数: • int totalAnnualSell(); // ③ • 程序:example8_3.cpp • 思考:将工具函数改成访问函数会有什么不同?

  26. 例4:一个关于日期的类: void Temp::getday( ) { day=1; month=1; year=1980; cout<<"1: "<<year <<"-"<<month <<"-"<<day<<"\n"; } void Temp::setday( ) { day=day+9; month=month+9; year=year+20; cout<<"2: "<<year <<"-"<<month <<"-"<<day<<"\n"; } //----examp2_1.cpp #include <iostream.h> class Temp{ public: void getday( ); void setday(); private: int day,month,year; }; void main( ) { Temp myday; //myday.day=12; 错误的语句 myday.getday( ); myday.setday( ); } 1: 1980-1-1 2: 2000-10-10 运行结果:

  27. 点评程序例4: 程序中的不良之处: 1.类名不明确: Temp和Date(日期)关联不明。 2.函数功能不明确: 函数getday()和函数setday()都可以修改私有数据成员。 设计原则: 1.类名要能反映分类的思想。 2.每个函数应具有独立的功能。

  28. 例5:修改例4的程序。 无法预料的结果 //----examp2_1a.cpp #include <iostream.h> class Date{ public: void getday( ); void setday( ); private: int day,month,year; }; void main( ) { Date myday; cout<<"1:"; myday.getday(); cout<<"2:"; myday.setday(); myday.getday(); } void Date::getday( ) { cout<<year<<"-" <<month <<"-" <<day<<"\n"; } void Date::setday( ) { day=day+9; month=month+9; year=year+20; } 运行结果: 1: 19394-5855-10459 2: 19414-5864-10468

  29. 点评程序例5: 1.好的方面: 类名比较清晰,函数功能比较明确。 2.不好的方面: 程序中出现了不可预料的结果,原因是由于对象的私有数据成员的值没有初始化。 设计原则: 1.任何对象的私有成员的值都应该进行初始化,以避免产生不确定的值。 2.get函数一般不要求带参数,set函数一般要求要带参数。

  30. 例6:改进例5的程序。 //----examp2_1b.cpp #include <iostream.h> class Date{ public: void getday(); void setday(int y,int m,int d); private: int day,month,year; }; void main( ) { Date myday; int yy=2000,mm=12,dd=31; myday.setday(yy,mm,dd); myday.getday(); yy=2001,mm=1,dd=1; myday.setday(yy,mm,dd); myday.getday(); } void Date::getday( ) { cout<<year<<"-" <<month<<"-" <<day<<"\n"; } void Date::setday(int y,int m,int d) { day=d; month=m; year=y; } 运行结果: 1980-1-1 2000-10-10

  31. 点评程序例6: 产生的新问题: 必须要先调用set函数,对私有数据成员赋值,才能确保程序的稳定。 设计原则: 1.任何对象生成之处,就拥有初始值。 2.set函数一般使用在程序中间,需要修改数据成员数值的时候。 3.采用构造函数为对象的数据成员赋初值。

  32. 保存在 1. 类的定义 <基本名>.h 保存在 2. 类中成员函数的定义 <基本名>.cpp 编译成 目标代码1 保存在 3. 主程序(头文件包含类定义文件) <文件名>.cpp 编译成 目标代码2 §8.6 接口和实现的分离 实际上就是将类的定义与类中的函数定义分别放在不同的文件中 4. 连接目标代码1和目标代码2  P.236——将程序example8_3.cpp进行分离

  33. 本章小结 重点: 1. 定义一个新的数据类型:类 2. 类中成员的性质: private、public 3. 一种属于"类"的数据类型:对象 4. 对象访问类中成员的权限 5. 访问函数和工具函数 6. 接口和实现的分离

  34. 本章练习 一、选择题 二、填空题 三、程序理解题 四、简答题 五、编程题 8.38、8.39、8.42、8.43

More Related