继承与多态
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
8.1.2 公有派生与私有派生
在派生类的定义中,基类前所加的访问限定符,对由 在派生类的定义中,基类前所加的访问限定符, 基类继承来的成员的访问作了进一步的限制。 基类继承来的成员的访问作了进一步的限制。有两方面含 派生类成员成员的访问, 义:派生类成员成员的访问,及从派生类对象之外对派生 类对象中的基类成员的访问。 类对象中的基类成员的访问。 1.公有派生 .基类的公有和保护成员的访问属性在派生 基类的公有和保护成员的访问属性在派生 类中不变, 成员不可访问。 类中不变,而基类的私有 成员不可访问。公有派生是 最常用的派生方式。 最常用的派生方式。 2.私有派生。基类中的公有成员和保护成员在派生类中 私有派生。 成为私有成员 3.保护派生。 保护派生。
第八章 继承与多态
8.1 继承与派生的概念
8. 5 MFC基础类及其层次结构 基础类及其层次结构
8.2 多重继承与派生类成员标识
8. 6 多态性与虚函数
8.3 虚基类
8. 7 MFC的消息映射与命令传递 的消息映射与命令传递
8.4 派生类应用讨论
8.1 继承与派生的概念
层次概念是计算机的重要概念。对类( 层次概念是计算机的重要概念。对类(class)分 ) 层,提供类型/子类型的关系,这是通过继承 提供类型 子类型的关系, 子类型的关系 (inheritance)的机制获得的。C++通过类派生 )的机制获得的。 通过类派生 (class derivation)的机制来支持继承。被继承的 )的机制来支持继承。 类型称为基类( 类型称为基类(base class)或超类(superclass), )或超类( ), 而新产生的类为派生类 派生类( 而新产生的类为派生类(derived class)或子类 ) (subclass),反映了事物之间的联系,事物的共性 ) 反映了事物之间的联系, 与个性之间的关系。从工作量上看,工作量少, 与个性之间的关系。从工作量上看,工作量少,重复 的部分可以从基类继承来,不需要单独编程。 的部分可以从基类继承来,不需要单独编程。
在派生类构造函数中, 在派生类构造函数中,只要基类不是缺省构造函数都要显式给出 基类名和参数表,除非基类使用默认的构造函数。 基类名和参数表,除非基类使用默认的构造函数。 析构函数的功能是作善后工作, 析构函数的功能是作善后工作,派生类析构函数只要把派生类新 增一般成员处理好就可以了。 增一般成员处理好就可以了。 析构函数各部分执行次序与构造函数相反, 析构函数各部分执行次序与构造函数相反,首先对派生类新增一 般成员析构,然后对新增对象成员析构,最后对基类成员析构。 般成员析构,然后对新增对象成员析构,最后对基类成员析构。
8.3 虚基类
这样在职研究生类的储存图参见图8.5,在Person的位置上放的 这样在职研究生类的储存图参见图 , 的位置上放的 是指针,两个指针都指向Person成员存储的内存。这种继承称为虚拟 是指针, 两个指针都指向 成员存储的内存。这种继承称为虚拟 成员存储的内存 继承(virtual inheritance)。在派生类对象的创建中,首先是虚基 继承( ) 在派生类对象的创建中, 类的构造函数被调用,并按它们被继承的顺序构造。 类的构造函数被调用 ,并按它们被继承的顺序构造 。 第二批是非虚基 类的构造函数按它们被继承的顺序调用。 类的构造函数按它们被继承的顺序调用 。 第三批是成员对象的构造函 数。最后是派生类自己的构造函数被调用。 最后是派生类自己的构造函数被调用。
8.1.3 派生类的构造函数与析构函数
派生类的构造函数的定义形式为: 派生类的构造函数的定义形式为: 派生类名::派生类名 参数总表) 基类名1( 派生类名::派生类名(参数总表):基类名 (参数表 ::派生类名( 1)《,基类名 (参数表 ), ……,基类名 (参数表 基类名2(参数表2) ) ,基类名n( n)》,《成员对象名 (成员对象参数表 ),……,成 成员对象名1(成员对象参数表1) ) , 员对象名m(成员对象参数表m) 员对象名 (成员对象参数表 )》{ ……//派生类新增成员的初始化; 派生类新增成员的初始化; 派生类新增成员的初始化 } 冒号后的基类名,成员对象名的次序可以随意, 冒号后的基类名,成员对象名的次序可以随意,这里 的次序与调用次序无关。在创建派生类对象时, 的次序与调用次序无关。在创建派生类对象时,系统会首 先使用各参数表中列出的参数, 先使用各参数表中列出的参数,调用基类和成员对象的构 造函数。 造函数。
8.1.3 派生类的构造函数与析构函数
派生类构造函数各部分的执行次序为: 派生类构造函数各部分的执行次序为: 1. 调用基类构造函数,按它们在派生类定义的先后顺序, 调用基类构造函数,按它们在派生类定义的先后顺序, 调用。 调用。 2. 调用成员对象的构造函数,按它们在类定义中声明的 调用成员对象的构造函数, 顺序,顺序调用。 顺序,顺序调用。 3. 派生类的构造函数体中的操作。 派生类的构造函数体中的操作。 顺序 先后
8.2 多重继承与派生类成员标识
椅子 床
沙发(单继承 沙发 单继承) 单继承
躺椅(多重继承 躺椅 多重继承) 多重继承 两用沙发(多重继承 两用沙发 多重继承) 多重继承 椅子, 图8.3 椅子,床到两用沙发
8.2 多重继承与派生类成员标识
必须解决唯一标识问题。 多重继承 ,必须解决唯一标识问题。通常采用作 用域分辨符: 用域分辨符: 基类名::成员名; 数据成员 基类名::成员名;//数据成员 ::成员名 wk.baidu.com类名::成员名(参数表);//函数成员 基类名::成员名(参数表); 函数成员 ::成员名 ); 用域分辨符是不能嵌套使用的, 用域分辨符是不能嵌套使用的,不可连续使用多 个作用域分辨符
8.1.3 派生类的构造函数与析构函数
【例8.1】由在册人员类公有派生学生类。 】由在册人员类公有派生学生类。 我们希望派生类总是和基类保持一致, 我们希望派生类总是和基类保持一致, 原有的成员和访问方 式被保留,这只能采用公有派生来实现 这只能采用公有派生来实现。 式被保留 这只能采用公有派生来实现。在私有派生时要保持接口 不变,则要在派生类中重编接口,去调用基类接口成员函数 去调用基类接口成员函数。 不变,则要在派生类中重编接口 去调用基类接口成员函数。所以 绝大多数场合总是用公有派生。 绝大多数场合总是用公有派生。 本例只是为了演示派生类的定义与使用, 本例只是为了演示派生类的定义与使用,尽可能顾及最常用 的各方面。 的各方面。继承性可以重复使用已经编译好的代码和已设计好的 数据结构,避免代码和数据结构的重复设计。 数据结构,避免代码和数据结构的重复设计。面向过程程序设计 层次概念使程序易读易懂,在面向对象的程序中, 层次概念使程序易读易懂,在面向对象的程序中,继承也显示了 一个层次性,使程序更加易读易懂,便于维护。 一个层次性,使程序更加易读易懂,便于维护。
8.1.1 类的派生与继承
派生出来的新类同样可以作为基类再继续派生出更新 的类,依此类推形成一个层次结构。 的类,依此类推形成一个层次结构。直接参与派生出某类 称为直接基类,而基类的基类, 称为直接基类,而基类的基类,以及更高层的基类称为间 接基类。 接基类。 在派生类的声明中,还有访问控制,亦称为继承方式, 在派生类的声明中,还有访问控制,亦称为继承方式, 是对基类成员进一步的限制。访问控制也是三种: 是对基类成员进一步的限制。访问控制也是三种:公有 (public)方式,保护(protected)方式和私有 )方式,保护( ) (private)方式,亦称公有继承、保护继承和私有继承。 )方式,亦称公有继承、保护继承和私有继承。 如不显式给出访问控制关键字,则默认为私有继承 如不显式给出访问控制关键字, 编制派生类时可分四步。首先吸收基类的成员;第二 编制派生类时可分四步。首先吸收基类的成员; 步是改造基类成员,称为同名覆盖(override)。第三 步是改造基类成员,称为同名覆盖( )。第三 )。 步发展新成员;第四步是重写构造函数与析构函数。 步发展新成员;第四步是重写构造函数与析构函数。
教师(单继承 教师 单继承) 单继承
工人(单继承 工人 单继承) 单继承
行政人员(单继承 行政人员 单继承) 单继承
研究生(单继承 研究生 单继承) 单继承
行政人员兼教师 (多重继承 多重继承) 多重继承
研究生助教 (多重继承 多重继承) 多重继承
在职研究生 (多重继承 多重继承) 多重继承
图8.2 大学在册人员继承关系
8.2 多重继承与派生类成员标识
【例8.2】由圆和高多重继承派生出圆锥。 】由圆和高多重继承派生出圆锥。 程序: 程序:Ex8_2.cpp
8.3 虚基类
给出class Person有两个拷贝,而实际上这是重复的, 有两个拷贝, 图8.4(b)给出 给出 有两个拷贝 而实际上这是重复的, 这个共同基类设置为虚基类, 把class Person这个共同基类设置为虚基类,这样从不同路径继承 这个共同基类设置为虚基类 来的同名数据成员在内存中就只有一个拷贝,同名函数也只有一种 来的同名数据成员在内存中就只有一个拷贝,同名函数也只有一种 映射。虚基类( 映射。虚基类(virtual base class)定义方式如下: )定义方式如下: class 派生类名 派生类名:virtual 访问限定符 基类类名 基类类名{...}; class 派生类名 访问限定符 virtual 基类类名 派生类名:访问限定符 基类类名{...}; 学生类定义: 学生类定义 class Student::virtual public Person{...}; 教职工类定义: 教职工类定义 class Employee::virtual public Person{...};
8.1.2 公有派生与私有派生
派生方式 基类中的访问限定 在派生类中对基类成员 的访问限定 public protected 不可直接访问 private private 不可直接访问 表8.1 公有派生和私有派生 在派生类对象外访问派 生类对象的基类成员 可直接访问 不可直接访问 不可直接访问 不可直接访问 不可直接访问 不可直接访问 public 公有派生 protected private public 私有派生 protected private
8.1 继承与派生的概念
8.1.1 类的派生与继承
8. 1.2 公有派生与私有派生
8. 1.3 派生类的构造函数与析构函数
8.1.1 类的派生与继承
由基类派生出派生类的定义的一般形式为 class 派 生 类名 : 访 问 限 定 符 基 类 名 1《 , 访 问 限 定符 基 类 名 类名 《 2,……,访问限定符 基类名 》 基类名n》 , , { 《 《private: 》 成员表1; 成员表 ;》//派生类增加或替代的私有成员 派生类增加或替代的私有成员 《public: 成员表2; 成员表 ;》//派生类增加或替代的公有成员 派生类增加或替代的公有成员 《protected: 成员表3;》//派生类增加或替代的保护成员 成员表 ; 派生类增加或替代的保护成员 } 其中基类1,基类 , 是已声明的类。 其中基类 ,基类2,……是已声明的类。 是已声明的类
第八章 继承与多态
继承( 继承(inheritance)机制是面向对象程序设计使代 )机制是面向对象程序设计使代 码可以复用的最重要的手段, 码可以复用的最重要的手段,它允许程序员在保持原有类 调整部分成员的特性, 特性的基础上 ,调整部分成员的特性,也可以增加一些新 成员。 成员。 多态性( 多态性(polymorphism)也是面向对象程序设计的 ) 标志性特征。多态性是考虑在不同层次的类中, 标志性特征。多态性是考虑在不同层次的类中,以及在同 一类中,同名的成员函数之间的关系问题。函数的重载, 一类中,同名的成员函数之间的关系问题。函数的重载, 运算符的重载,都属于多态性中的编译时的多态性。 运算符的重载,都属于多态性中的编译时的多态性。运行 时的多态性,这是以虚基类为基础的多态性。 时的多态性,这是以虚基类为基础的多态性。
程序: 程序:Ex8_1.cpp
8.2 多重继承与派生类成员标识
由多个基类共同派生出新的派生类, 由多个基类共同派生出新的派生类,称为多重继承或多继承 (multiple-inheritance) 。 )
在册人员
教职工(单继承 教职工 单继承) 单继承
学生(单继承 学生 单继承) 单继承
兼职教师(单继承 兼职教师 单继承) 单继承