类和对象 多态 运算符重载
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
返回
16
void main() { Shape *p; Triangle t; Rectangle r; p=&t; p->set(5.1,10); p->area(); p=&r; p->set(5.1,10); p->area(); }
返回
17
应用举例
例12-4
返回
18
上机题
应用抽象类,求圆、圆内接正方形和圆外切正方 形的面积和周长。 提示: 定义一个抽象类shape,在其中定义纯虚函数area ()和perimeter()
15
class Triangle: public Shape { public: void area() { cout<< "三角形面积: " <<0.5*x*y<<endl; } }; class Rectangle: public Shape { public: void area() { cout<<"矩形面积:" <<x*y<<endl; } };
例12-2
返回
4
虚函数
virtual <类型说明符 ><函数名>(<参数表>) 即在类的说明中,在函数原型之前加virtual。 注意: • virtual 只用在类定义的原型说明中,不能用在函数实 现中。 • 具有继承性,基类中定义了虚函数,派生类中无论是 否说明,同原型函数都自动为虚函数。 • 本质:不是重载定义而是覆盖定义。 • 调用方式:通过基类指针或引用,执行时会根据指针 指向的对象的类,决定调用哪个函数。
十二章 多态性与虚函数
12.1 多态性 学生 教师
消息:调用函数
新学期开学
方法:函数
家长
后勤人员
多态性就是向不同的对象发送同一个消息,不同的对象 在接收时会产生不同的行为(方法)。或者说,每个对象 可以用自己的方式去响应共同的消息。 返回
1
两种多态性
编译时的多态:静态多态性 运行时的多态:动态多态性
在程序编译的时候就能 决定调用的是哪一个函 数,因此也称为静态多态性
在程序运行的过程中动态 的确定操作所针对的对象, 因此也称为动态多态性
运算符重载和函数重载
虚函数
例12-1
返回
2
虚函数
同一个类中,不能定义两个名字相同、参数个数和类型都相 同的函数,否则是重复定义。 在类的继承层次结构中,不同的层次中可以出现名字相同,参 数个数和类型都相同的功能不同的函数。 cy.area( ) 调用派生类的成员函数area( )
返回
9
虚析构函数
当撤消派生类的对象时,先调用派生类析构函数, 然后自动调用基类析构函数,如此看来析构函数没 必要定义为虚函数。但是,假如使用基类指针指向 其派生类的对象,而这个派生类对象是用new运算创 建的。当程序使用delete运算撤消派生类对象时,结 果会如何呢?
一个简单的例题:例12-3
返回
返回
14
应用举例
例1. 设计一个抽象类shape,它表示具有形状的东西, 体现了抽象的概念,在它下面可以派生出多种具体形 状,比如三角形、矩形。 #include<iostream.h> class Shape { protected: double x,y; public: void set(double i, double j) { x=i; y=j; } virtual void area()=0; //声明纯虚函数 }; 返回
不能!因为在执行构造函数时类对象还未完成建立 过程,当然谈不上函数与类对象的绑定。 返回
12
纯虚函数
纯虚函数是在基类中只声明虚函数而不给出具体的 函数定义体,将它的具体定义放在各派生类中,称此 虚函数为纯虚函数。通过该基类的指针或引用就可以 调用所有派生类的虚函数,基类只是用于继承,仅作 为一个接口,具体功能在派生类中实现。 纯虚函数的声明如下: virtual 函数原型=0; 其中:函数原型的格式同前面所学格式一样,要包括 函数返回值的类型、函数名、圆括号、形参及其类型 等
返回
19
返回
5
静态关联与动态关联
关联(联编)的含义是指把一个消息和一个方法联系在 一起,也就是把一个函数名与其实现代码联系在一起
静态关联:在编译时即可确定其调用的虚函数 属于哪一个类,其过程称为静态关联,或者称 为早期关联。 动态关联:在运行阶段把虚函数和类对象 绑定在一起,其过程称为动态关联,或者 称为滞后关联
ቤተ መጻሕፍቲ ባይዱ
10
这时只调用了基类的析构函数,而没有调用派 生类的析构函数。 如果使用虚析构函数,无论指针所指的对象是 基类对象还是派生类对象,程序执行时都会调用对 应的析构函数。
返回
11
虚析构函数的应用场合:
主要用于:如果用new运算符建立了临时对象,若 基类中有析构函数,并且定义了一个指向该基类 的指针变量。在程序用带指针参数的delete运算 符撤销对象时,会发生一个情况: 系统会只执行 基类的析构函数,而不执行派生类的析构函数。 原因:p是指向基类的指针变量,指向new开辟的 动态存储空间,detele释放该空间。 构造函数能声明为虚函数吗?
cy.Circle::area( ) 调用基类Circle中的成员函数() 能否采用同一调用形式,既能调用基类又能调用派生 类的同名函数?
返回
3
虚函数
虚函数的作用是允许在派生类中重新定义与基类同名的 函数,并且可以通过基类指针或引用来访问基类和派生 类中的同名函数。
程序中不是通过不同的对象名去调用不同派生层次中 的同名函数,而是通过指针调用它们。
返回
6
关于虚函数的注意事项:
• 只能用virtual声明类的成员函数,使它成为虚函数, 而不能将类外的普通函数声明为虚函数 • 一个成员函数被声明成虚函数以后,同一类族中不能 再定义一个非virtual的但与该虚函数具有相同参数 (包括个数和类型)和函数返回值类型的同名函数。 • 虚函数的函数体可以是空的,具体的功能由派生类添 加。
返回
13
抽象类
声明了纯虚函数的类,称为抽象类。 使用纯虚函数时应注意: (1)抽象类中可以有多个纯虚函数。 (2)不能声明抽象类的对象,但可以声明指向抽象类 的指针变量和引用变量。 (3)抽象类也可以定义其他非纯虚函数。 (4)如果派生类中没有重新定义基类中的纯虚函数,则在派生类中 必须再将该虚函数声明为纯虚函数。 (5)从抽象类可以派生出具体或抽象类,但不能从具体类派生出抽 象类。 (6)在一个复杂的类继承结构中,越上层的类抽象程度越高,有时 甚至无法给出某些成员函数的实现,显然,抽象类是一种特殊的 类,它一般处于类继承结构的较外层。 (7)引入抽象类的目的,主要是为了能将相关类组织在一个类继承 结构中,并通过抽象类来为这些相关类提供统一的操作接口。
返回
7
在什么情况下声明虚函数
• 成员函数所在的类是否为基类,且在其派生类 中是否希望被更改功能 • 是否通过基类指针或引用去访问。
返回
8
虚函数与重载函数的比较
(1)重载函数要求函数有相同的函数名称,并有不同的 参数序列;而虚函数则要求这三项(函数名、返回值 类型和参数序列)完全相同; (2)重载函数可以是成员函数或友员函数,而虚函数只 能是成员函数; (3)重载函数的调用是以所传递参数序列的差别作为调 用不同函数的依据;虚函数是根据对象的不同去调用 不同类的虚函数; (4)虚函数在运行时表现出多态功能,这是C++的精髓; 而重载函数则在编译时表现出多态性。