继承是软件可重用性的一种形式,新类通过继承的方式,从现有的类中吸收其属性和行为,并对其进行覆盖或者改写,产生新类所需要的功能。
派生类可以增加自己的数据成员和成员函数,因此派生类比基类更加强大,派生类由于代表更小的一组对象,因此比基类更加具体,利用简单继承派生出来的派生类开始与基类的本质是一样的,继承真正的优越性来自于派生类中定义对基类特征的追加、替代和精简。
C++提供三类继承:public、protected、private,public继承产生的派生类,它的每个对象也可被认为是这个派生类对应的基类的一个对象,反之则不然,基类对象不是该基类的派生类的对象,利用“派生类对象是基类对象”的原则可以执行一系列有趣的操作,可利用继承将大量不同却相关的对象串联成衣系列相关联的基类对象,这样,大量的对象就可以用统一的方法来处理。
protected成员访问控制符,派生类成员函数及其友元函数可以访问protected基类成员。
C++提出一种非常著名的“透过现象看本质”的思想,其中一个具体的实现就是“抽象”,即提出基类和派生类的概念。
这里提出“是一”和“有一”的概念,“是一”的关系是继承,即派生类的对象是基类的对象,“有一”的关系是合成,该类的对象有一个或多个对象作为它的成员;
派生类不能访问基类的private成员,这样违反了类的封装性,派生类可以访问基类的protected和public成员,继承时,基类中不能被派生类访问的成员定义为private,派生类只有通过基类提供的public和protected成员函数来访问这些成员。
派生类继承public成员函数不需要有明确的声明,当一个基类的成员不适合该派生类时,可以在派生类中以合适的方式重载它。
1.public继承
a.形式:class CommissionWorker:public Employee{
... ...
};
基类中的public和protected成员(包括数据成员和成员函数)分别被继承为派生类的public和protected成员,基类的private成员派生类不能访问,基类的友元函数也不能被继承。
完全可以把基类对象和派生类对象看成是相似的,而这些共同点就表现在基类的属性和行为中,任何一个从同一个基类通过public继承派生成的类的对象都可以看作是这个基类的对象(注意一定要是public继承)。
2.成员访问控制符protected
基类的public成员(无论是数据成员还是成员函数)允许程序中的所有函数访问;
基类的private成员(无论是数据成员还是成员函数)只允许该类的成员函数和友元函数访问;
基类的protected成员,允许基类的成员函数和友元函数访问,也允许派生类的成员函数和友元函数访问。
派生类的成员引用基类的public或者protected成员时只需要引用名称即可。
3.基类指针向派生类指针的强制类型转换(派生类向基类是隐式转换,不需要强制类型转换)
public派生类可以视为基类的对象,尽管从一个基类可以派生出很多派生类,这些派生类有各自的对象,但是仍可以将这些对象视为基类的对象,仍可以将他们创建一个链表,而基类的对象不能自动强制转换为派生类对象。
经常显式将基类指针强制转换为派生类指针,向下强制转换指针类型,显式将一个基类类型的指针转换成为一个派生类类型的指针,然后用这个指针引用基类对象中不存在的成员,回导致运行时错误。
在public继承中,基类的protected成员和public成员分别被子类继承,即子类的publice成员包括父类的public成员,protected成员包括父类的protected成员,子类的定义中不必显式声明,直接调用即可。
通过public继承,可以将派生类指针付给基类指针,基类指针看起来只是派生类的基类部分,编译器执行派生类指针想基类指针的隐式转换。基类指针虽然只显示派生类的基类部分,但是基类指针始终指向派生类对象,当把基类指针显式强制转换成派生类指针时,还是可以显示出派生类的全部信息。
基类指针不能直接赋值给派生类指针,编译器不会执行隐式转换,可以使用显示转换,显示转换后,调用基类中不存在的数据成员不会有危险,但是调用不存在的成员函数可能会使程序崩溃。
4.在派生类中改写基类成员
派生类中可以改写基类的成员函数,只要采用相同的签名即可,如果签名不同,是函数重载(函数名相同,参数列表不同),在派生类传名调用函数时,会自动选择派生类,派生类需要访问基类版本的成员函数时,需要使用作用域分辨符。
5.三类继承方式:public protected private
只有public继承,基类的publc成员和protected成员分别被子类继承为public成员和protected成员,派生类对象是一种基类对象,存在“是一”关系,private(所有都继承为private类型)和protected(所有都继承为protected类型)继承不是“是一”关系的继承
6.派生类中的构造和析构函数
派生类继承了基类的成员,因此实例化派生类的对象时,需要调用基类的构造函数,用于初始化派生类对象中的基类成员,基类的初始化程序可以在派生类的构造函数中显式调用,否则调用基类的默认构造函数。
基类的构造函数和基类的赋值操作符不能被派生类继承,但派生类的构造函数和赋值操作符可以调用基类的构造函数和赋值操作符。
创建了一个派生类对象,基类和派生类都包含其他类的对象,创建派生类的对象时,首先执行基类成员对象的构造函数,其次是基类的构造函数,然后是派生类的成员对象的构造函数,最后是派生类的构造函数,析构函数的调用顺序刚好相反(成员对象的构造顺序与其在类中的声明顺序一致)。
7.继承
思想:从现有的类继承属性和行为,然后增加属性和行为定制类以满足我们的实际要求,创建派生类不会英系那个基类的源代码,基类的完整性可以得到保证。