C++进阶部分之继承
1.继承的概念和定义1.1继承的概念继承机制是面向对象程序设计使代码可以复用的最重要的手段它允许我们在保持原有类特性的基础上进行扩展增加方法成员函数和属性成员变量这一产生新的类称为子类。继承呈现了面向对象程序设计的结构以下面这两个类举例我们很容易注意到这两个类有重复部分这时我们就可以把公共的信息提取出来放到person类里面就不需要去重复定义了1.2继承定义1.2.1定义格式下面我们看到Person是父类也称作基类。Student是子类也称作派生类1.父类的private成员在子类中无论以什么方式继承都是不可见的不可见的意思是被继承了但是不能通过任何方式访问2.父类private成员在子类中是不能被访问如果父类成员不想在类外直接被访问但需要在子类中能被访问就定义为protected3.父类其他成员在子类的访问方式 Min(成员在父类的访问限定符继承方式)4.使用class的默认继承方式是private使用struct的默认继承方式的public5.实际运用时一般都是使用public继承很少使用protected和private1.3继承类模板2.父类和子类赋值兼容转换1.public继承在公有继承的前提下的子类对象可以赋值给父类的对象/父类的指针/父类的引用赋值只能赋值从父类继承的部分不能赋值子类独有的部分2.父类对象不能赋值给子类对象3.父类的指针或者引用可以通过强制类型转换赋值给子类的指针或引用但是必须是父类的指针是指向子类对象时才是安全的从这里就能看出继承下的变量是同一类型无需进行类型转换而下面的那个必须进行类型转换才能绑定引用引用必须绑定在一个内存中真实存在的数据就是无需进行类型转换之类的操作立马就有的数据3.1继承中的作用域3.1隐藏规则1.在继承体系中父类和子类都有独立的作用域2.子类和父类中有同名成员子类成员将屏蔽父类对同名成员的直接访问这种情况叫做隐藏在子类成员函数中可以使用父类父类成员显示访问3.需要注意的是如果是成员函数的隐藏只需要函数名相同就构成隐藏4.注意在实际中继承体系里面最好不要定义同名的成员4.子类的默认成员函数4.1 4个常见的默认成员函数默认成员构造函数的意思就是我们不写会自动生成一个1.子类的构造函数必须调用父类的构造函数初始化父类的那一部分成员如果父类没有默认构造函数则必须在子类构造函数的初始化阶段显示调用必须这样显示调用2.子类的拷贝构造函数必须调用父类的拷贝构造完成父类的拷贝初始化3.子类的operator必须要调用父类的operator完成父类的复制需要注意的是子类的operator隐藏了父类的operator所以显示调用父类的operator需要指定父类作用域4.2实现一个不能被继承的类方法一父类的构造私有子类的构成必须调用父类的构造函数但是父类的构造函数私有化后子类看不见就不能调用了那么子类就无法实例化出对象方法二C11新增关键字finalfinal修改父类子类就不能继承了5.继承与友元友元关系不能继承也就是父类的友元不能访问子类的私有成员补充友元函数. 三种形式友元全局函数授权一个普通的全局函数来访问类的内部数据。友元类授权整个类使其所有成员函数都能访问当前类的私有成员常用于紧密耦合的类如容器与迭代器。友元成员函数只授权另一个类中的某一个特定成员函数。. 三大铁律单向性A 是 B 的友元不代表 B 是 A 的友元。不传递A 是 B 的友元B 是 C 的友元不代表 A 能访问 C。不继承基类的友元不会自动成为派生类的友元。6.继承与静态成员父类定义了static静态成员则整个继承体系里面只有一个这样的成员无论派生出多少个子类都只有一个static成员实例7.多继承以及菱形继承问题单继承一个子类只有一个直接父类时称这个继承关系为单继承多继承一个子类有两个或以上直接父类时称这个继承关系为多继承多几次对象在内存中的模型是先几次父类在前面后面几次的父类在后面子类成员放到最后面菱形继承菱形继承是多继承的一种特殊情况会出现数据冗余和多义性的问题7.2虚继承这个一定要给两份及以上使用虚继承就是virtual就可以解决这个问题在内存中值保留一份共享的基类成员让基类成员不再报错解决了二义性的问题还有一点在普通继承中每个类负责调用自己直接父类的构造函数。但在虚继承中为了保证基类只被初始化一次虚基类的构造函数必须由继承体系中最底层的那个类最派生类直接调用和初始化注意这个不能随便乱用虚拟继承付出了不小的代价在初始化方面容易错乱很容易出错8.继承和组合1.public继承是一种is-a的关系也就是说每一个子类对象都是一个父类对象2.组合是一种has-a的关系假设B组合了A每一个B对象中都有一个A对象3.继承允许你根据父类的实现来定义子类的实现这种通过生成子类的复用通常为称为白箱复用在继承方式中父类内部的细节对子类可见。继承一定程度破坏了父类的封装父类的改变对子类有很大的影响。子类和父类之间依赖关系强耦合度高对象组合是类继承之外另外一种复用选择新的更复杂的功能可以通过组装或者组合对象来获得。对象组合要求被组合的对象具有良好定义的接口这种复用被称为黑箱复用因为对象内部细节是不可见的所以组合之间没有很强的依赖关系耦合度低优先使用对象组合有利于保持每一个类的封装耦合度程序之间互相依赖和连接的紧密度高内聚让模块内部的各个元素紧密相关专注于完成单一、明确的功能。低耦合高内聚以上面为例继承中栈是一种特殊的链表组合中栈里面有一个链表