继承和派生
来源:互联网 发布:窗帘拼布算法 编辑:程序博客网 时间:2024/05/29 15:54
继承、多态和封装是面向对象的三大特性
一、什么是继承?
1.继承概念
继承:面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行拓展,增加功能。 比如你和你父母就会有很多地方很像,但是你也有自己的特点,你只是继承了父母的一部分特性。
2.继承定义格式(派生类的书写格式):
class 派生类(子类)名称:继承类型 基类(父类)名称继承类型:基类成员在派生类中的可见性继承类型有:public(公有继承) protected(受保护继承) private(私有继承) 在这里呢,我们要把类中成员的访问限定符与继承类型分清。public、protected和private作为类成员访问限定符时: public修饰类成员时,表示此成员是公有的,可以在类外访问 protected和private修饰类成员时表示此成员在类外不能进行访问,只能在类内访问
3.基类成员在派生类中的访问属性:
由表可知:
(1) 无论是那种继承方式,基类的私有成员在派生类中都不可见,在派生类中都可以访问基类的公有成员和受保护的成员,只是会因为继承方式不同而引起权限发生变化。
(2)在实际应用中都会采取public继承,不太采取protected和private继承
(3)权限变化依次减小:public–>protected–>private,在继承时,权限会因为继承方式的不同而发生改变,会由大权限变为小权限,例如:在继承关系为protected时,public类成员会变为protected成员。
二、派生类
1、派生类是什么?
继承基类的类就被称为派生类(子类) 派生类也会有六个默认的成员函数:构造函数、拷贝构造函数、析构函数、赋值操作符重载、取地址操作符重载、const修饰的取地址操作符重载
2.在继承体系中基类和派生类的构造函数和析构函数的调用次序
构造函数: 调用派生类的构造函数--->调用基类的构造函数(在派生类构造函数的初始化列表第一条语句位置)--->初始化派生类自己的成员--->执行派生类构造函数的函数体析构函数: 调用派生类的析构函数--->销毁派生类自己管理的资源--->调用基类的析构函数(在派生类析构函数的函数体中的最后一条语句位置)--->销毁基类管理的资源 编译器给派生类合成默认构造函数的情况: 在继承人体系中,如果基类中存在缺省的构造函数,派生类的构造函数没有显式的给出,,编译器会给派生类合成一个默认的构造函数
3.继承体系中的作用域
1.在继承体系中,基类和派生类是两个不同的作用域,由此也进一步证明 ,基类的私有成员,无论在那种继承体系下都不能在派生类中访问。 2.在继承体系中,基类和派生类中如果存在相同名字的成员,如果使用派生类对象调用此成员,会优先调用派生类中存在的成员,把基类中存在的隐藏掉---->同名隐藏 相同名字的成员:同名成员变量、同名成名函数(与变量和函数的类型无关,只要是相同名字就好) 所以,不要在继承体系中使用相同名字的成员
4.继承与派生之间的关系—>赋值兼容规则
三、继承的分类
继承分为单继承、多继承、菱形继承(钻石继承)
单继承
一个基类对应一个派生类,它们之间的关系是一对一
单继承的对象模型
多继承
一个派生类对应多个基类,它们之间的关系是一对多
多继承的对象模型
这里对象模型中基类的顺序是按照派生类继承基类时的顺序排列的,比如这里基类1就是Student类,基类2就是Teacher类,因为Graduate先继承Student类,所以基类1就是Student类
菱形继承
单继承和多继承的结合
由图可见:Student类和Teacher类分别单继承Person类,Graduate类多继承Student类和Teacher类
#include<stdlib.h>#include<iostream>using namespace std;class Person{public: int _p;};class Student :public Person{private: int _s;};class Teacher:public Person{private: int _t;};class Graduate :public Student, public Teacher{public: int _g;};int main(){ Graduate g; Person p; g._p = 0;//二义性问题,此时编译器就会报错,_p指代不明确 system("pause"); return 0;} Graduate中有两份Person类中的成员,当访问Person类中的成员时,不知道该访问Student类中的,还是Teacher类中的,因为Student和Teacher分别单继承Person类,它们都把Person类中的成员继承了。所以,菱形继承会存在二义性和数据冗余问题。
那应该怎么解决菱形继承中存在的二义性和数据冗余问题呢?
虚继承很好的解决了这个问题,那什么是虚继承呢?
虚继承:是面向对象编程中的一种技术,是指一个指定的基类,在继承体系中,将其成员数据实例共享给也从这个基类直接或间接派生的其他类。简单来说就是会使指定基类中的成员在整个继承体系中只存在一份。
虚继承和单继承的比较:
虚拟继承多的四个字节是:指向偏移量表格的指针
偏移量表格
菱形虚拟继承很好的解决了菱形继承中存在的二义性(某数据在继承体系中保存了两份,编译器在访问时不知道该访问那个)问题
那什么是菱形虚拟继承呢?
菱形虚拟继承的对象模型:
例如:
如下表:总大小为20个字节,4个int,所有的偏移量表格占四个字节,总共20个字节
第一个偏移量表格的终地址为相对于整个对象大小的偏移量,终值是20
第二个偏移量表格的终地址为相对于整个对象大小的偏移量,终值是12
为什么菱形虚拟继承可以解决菱形继承中存在的二义性问题呢?
虚拟继承把具有二义性的数据(此例是Person类)放在类的其他成员之后,这样在整个继承体系中就只保存了一份,这样再访问Preson类中的数据时,就不会出现多种选择,只有一种选择(即某数据在继承体系中只会保存一份)
- 派生和继承
- 继承和派生类
- 派生和继承
- 继承和派生
- 派生和继承
- 继承和派生
- 继承和派生
- 继承和派生
- Android_继承和派生
- VC_继承和派生
- C++ 继承和派生
- 继承和派生
- C++继承和派生
- 继承和派生
- 继承和派生
- 继承和派生
- 继承和派生
- 继承和派生1
- redis源码分析之事务Transaction(上)
- SolidWorks Inspection质检部门的福音
- String类split方法
- debug python in ipython
- ps学习第1天,cs6界面 图层
- 继承和派生
- Ajax与后台的交互
- Glide学习笔记
- redis源码分析之事务Transaction(下)
- Vue学习日志:初识VUE(1)
- 你真正了解Radmax和Radtube嘛?
- C++——装载问题
- 计算机网络第四章测试 网络层
- netty(一):数据流分析