皮德常《面向对象的程序设计》课程ppt
合集下载
面向对象程序设计PPT课件 PPT资料共63页
Stringed object vptr
Percussion object vptr
&Wind::play() & Stringed::play() & Percussion::play()
06.11.2019
第5章多态与抽象类
37
当通过对象调用虚函数时,是通过 vptr找到虚函数表,再找出虚函数的 真正地址。
06.11.2019
第5章多态与抽象类
28
【思考题5-4】将例5-5中用对象调用
虚函数,其结果如何?
【注意】只有通过对象指针或对象引 用来调用虚函数,才能实现动态联编 。如果采用对象来调用虚函数,则采 用的是静态联编方式。
06.11.2019
第5章多态与抽象类
29
【例5-6】将例5-4基类的成员函数 print()设为虚函数,采用对象引用调 用虚函数,进而实现动态联编。
06.11.2019
第5章多态与抽象类
32
小结
(1)如果你期望在派生类中重新定义一 个成员函数,那么你就应该在基类中 把该函数设为virtual。
(2)以单一指令调用不同函数,这种性 质就是"多态"。
(3)虚函数是C++语言的多态性质和动 态绑定的关键。
(4)虚函数派生下去仍是虚函数,而且
可以省略virtual关键词。 06.11.2019
25
该程序的运行结果为:
A student A graduate student A student A student A graduate student
06.11.2019
第5章多态与抽象类
26
【思考题5-5】如果将例5-5中Student类改 为:
Percussion object vptr
&Wind::play() & Stringed::play() & Percussion::play()
06.11.2019
第5章多态与抽象类
37
当通过对象调用虚函数时,是通过 vptr找到虚函数表,再找出虚函数的 真正地址。
06.11.2019
第5章多态与抽象类
28
【思考题5-4】将例5-5中用对象调用
虚函数,其结果如何?
【注意】只有通过对象指针或对象引 用来调用虚函数,才能实现动态联编 。如果采用对象来调用虚函数,则采 用的是静态联编方式。
06.11.2019
第5章多态与抽象类
29
【例5-6】将例5-4基类的成员函数 print()设为虚函数,采用对象引用调 用虚函数,进而实现动态联编。
06.11.2019
第5章多态与抽象类
32
小结
(1)如果你期望在派生类中重新定义一 个成员函数,那么你就应该在基类中 把该函数设为virtual。
(2)以单一指令调用不同函数,这种性 质就是"多态"。
(3)虚函数是C++语言的多态性质和动 态绑定的关键。
(4)虚函数派生下去仍是虚函数,而且
可以省略virtual关键词。 06.11.2019
25
该程序的运行结果为:
A student A graduate student A student A student A graduate student
06.11.2019
第5章多态与抽象类
26
【思考题5-5】如果将例5-5中Student类改 为:
面向对象的程序设计基础课件
2. AddObject方法是在运行时向容器对象中添加对象。 3. Clear方法是清除组合框或列表框中的内容。 4. Refresh方法是重画表单或控件,并刷新所有值。 5.Setall方法是为容器对象中的控件或某类控件指定属性
设置。 6. SetFocus方法是为一个控件指定焦点 7.Show方法是显示一个表单,并且确定是模式表单还是无
如按【Tab】键或单击,或者在代码中使用 SetFocus方法
VFP的核心事件集
• Lostfocus:对象失去焦点,由用户动作引起,如按【 Tab】键或单击,或者在代码中使用SetFocus方法
• KeyPress:用户按下或释放键 • MouseDown:当鼠标指针停在一个对象上时,用户按
下鼠标按钮。 • MouseMove:用户在对象上移动鼠标 • MouseUp:当鼠标指针停在一个对象上时,用户释放
对象
1每个对象都具有属性以及与之相关的事件和方法,通过对象的属 性、事件和方法来处理对象。
§ 属性 定义对象的特征或某一方面的行为,如大小、颜色、所处 的位置等。
§ 事件 是由对象识别的一个动作,可以编写相应的代码,以对此 动作进行响应。事件是一种预先定义好的特定动作,被用户或系 统激活,每个对象都可以对事件的动作进行识别和响应。在多数 情况下,事件是由用户的交互行为产生的 (用户不能创建新的事 件)
返 回
类的分类
v 基类 ( base class ) ——VFP 系统提供的内部定义的类, 用做其他用户自定义类的基础。(如表单和所有控件)
v 子类(Subclass)——以其他类定义为起点,为某一种对象 所建立的新类。子类将继承任何对父类(即子类所基于的 类)所做的修改。
v 用户自定义类——与基类相似,但由用户定义,并且可用 来派生子类。这种类没有可视化表示形式。
设置。 6. SetFocus方法是为一个控件指定焦点 7.Show方法是显示一个表单,并且确定是模式表单还是无
如按【Tab】键或单击,或者在代码中使用 SetFocus方法
VFP的核心事件集
• Lostfocus:对象失去焦点,由用户动作引起,如按【 Tab】键或单击,或者在代码中使用SetFocus方法
• KeyPress:用户按下或释放键 • MouseDown:当鼠标指针停在一个对象上时,用户按
下鼠标按钮。 • MouseMove:用户在对象上移动鼠标 • MouseUp:当鼠标指针停在一个对象上时,用户释放
对象
1每个对象都具有属性以及与之相关的事件和方法,通过对象的属 性、事件和方法来处理对象。
§ 属性 定义对象的特征或某一方面的行为,如大小、颜色、所处 的位置等。
§ 事件 是由对象识别的一个动作,可以编写相应的代码,以对此 动作进行响应。事件是一种预先定义好的特定动作,被用户或系 统激活,每个对象都可以对事件的动作进行识别和响应。在多数 情况下,事件是由用户的交互行为产生的 (用户不能创建新的事 件)
返 回
类的分类
v 基类 ( base class ) ——VFP 系统提供的内部定义的类, 用做其他用户自定义类的基础。(如表单和所有控件)
v 子类(Subclass)——以其他类定义为起点,为某一种对象 所建立的新类。子类将继承任何对父类(即子类所基于的 类)所做的修改。
v 用户自定义类——与基类相似,但由用户定义,并且可用 来派生子类。这种类没有可视化表示形式。
第06章 面向对象程序设计PPT课件
3
面向对象的基本概念2-1
• 类和对象
– 通常把具有相同性质和功能的事物所构成的整体称为 类
– 属于一个类的某个具体的事物称为该类的一个对象
• 属性、方法和事件
– 属性是指一个类的性质 – 方法是指一个类的功能 – 事件是对象能够识别和响应的某些操作
• 封装
– 封装是指将用来描述客观事物的一组数据和操作包装 在一起,形成一个类
• namespace Ns1 • { class A {…} • class B {…} •}
10
使用命名空间5-4
• 命名空间可以嵌套使用,例如
– namespace Ns1 –{ – namespace Ns2 –{ – class B {…} –} –}
11
使用命名空间5-5
• 在C#开发中,每个项目会自动附加一个默 认的命名空间
方法
方法定义类可以执行的操作。方法可以接受提供输入数据的参数, 并且可以通过参数返回输出数据。方法还可以不使用参数而直接返 回值
事件
事件是向其他对象提供有关事件发生(如单击按钮或成功完成某个 方法)通知的一种方式
索引器 索引器允许以类似于数组的方式为对象建立索引
运算符 运算符是对操作数执行运算的术语或符号,如 +、*、< 等
• 析构函数具有如下性质
– 析构函数在类对象销毁时自动执行 – 一个类只能有一个析构函数,而且析构函数没有参数,
即析构函数不能重载 – 析构函数的名称是“~”加上类的名称(中间没有空
格)。 – 与构造函数一样,析构函数也没有返回类型 – 析构函数也不能被继承
24
析构函数示例
using System;
4
面向对象的基本概念2-2
面向对象程序设计(共13张PPT)
9.2.2 对象的使用
对象的使用主要体现在对其成员的引用上,对 象只能访问公有成员,一般格式为:
<对象名> . <公有成员数据名>
<对象名> . <公有成员函数名>(<参数表>)
prev
next
back
第5页,共13页。
9.2 类的使用
9.2.2 对象的使用
成员选择运算符 这里的符号“.”称为 对象数组的元素通过缺省构造函数而得到初始化。
4. 一个类的对象可作为另一个类的成员,
prev
称为对象成员。
next
back
第7页,共13页。
9.2 类的使用
9.2.3 对象数组和对象指针
定义一维对象数组的一般格式为:
《存储类型》<类名> <对象数组名>[<常量表达式
>];
对象数组中的每个元素可以象一般的对 象使用。
注意,在说明对象数组时,不能对它进 行初始化。对象数组的元素通过缺省构
第12页,共13页。
9.2 类的使用
9.2.5 类实现数据的封装
对象的封装性是指将对象的属性(成员数据)和 作用于这些属性上的操作(成员函数)封装在一 起,对象的使用者只能通过提供给它的接口
(公有成员函数)使用这个对象。
类通过对其成员设计不同的访问权限实现数据的
封装。公有成员是类的外部表现(在类外可以对 其进行访问和修改),而私有和保护成员则被 隐藏了。
prev
在定义类时,通常将该类的所有属性(成员数
据)和只供内部调用的操作(成员函数)定义为私
next
有成员或保护成员。
例9.5
back
对象的使用主要体现在对其成员的引用上,对 象只能访问公有成员,一般格式为:
<对象名> . <公有成员数据名>
<对象名> . <公有成员函数名>(<参数表>)
prev
next
back
第5页,共13页。
9.2 类的使用
9.2.2 对象的使用
成员选择运算符 这里的符号“.”称为 对象数组的元素通过缺省构造函数而得到初始化。
4. 一个类的对象可作为另一个类的成员,
prev
称为对象成员。
next
back
第7页,共13页。
9.2 类的使用
9.2.3 对象数组和对象指针
定义一维对象数组的一般格式为:
《存储类型》<类名> <对象数组名>[<常量表达式
>];
对象数组中的每个元素可以象一般的对 象使用。
注意,在说明对象数组时,不能对它进 行初始化。对象数组的元素通过缺省构
第12页,共13页。
9.2 类的使用
9.2.5 类实现数据的封装
对象的封装性是指将对象的属性(成员数据)和 作用于这些属性上的操作(成员函数)封装在一 起,对象的使用者只能通过提供给它的接口
(公有成员函数)使用这个对象。
类通过对其成员设计不同的访问权限实现数据的
封装。公有成员是类的外部表现(在类外可以对 其进行访问和修改),而私有和保护成员则被 隐藏了。
prev
在定义类时,通常将该类的所有属性(成员数
据)和只供内部调用的操作(成员函数)定义为私
next
有成员或保护成员。
例9.5
back
南航皮德常超星视频配套PPT Chapter-8
默认情况下类的成员是私有 的,而结构体(struct)中的成 员是公有的。
setData(float, float); calcArea( ); getWidth( ); getLength( ); getArea( );
8.2 类的基本概念(续)
• 为了使类的成员能够在类外面被访问,其 成员必须定义为public. • Example:
Rectangle.h Rectangle.cpp 8-2.cpp
8.6 私有函数成员的作用
• 专门用于内部处理的函数,它们在类的外部不能 使用,这些函数为私有的。 • 私有函数可以被同一个类中的其它函数调用。 Example: class Rectangle { private: float width, length , area; void calcArea( ); public: … 26 };
7
class Rectangle { private: float width; float length: float area; public: void setData(float, float); void calcArea( ); float getWidth( ); float getLength( ); float getArea( ); };
31
8.8.1 构造函数
• 构造函数是与类同名的函数成员; • 没有返回值类型,也不允许有void; • 如果构造函数没有参数,则称为缺省构造函数; • 构造函数的作用:在对象被创建时,采用给定的值将 对象初始化为一个特定的状态。 • 在对象创建时,由系统自动调用; • 如果程序中未声明,则系统自动产生出一个缺省形式 的构造函数; • 允许为内联函数、重载函数、带缺省形参值的函数。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
}
auxi1.h budget3.h auxi1.cpp budget3.cpp 9-3.cpp
9.2.3 一个类作为另外一个类的友元
• 若一个类为另一个类的友元,则此类的所有成员 都能访问对方类的私有成员。
class A { int x; friend class B; public: void Display( ){ cout<<x<<endl;} }; class B { A a; public: void Set(int i) { a.x = i; } void Display( ) { a.Display( ); } 23 };
Plz
// Contents of main program #include "budget3.h“ void main( ) { float amount; int i; float bud;
cout << "Enter the main office's budget: "; cin >> amount; Budget::mainOffice(amount); Budget divisions[4]; Aux auxOffices[4];
• 如果要统计一个班学生总数?
– 用类外的变量记录,违背了数据封装。 – 用类的一个数据成员记录,导致多个副本, 不仅冗余,而且势必造成数据不一致。
3
9.1.1 静态数据成员
1. 用关键字static声明;
2. 同一个类中的所有对象都共享该变量; 3. 必须在类外定义和初始化,用(::)来指明所属的类。 4. 静态变量不依赖于对象而存在,无论是否定义该类的 对象,这种类型的变量都存在。静态数据成员实际 上是在类外定义的一个变量,它的生存期和整个程 序的生存期一样,在定义对象之前,静态数据成员 就已经存在。
// Contents of auxi1.cpp #include "auxi1.h" #include "budget3.h"
// Definition of member function mainOffice. void Aux::addBudget(float b, Budget &div) { auxBudget += b; div.corpBudget += auxBudget; } Attention
4
class StaticDemo { static int x ; int y ; public: 理解它! void putx( int a){ x=a ; } void puty( int b ){ y=b ; } int get) { return y ; } }; int StaticDemo::x ; // 静态变量x将被StaticDemo类的所有对象共享,例如: StaticDemo obj1, obj2 ; obj1.putx(5) ; obj1.puty( l0 ) ; obj2.puty(20 ) ; cout << "x: "<< obj1.getx( ) << " " << obj2.getx( ) << endl ; cout << "y: "<< obj1.gety( ) <<" "<< obj2.gety( ) << endl ;
9.1.2 静态函数成员
– 静态函数成员是类中的一个函数,有static修饰。
– 静态函数成员和静态数据成员类似,在对象生成 之前也已经存在。这就是说在对象产生之前,静 态的函数成员就能访问其它静态成员。 – 类外代码可以使用类名和作用域操作符来调用静 态成员函数。 – 静态成员函数只能引用属于该类的静态数据成员 或静态成员函数。见例【例9-2】。
class Budget // Budget class declaration { static float corpBudget; float divBudget; public: Budget( ) { divBudget = 0; } void addBudget(float B) { divBudget += B; corpBudget += divBudget; } float getDivBudget( ) { return divBudget; } float getCorpBudget( ) { return corpBudget; } static void mainOffice( float ); friend void Aux::addBudget(float, Budget &); };
cout << "Here are the division budget requests:\n"; for (i = 0; i < 4; i++) { cout << "\tDivision " << (i + 1) << "\t\t\t "; cout << setw(7); cout << divisions[i].getDivBudget( ) << endl; cout << "\tAuxilary Office of Division " <<(i+1); cout << "\t"; cout << auxOffices[i].getDivBudget( ) << endl; } cout << "\tTotal Requests (including main office):"; cout << divisions[0].getCorpBudget( ) << endl;
6
// budget2.h文件的内容 。 class Budget { static float corpBudget; float divBudget; public: Budget( ) { divBudget = 0; } void addBudget( float b) { divBudget += b; corpBudget += divBudget; } static void mainOffice( float ); float getDivBudget( ) { return divBudget; } float getCorpBudget( ){ return corpBudget;} };
// Contents of budget3.cpp #include "budget3.h" // Definition of static member of Budget class float Budget::corpBudget = 0; // Definition of static member function mainOffice. void Budget::mainOffice(float moffice ) { corpBudget += moffice; }
// Contents of budget2.cpp #include "budget2.h" float Budget::corpBudget = 0 ;
// Definition of static member function. void Budget::mainOffice(float moffice) { corpBudget += moffice; }
cout << "\t Total Requests: "; cout << divisions[0].getCorpBudget( ) << endl; }
budget2.h budget2.cpp
9-2.cpp
1. 对于静态的函数成员,是通过类名和作用域分辨符 调用的。 2. 也可以采用对象点的方式调用
不采用友元 如何解决?
cout<< Distance(p1, p2) <<endl;
}
9-3.cpp
9.2.2 类的成员函数作为另外一个类的友元
其他类的成员函数声明为一个类的友元函数,这 个成员函数也称为友元成员。 友元成员不仅可以访问自己所在类对象中的私有
成员和公有成员,还可以访问friend声明语句所在类对
for (i = 0; i < 4; i++) { cout << "Enter the budget request for division "; cout << (i + 1) << ": "; cin >> bud; divisions[i].addBudget(bud); cout << "Enter the budget request for division"; cout << (i + 1) << "'s auxiliary office: "; cin >> bud; auxOffices[i].addBudget(bud, divisions[i]); }
象中的私有成员和公有成员,这样能使两个类相互合
作完成某一任务。
例:将Aux类的函数addBudget声明为Budget类的友元 函数。
15
class Budget ; // 对Budget类超前使用说明 class Aux // Aux类的定义 { private: float auxBudget ; public: Aux( ) { auxBudget = 0 ; } void addBudget( float , Budget & ) ; float getDivBudget( ) { return auxBudget ; } };
auxi1.h budget3.h auxi1.cpp budget3.cpp 9-3.cpp
9.2.3 一个类作为另外一个类的友元
• 若一个类为另一个类的友元,则此类的所有成员 都能访问对方类的私有成员。
class A { int x; friend class B; public: void Display( ){ cout<<x<<endl;} }; class B { A a; public: void Set(int i) { a.x = i; } void Display( ) { a.Display( ); } 23 };
Plz
// Contents of main program #include "budget3.h“ void main( ) { float amount; int i; float bud;
cout << "Enter the main office's budget: "; cin >> amount; Budget::mainOffice(amount); Budget divisions[4]; Aux auxOffices[4];
• 如果要统计一个班学生总数?
– 用类外的变量记录,违背了数据封装。 – 用类的一个数据成员记录,导致多个副本, 不仅冗余,而且势必造成数据不一致。
3
9.1.1 静态数据成员
1. 用关键字static声明;
2. 同一个类中的所有对象都共享该变量; 3. 必须在类外定义和初始化,用(::)来指明所属的类。 4. 静态变量不依赖于对象而存在,无论是否定义该类的 对象,这种类型的变量都存在。静态数据成员实际 上是在类外定义的一个变量,它的生存期和整个程 序的生存期一样,在定义对象之前,静态数据成员 就已经存在。
// Contents of auxi1.cpp #include "auxi1.h" #include "budget3.h"
// Definition of member function mainOffice. void Aux::addBudget(float b, Budget &div) { auxBudget += b; div.corpBudget += auxBudget; } Attention
4
class StaticDemo { static int x ; int y ; public: 理解它! void putx( int a){ x=a ; } void puty( int b ){ y=b ; } int get) { return y ; } }; int StaticDemo::x ; // 静态变量x将被StaticDemo类的所有对象共享,例如: StaticDemo obj1, obj2 ; obj1.putx(5) ; obj1.puty( l0 ) ; obj2.puty(20 ) ; cout << "x: "<< obj1.getx( ) << " " << obj2.getx( ) << endl ; cout << "y: "<< obj1.gety( ) <<" "<< obj2.gety( ) << endl ;
9.1.2 静态函数成员
– 静态函数成员是类中的一个函数,有static修饰。
– 静态函数成员和静态数据成员类似,在对象生成 之前也已经存在。这就是说在对象产生之前,静 态的函数成员就能访问其它静态成员。 – 类外代码可以使用类名和作用域操作符来调用静 态成员函数。 – 静态成员函数只能引用属于该类的静态数据成员 或静态成员函数。见例【例9-2】。
class Budget // Budget class declaration { static float corpBudget; float divBudget; public: Budget( ) { divBudget = 0; } void addBudget(float B) { divBudget += B; corpBudget += divBudget; } float getDivBudget( ) { return divBudget; } float getCorpBudget( ) { return corpBudget; } static void mainOffice( float ); friend void Aux::addBudget(float, Budget &); };
cout << "Here are the division budget requests:\n"; for (i = 0; i < 4; i++) { cout << "\tDivision " << (i + 1) << "\t\t\t "; cout << setw(7); cout << divisions[i].getDivBudget( ) << endl; cout << "\tAuxilary Office of Division " <<(i+1); cout << "\t"; cout << auxOffices[i].getDivBudget( ) << endl; } cout << "\tTotal Requests (including main office):"; cout << divisions[0].getCorpBudget( ) << endl;
6
// budget2.h文件的内容 。 class Budget { static float corpBudget; float divBudget; public: Budget( ) { divBudget = 0; } void addBudget( float b) { divBudget += b; corpBudget += divBudget; } static void mainOffice( float ); float getDivBudget( ) { return divBudget; } float getCorpBudget( ){ return corpBudget;} };
// Contents of budget3.cpp #include "budget3.h" // Definition of static member of Budget class float Budget::corpBudget = 0; // Definition of static member function mainOffice. void Budget::mainOffice(float moffice ) { corpBudget += moffice; }
// Contents of budget2.cpp #include "budget2.h" float Budget::corpBudget = 0 ;
// Definition of static member function. void Budget::mainOffice(float moffice) { corpBudget += moffice; }
cout << "\t Total Requests: "; cout << divisions[0].getCorpBudget( ) << endl; }
budget2.h budget2.cpp
9-2.cpp
1. 对于静态的函数成员,是通过类名和作用域分辨符 调用的。 2. 也可以采用对象点的方式调用
不采用友元 如何解决?
cout<< Distance(p1, p2) <<endl;
}
9-3.cpp
9.2.2 类的成员函数作为另外一个类的友元
其他类的成员函数声明为一个类的友元函数,这 个成员函数也称为友元成员。 友元成员不仅可以访问自己所在类对象中的私有
成员和公有成员,还可以访问friend声明语句所在类对
for (i = 0; i < 4; i++) { cout << "Enter the budget request for division "; cout << (i + 1) << ": "; cin >> bud; divisions[i].addBudget(bud); cout << "Enter the budget request for division"; cout << (i + 1) << "'s auxiliary office: "; cin >> bud; auxOffices[i].addBudget(bud, divisions[i]); }
象中的私有成员和公有成员,这样能使两个类相互合
作完成某一任务。
例:将Aux类的函数addBudget声明为Budget类的友元 函数。
15
class Budget ; // 对Budget类超前使用说明 class Aux // Aux类的定义 { private: float auxBudget ; public: Aux( ) { auxBudget = 0 ; } void addBudget( float , Budget & ) ; float getDivBudget( ) { return auxBudget ; } };