1 / 63

程序设计基础

程序设计是计算机学科的. 核心和灵魂. 程序设计基础. 第五章 类与对象. 类的作用 类界面与类实现 类成员的访问控制 对象的创建 静态数据成员 构造函数与析构函数 成员对象的初始化. §5.1 类的引入. 实体:从属性与行为两个方面刻画一个实体 现实世界实体例:银行账户、学生、传感器、 … 思维世界实体例:复数、矩阵、堆栈、 … 类:描述实体的抽象概念 对象:对应于一个个具体实体. §5.1 类的引入. 5.1.1 循环计数器 循环计数: 0 0 ~359 0 、 1~12

Download Presentation

程序设计基础

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. 程序设计是计算机学科的 核心和灵魂 程序设计基础 第五章 类与对象

  2. 类的作用 • 类界面与类实现 • 类成员的访问控制 • 对象的创建 • 静态数据成员 • 构造函数与析构函数 • 成员对象的初始化

  3. §5.1 类的引入 实体:从属性与行为两个方面刻画一个实体 • 现实世界实体例:银行账户、学生、传感器、… • 思维世界实体例:复数、矩阵、堆栈、… 类:描述实体的抽象概念 对象:对应于一个个具体实体

  4. §5.1 类的引入 5.1.1 循环计数器 循环计数:00~3590、1~12 数据定义:min_val、max_val、current 函数设计:increment()、decrement()、 set_mode()、 get_value()、set_value

  5. §5.1 类的引入 5.1.1 循环计数器 保护内部数据: static int min_val; static int max_val; static int current; 信息隐藏 • 将一个模块的内部数据或操作隐藏起来,其他模块只能通过该模块提供的公开操作来访问该模块 • 信息隐藏由封装机制来实现。 在C语言中用文件作为模块来实现

  6. §5.1 类的引入 5.1.1 循环计数器 用文件作为模块来实现封装 CIRNUM1.Hpp //循环计数器头文件 CIRNUM1.CPP //实现循环计数器

  7. §5.1 类的引入 增加程序可靠性和可重用性 5.1.2 循环计数器的讨论 用文件作为循环计数器模块的好处: 头文件作为模块界面,保护内部数据; 应用程序不关心模块内部实现细节; 便于模块设计者修改实现方法和扩展新功能。 不足: 不够抽象,如定义三个记录角度、月份和时间的计数器; 函数名冲突问题; 模块修改必须重新编译。

  8. §5.1 类的引入 5.1.3 类作为构造程序的基本单位 类(class):构造程序的基本单位,将数据以及这些数据上的操作(函数)封装在一起。 类成员(member):数据与函数 C++类的作用: 数据封装 类型定义

  9. §5.2 类的定义 5.2.1 类声明 类是对一群具有相同属性、表现相同行为的对象的描述,类声明的一般形式 : class 类名 { public: 公有数据和函数 private: 私有数据和函数 }; 类中定义的数据(变量)称为数据成员类中定义的函数(行为操作)称为成员函数

  10. §5.2 类的定义 void increment() {// 循环计数器加一 int mode = max_val – min_val + 1; current = ((current – min_val) + 1) % mode + min_val; return; } void decrement() {// 循环计数器减一 int mode = max_val – min_val + 1; current = ((current – min_val) - 1 + mode) % mode + min_val; return; } private: int min_val;// 最小值 int max_val;// 最大值 int current;// 当前值 }; 5.2.1 类声明 例:循环计数器类 class CIRCULAR_NUMBERS { public: void set_mode(int min, int max) {// 设置循环计数器的上、下限 min_val = min; max_val = max; return; } void set_value(int value) {// 设置循环计数器的当前值 current = value; return; } int get_value() {// 查询循环计数器的当前值 return current; }

  11. §5.2 类的定义 5.2.1 类声明 说明: • 类的数据成员允许是任何数据类型,但不能是本类类型的。正在定义的类名只可以以指针形式声明自己类中的数据成员 class Link { class Link { Link member; Link *member; ………… }; };

  12. = 0 = 359 §5.2 类的定义 5.2.1 类声明 • 类中的数据成员不允许使用初值表达式 class CIRCULAR_NUMBERS { … private: int min_val ; int max_val ; … }; • 类中的数据成员不允许使用auto,register,extern修饰,但允许使用static修饰,得到静态数据成员:供该类的所有对象公用

  13. §5.2 类的定义 5.2.1 类声明 • 在类中 const 的使用 • const修饰数据成员:用于声明类中的一个常量数据成员。由于类的数据成员在声明时不能有初值表达式,因此类的常量数据成员在声明时不能指定常量值。 class C { const double PI ; …… }; • const修饰成员函数:常量成员函数,常量成员函数中不允许修改本类数据成员的值。 class C { int get_value() const { …… } };

  14. §5.2 类的定义 5.2.2 类成员的访问控制 指明成员的可访问性 • 私有段:由private标记的段 段内的数据成员和成员函数称为私有成员,仅能由该类中的成员函数来访问,即仅可在成员函数定义中使用私有成员的名字。 • 公有段:由public标记的段 段内的数据成员和成员函数称为公有成员,为该类提供与外部世界的接口界面,即可在类内也可在类外访问。 • 类中每一个成员都有访问控制属性,若没有明确指明,成员的访问控制方式缺省为private。

  15. §5.2 类的定义 5.2.3 类界面与类实现 • 类的成员函数可以在类内定义,也可以在类外定义。 • 类界面:头文件 *.hpp声明类,包括类的所有数据成员,以及成员函数的原型 //程序:CIRNUM3.hpp //功能:循环计数器头文件 class CIRCULAR_NUMBERS { public: void set_mode(int min, int max);// 设置循环计数器的上、下限 void set_value(int value) // 设置循环计数器的当前值 int get_value() // 查询循环计数器的当前值 void increment() // 循环计数器加1 void decrement() // 循环计数器减1 private: int min_val; // 最小值 int max_val; // 最大值 int current; // 当前值 };

  16. §5.2 类的定义 5.2.3 类界面与类实现 • 类实现:源程序 *.cpp首先要包含类界面:#include “*.hpp”然后定义成员函数,由于此时成员函数的定义是位于类的外面,因此必须用类名和作用域运算符::来修饰函数名。一般形式为: 成员函数类型 类名::成员函数名(形参表) { 函数体 } 例:// 循环计数器加一 void CIRCULAR_NUMBERS::increment() { int mode = max_val - min_val + 1; current = ((current - min_val) + 1) % mode + min_val; return; }

  17. §5.2 类的定义 5.2.4标识符的类作用域 • { }内即为类作用域 • 在类作用域中声明的标识符只在该类中具有可见性 • 成员名限定:类中一个成员名字可以使用类名和作用域运算符来显式指定 class C { void C::set(int val) public: { value = val; void set(int val); return; private: } int value; }; C::value

  18. §5.3 对象的创建 5.3.1 对象声明 • 类:数据类型 • 具有类类型的变量称为对象,对象称为类的实例。 • 对象声明一般格式: <类名> <对象名> int main() { CIRCULAR_NUMBERS angle; // 角度循环计数器 CIRCULAR_NUMBERS month; // 月份循环计数器 angle.set_mode(0, 359); // 设置角度取值范围从0到359 angle.set_value(250); // 设置当前角度为250 month.set_mode(1, 12); // 设置月份取值范围从1到12 month.set_value(11); // 设置当前月为11月 } 小写字母

  19. CIRCULAR_NUMBER 对象month 对象angle 1 min_val set_value() decrement() increment() get_value() set_mode() min_val current max_val 250 359 0 12 max_val 11 current set_mode() set_mode()代码 set_value() get_value() increment() set_value()代码 increment()代码 decrement() decrement()代码 get_value()代码 §5.3 对象的创建 类CIRCULAR_NUMBERS 的实例 5.3.1 对象声明 CIRCULAR_NUMBERS angle,month;

  20. §5.3 对象的创建 5.3.1 对象声明 静态数据成员 • 用static修饰的数据成员:被分配占用一个固定的存储空间,由此类的所有对象共享,对于类来说:静态数据成员相当于类的全局变量。 • 使用方法: • 在类的界面中(定义)声明一个静态数据成员 • 在类实现中,必须再次声明并初始化这个静态数据变量 // test1.hpp// test1.cpp class C { #include “test1.hpp” private: int x; int C::s = 18 ; int y;static int s; int C::set(int i, int j) public: { x = i ; int set(int,int); y = j ; }; s++; }

  21. set() x y 对象c2 对象c1 x y s: 18 set() set ()代码 §5.3 对象的创建 5.3.1 对象声明 静态数据成员 // test.cpp #include “test1.hpp” void main( ) { C c1, c2; c1.set(100,200); c2.set(15, 30); } 类C 19 20 100 200 15 30

  22. §5.3 对象的创建 5.3.2 使用对象成员 通过成员选择运算符.来访问/使用对象的公有成员 对象名.成员名 angle.get_value(); angle.setmode(0,359);

  23. §5.3 对象的创建 5.3.3 对象的生存期 对象生存期:对象从被创建开始到被释放为止的时间。 数据成员生存期有对象生存期决定,成员函数具有全局生存期 (1)局部对象:定义在函数体内或程序块内,作用域限定在函数体或程序块中。 (2)静态对象:定义在一个文件中,作用域从定义时起到文件结束。 (3)全局对象:定义在某个文件中,作用域在包含该文件的整个程序中。

  24. §5.4 对象的初始化 5.4.1 构造函数 • 类中的一个特殊函数 • 功能:对该类的对象进行初始化 • 一般形式:类名(形式参数表); • 特点: • 构造函数是公有的,可由用户提供,也可由系统提供缺省的。 • 构造函数可以有任何类型的形参,但是无返回值,也不能指定返回类型。 • 构造函数在声明一个新对象时调用(对象声明语句中为构造函数提供实参),不可显式调用

  25. §5.4 对象的初始化 5.4.1 构造函数 程序5.4.1 //程序:CIRNUM4.hpp //功能:循环计数器类头文件,使用构造函数 class CIRCULAR_NUMBERS { public: CIRCULAR_NUMBERS(int min, int max, int value); // 设置循环计数器的上下限和当前值 int get_value(); // 查询循环计数器的当前值 void increment(); // 循环计数器加1 void decrement(); // 循环计数器减1 private: int min_val; // 最小值 int max_val; // 最大值 int current; // 当前值 };

  26. §5.4 对象的初始化 5.4.1 构造函数 程序5.4.2 …… // 设置循环计数器的上下限和当前值 CIRCULAR_NUMBERS::CIRCULAR_NUMBERS(int min, int max, int value) { min_val = (min <= max) ? min : max; max_val = (min <= max) ? max : min; if (value < min_val) current = min_val; else { if (value > max_val) current = max_val; else current = value; } return; } ……

  27. §5.4 对象的初始化 5.4.1 构造函数 程序5.4.3 …… int main() { // 创建两个循环计数器对象并初始化 CIRCULAR_NUMBERS angle(0, 359, 250); // 角度循环计数器 CIRCULAR_NUMBERS month(1, 12, 11); // 月份循环计数器 …… }

  28. §5.4 对象的初始化 全局对象与静态对象的构造函数在main()函数执行之前被调用 5.4.1 构造函数 程序5.4.4 //程序:CIRDEMO5.cpp //功能:演示全局对象与静态对象的初始化 #include “cirnum4.hpp” #include <iostream.h> CIRCULAR_NUMBERS angle(0, 359, 250); // 角度循环计数器作为全局对象 int main() { static CIRCULAR_NUMBERS month(1, 12, 11); // 月份循环计数器作为静态对象 //显示对象状态 cout<<“The initial angle is ”<<angle.get_value()<<“\n”; cout<<“The initial month is ”<<month.get_value()<<“\n”; }

  29. §5.4 对象的初始化 5.4.1 构造函数 程序5.4.5 //程序:一个时间类DATE的例子 //功能:演示多个不同的构造函数 class Date { protected: int year; int month; int day; public: Date() //构造函数,不带参数 { year=0; month=1; day=1; } Date(int y, int m, int d) //构造函数,带参数 { year=y; month=m; day=d; } Date(Date& obj) //构造函数,以一个同类对象为参数 { year=obj.year; month=obj.month; day=obj.day; } void print() { cout<<year<<“/”<<month<<“/”<<day<<endl; } }

  30. §5.4 对象的初始化 5.4.2 析构函数 • 类中的一个特殊函数 • 功能:为撤销一个类的对象做善后清理工作(如:回收存储空间) • 一般形式:~类名( ); • 特点: • 析构函数是公有的,可由用户提供,也可由系统提供缺省的。 • 析构函数不可带任何参数,无返回值,也不能指定返回类型。 • 在对象生存期结束时,程序将自动调用该对象所属类的析构函数,调用且仅调用一次。

  31. §5.4 对象的初始化 5.4.2 析构函数 程序5.4.6 //程序:DESTROY.CPP //功能:演示构造函数与析构函数的调用 #include <iostream.h> class DEMO_CLASS { public: DEMO_CLASS(int i); ~DEMO_CLASS(); }; DEMO_CLASS::DEMO_CLASS(int i) { cout << "Initial value is " << i << "\n"; return; } DEMO_CLASS::~DEMO_CLASS() { cout << "Goodbye!\n"; return; }

  32. §5.4 对象的初始化 5.4.2 析构函数 int main() { DEMO_CLASS obj(30);// 声明一个对象 cout << "This is the end of main().\n"; return 0; } 运行结果: Initial value is 30 This is the end of main(). Goodbye!

  33. §5.4 对象的初始化 5.4.3 对象成员的初始化 • 对象成员:在一个类中声明具有类类型的数据成员 • 初始化对象成员的方法:在本类的构造函数中调用这些对象成员所属类的构造函数,其一般形式:类名::类名(形参表):初始化列表{ …… } class A { …… public: B::B():obj2(10,20), obj1(5,3) A(int a, float b); { …… }; } class B { A obj1, obj2; public: B(); }

  34. §5.4 对象的初始化 5.4.3 对象成员的初始化 说明 • 如果有多个对象成员,对象成员构造函数的调用次序取决于这些成员在类中声明的次序。 • 执行次序: 创建类的对象时,调用此类的构造函数,先根据初始化列表调用对象成员的构造函数,初始化对象成员,然后才执行本身的构造函数的函数体。 析构函数调用的次序相反。

  35. §5.4 对象的初始化 5.4.3 对象成员的初始化 程序5.4.8 //程序:OBJECT.CPP //功能:演示类中包含有另一个类的对象初始化 // 在构造函数和析构函数中加入输出以便跟踪 #include<iostream.h> class Object { int val; public: Object( ); //构造函数 Object( int i ); //构造函数 ~Object( ); //析构函数 }; Object::Object( ) { val=0; cout<<"\n Default constructor for Object.\n"; }

  36. §5.4 对象的初始化 5.4.3 对象成员的初始化 Object::Object( int i) //构造函数定义 { val=i; cout<<"\n Constructor for Object: "<<val<<endl; } Object::~Object( ) //析构函数定义 { cout<<"\n Destructor for Object: "<<val<<endl;} class Container //定义新类,它含Object的对象 { private: int date; Object one; //对象成员 Object two; //对象成员 public: Container( ); //构造函数 Container( int i, int j, int k); //构造函数 ~Container( ); //析构函数 };

  37. §5.4 对象的初始化 5.4.3 对象成员的初始化 Container::Container( ) //构造函数定义 { date=0; cout<<"\n Default constructor for Container.\n"; } Container::Container( int i, int j, int k):two(i),one(j) { date=k; cout<<"\n Constructor for Container.\n"; } Container::~Container( ) { cout<<"\n Destructor for Container.\n"; } void main( ) //演示程序 { cout<<"\n... Entering main ...\n"; Container obj(5,6,10); cout<<"\n... Exiting main ...\n"; }

  38. §5.4 对象的初始化 5.4.3 对象成员的初始化 执行结果为: ... Entering main ... Constructor for Object: 6 //对象one调用构造函数 Constructor for Object: 5 //对象two调用构造函数 Constructor for Container. //调用Container的构造函数 ...Exiting main ... Destructor for Container. //调用Container的析构函数 Destructor for Object: 5 //调用two的析构函数 Destructor for Object: 6 //调用one的析构函数

  39. §5.4 对象的初始化 5.4.3 对象成员的初始化 初始化列表的其他用途 • 基本数据类型的数据成员也可用初始化列表做初始化 class C { public: C(int i):number(i) C(int i) {……} <=> { number = i; private: …… int number; } };

  40. §5.4 对象的初始化 5.4.3 对象成员的初始化 初始化列表的其他用途 • 常量数据成员的初始化 常量数据成员: 不能在类的声明中初始化(类中不能用初值表达式) 不能在构造函数中设置其值(赋值操作不能用于常量) 只能采用初始化列表中来赋值 例:class C { C::C(int i): PI(3.14159) public: { C(int i); …… private: } const double PI ; };

  41. §5.4 对象的初始化 5.4.3 对象成员的初始化 //程序:OBJECT1.CPP //功能:演示类中包含有另一个类的对象初始化 #include <iostream.h> #include <conio.h> class base{ public: base(char *s){ cout<<"Construct for Base "<<s<<"\n"; } ~base() { cout<<"Destruct for Base\n"; } }; class screen { private: const unsigned size; long price; base obj; public: screen(int s, long p):size(s),price(p),obj("testing") {cout<<"Construct for Screen\n"; } void list(); ~screen(){ cout<<"Destruct for Screen\n"; } };

  42. §5.4 对象的初始化 5.4.3 对象成员的初始化 void main() { screen nec(14,40000L); nec.list(); getch(); } void screen::list() { cout<<"The size of the screen is :"<<size<<"\n"; cout<<"The price of the screen is :"<<price<<"\n"; } 运行结果: Construct for Base testing Construct for Screen The size of the screen is :14 The price of the screen is :40000 Destruct for Screen Destruct for Base

  43. §5.5 使用类与对象构造程序的实例 5.5.1 模拟数字式时钟 //程序:CLOCK.HPP //功能:时钟类的头文件 #include "cirnum4.hpp" #include <iostream.h> class Clock { public: Clock(int hh, int mm, int ss); void update(); void show(); private: CIRCULAR_NUMBERS hour; CIRCULAR_NUMBERS minute; CIRCULAR_NUMBERS second; };

  44. §5.5 使用类与对象构造程序的实例 5.5.1 模拟数字式时钟 //设置时钟当前值 Clock::Clock(int hh, int mm, int ss): hour(0,23,hh), minute(0,59,mm), second(0,59,ss) { return; } void Clock::update() // 刷新时间 { second.increment(); if(second.get_value()==0) { minute.increment(); if(minute.get_value()==0)hour.increment(); } return; } void Clock::show() //显示时间 { cout<<hour.get_value()<<":"<<minute.get_value()<<":"<<second.get_value()<<endl; return; }

  45. §5.5 使用类与对象构造程序的实例 5.5.1 模拟数字式时钟 //程序:TIMEDEMO.cpp //功能:使用类Clock模拟数字式时钟 #include "clock.hpp" #include <iostream.h> int main() { int loop; Clock rolex(4,15,30); Clock cima(14,0,0); cout<<"Rolex: \n"; //显示rolex对象 for(loop=1; loop<=100; loop=loop+1) { rolex.update(); rolex.show(); } cout<<"Cima: \n"; //显示Cima对象 for(loop=1; loop<=100; loop=loop+1) { cima.update(); cima.show(); } return 0; }

  46. §5.5 使用类与对象构造程序的实例 5.5.2 模拟加油站油泵的对象工作 //程序:PUMP.CPP //功能:加油站油泵实现文件 #include <iostream.h> #include <iomanip.h> const float AMTINT=300.0; // 初始化油桶中的油量 const float PRICE=1.25; // 单价 class Pump { protected: float amtint,price; public: Pump(float,float); void values(); void request(float); };

  47. §5.5 使用类与对象构造程序的实例 5.5.2 模拟加油站油泵的对象工作 Pump::Pump(float start, float todays) { amtint=start; price=todays;} void Pump::values() { cout<<"The gas tank has: "<<amtint<<endl; cout<<"The price per kg of gas is: "<<price<<endl; } void Pump::request(float pumpamt) { float pumped; if(amtint>=pumpamt) pumped=pumpamt; //满足 else pumped=amtint; amtint=amtint-pumped; // 加油后剩余数 cout<<pumpamt<<" kg were requested"<<endl; cout<<pumped<<" kg were pumped"<<endl; cout<<amtint<<" kg remain in the tank"<<endl; cout<<" The total price is: "<<(pumped*price)<<endl; }

  48. §5.5 使用类与对象构造程序的实例 5.5.2 模拟加油站油泵的对象工作 void main() { Pump obj(AMTINT,PRICE); obj.values(); cout<<endl; obj.request(30.0); cout<<endl; obj.request(280.0); } 程序运行结果: The gas tank has: 300 The price per kg of gas is: 1.25 30 kg were requested 30 kg were pumped 270 kg remain in the tank The total price is: 37.5 280 kg were requested 270 kg were pumped 0 kg remain in the tank The total price is: 337.5

  49. §5.5 使用类与对象构造程序的实例 5.5.3 单实例对象 //程序:SINGLE.HPP //功能:单实例类的头文件 class Single_Instance { public: Single_Instance(); ~Single_Instance(); private: static int instance_count; // 当前对象实例计数 }; #include <iostream.h> int Single_Instance::instance_count=0; // 初始化实例计数,注意静态成员的这种用法 Single_Instance::Single_Instance() //构造函数中必须为实例计数加1 { instance_count++; if(instance_count>1) cout<<"Warning: more than one object instance!"<<endl; } Single_Instance::~Single_Instance() //析构函数必须为实例计数减 1 { instance_count--; }

  50. §5.5 使用类与对象构造程序的实例 5.5.3 单实例对象 //程序:SGL_DEMO.HPP //功能:演示单实例对象的用法 #include "single.hpp" #include <iostream.h> int main() { cout<<" I have the first object."<<endl; Single_Instance obj1; cout<<" I have the second object."<<endl; Single_Instance obj2; cout<<" End of demostration"<<endl; return 0; } 程序运行结果: I have the first object. I have the second object. Warning: more than one object instance! End of demostration

More Related