第七章继承和派生

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

C++自考资料1第七章继承和派生一、基类和派生类1.在C++中,可以从一个类派生出另一个类,前者称为基类或父类,后者称为派生类或子类。一个派生类可以从一个或多个基类派生。从一个基类派生的继承称单继承,从多个基类派生的继承称多继承。2.单继承定义格式:class派生类:继承方式基类{派生类新定义成员;};其中,“派生类”是从“基类”按指定的“继承关系”派生出的、新定义的一个类的名字。“继承方式”有三种:(1)public公有继承(2)private私有继承(3)protected保护继承3.多继承定义格式:class派生类:继承方式1基类1,继承方式2基类2,…{派生类新定义成员;};4.公有继承:当派生类的继承方式是public继承时,基类的public和protected成员的访问属性在派生类中保持不变,而基类的private成员不可访问,即基类的public和protected成员分别作为派生类的public和protected成员,派生类的其他成员可以直接访问它们。例1:classB{private:intx;protected:inty;public:intz;…};classA:publicB{private:inta;protected:intb;public:intc;…};Aa;(1)类B是基类,有3个数据成员x、y、z,分别是private、protected、public属性。类A是派生类,有3个数据成员a、b、c,分别是private、protected、public属性。由于类A是从类B公有派生的,类B中的public、protected属性的成员可继承到类A中来,且保持原来的属性。故类A中有5个数据成员,即a、b、c、y。(2)可以通过类A的对象a直接访问public成员,即z和c,并不能访问a、b、y数据成员。(3)不考虑派生类时,类中的private和protected属性的成员都可以被类的成员函数访问,而都不能被该类的对象直接访问。在派生类中,当公有继承时,基类中protected属性的成员可以作为派生类的protected属性的成员,而private属性的成员不能作为派生类的成员。5.保护继承:当派生类的继承方式是protected继承时,基类的public和protected成员可以被继承到派生类中,但访问属性都变成protected,而基类的private成员不可访问,即基类的public和protected成员都作为派生类的protected成员,派生类的其他成员可以直接访问它们。例2:classB{private:intx;protected:inty;public:intz;…};classA:protectedB{private:inta;protected:intb;public:intc;…};Aa;类B是基类,有3个数据成员x、y、z,分别是private、protected、public属性。类A是从类B保护派生的,类B中的protected、public属性的成员可继承到类A中,均变成protected属性。故类A中有5个数据成员,即a、b、c、y、z。可以通过类A的对象a直接访问public成员,即c,不能访问a、b、y、z数据成员。6.私有继承:当派生类的继承方式是private继承时,基类的public和protected成员可以被继承到派生类中,但访问属性都变成private,而基类的private成员不可访问,即基类的public和protected成员都作为派生类的private成员,派生类的其他成员可以直接访问它们。例3:classB{private:intx;protected:inty;public:intz;…};classA:privateB{private:inta;protected:intb;public:intc;…};Aa;类B是基类,有3个数据成员x、y、z,分别是private、protected、public属性。类A是从类B私有派生的,类B中的protected、public属性的成员可继承到类A中,均变成private属性。故类A中有5个数据成员,即a、b、c、y、z。可以通过类A的对象a直接访问public成员,即c,不能访问a、b、y、z数据成员。C++自考资料2二、单继承1.在单继承中,每个类可以有多个派生类,但是每个派生类只能有一个基类,从而形成树形结构。2.构造函数不能被继承,故派生类的构造函数必须通过调用基类的构造函数来初始化基类子对象。在定义派生类的构造函数时,除了要对自己的数据成员进行初始化,还要调用基类构造函数使基类的数据成员得以初始化。若派生类中还有子对象,应包含对子对象初始化的构造函数。3.派生类构造函数一般格式:派生类名(派生类构造函数总参数表):基类构造函数(参数表1),子对象名(参数表2){派生类中数据成员初始化;};4.派生类构造函数调用顺序:(1)基类的构造函数;(2)子对象类的构造函数(有的话);(3)派生类构造函数。例4:classA{public:A(){cout”AConstructor”endl;}};classB:publicA{public:B(){cout”BConstructor”endl;}};voidmain(){Bb;}执行结果为:AConstructorBConstructor5.当对象被删除时,派生类的析构函数被执行。析构函数也不能被继承,故在执行派生类的析构函数时,基类的析构函数也将被调用。析构函数的执行顺序是先执行派生类的析构函数,再执行基类的析构函数。例5:classA{public:A(){cout”AConstructor”endl;}~A(){cout”ADestructor”endl;}};classB:publicA{public:B(){cout”BConstructor”endl;}~B(){cout”BDestructor”endl;};voidmain(){Bb;}执行结果为:AConstructorBConstructorBDestructorADestructor6.派生类构造函数的定义中可以省略对基类构造函数的调用,条件是在基类中必须有默认的构造函数或根本没有定义构造函数。7.当基类的构造函数使用一个或多个参数时,则派生类必须定义构造函数,提供将参数传递给基类构造函数的途径。有的情况下,派生类构造函数的函数体可能为空,仅起到参数传递的作用。三、多继承1.多继承是指派生类具有多个基类,派生类和每个基类间的关系仍可看作一个单继承。如:classA{…};classB{…};classC:publicA,publicB{…};其中派生类C具有两个基类,故为多继承。派生类C的成员包含了基类A和基类B中的成员和它本身的成员。2.多继承派生类的构造函数格式:派生类名(总参数表):基类名1(参数表1),基类名2(参数表2),…基类名n(参数表n),子对象名(参数表n+1)…{派生类构造函数体;}其中,“总参数表”中各个参数包含了其后的各个分参数表。3.多继承和单继承派生类的构造函数必须同时负责该派生类所有基类构造函数的调用,且派生类的参数个数必须包含完成所有基类初始化所需的参数个数。4.多继承派生类构造函数的执行顺序:(1)调用基类的构造函数,调用次序按照它们被继承时说明的次序(从左到右)。(2)调用子对象的构造函数,调用次序按照它们在类中说明的次序。(3)调用派生类的构造函数。5.对于处于同一层次的各基类构造函数的执行顺序取决于定义派生类时所指定的各基类顺序,与派生类构造函数中所定义的成员初始化列表中的各项顺序无关。例6:classA{inta;public:A(inti){a=i;cout”AConstructor”endl;}C++自考资料3voiddisp(){cout”a=”aendl;}};classB{intb;public:B(intj){b=j;cout”BConstructor”endl;}voiddisp(){cout”b=”bendl;}};classC:publicB,publicA{intc;public:c(intk):A(k-2):B(k+2){c=k;cout”CConstructor”endl;}voiddisp(){A::disp();B::disp();cout”c=”cendl;}};voidmain(){Cobj(10);obj.disp();}执行结果为:BConstructorAConstructorCConstructora=8b=12c=106.多继承中析构函数的执行顺序与构造函数的顺序正好相反。7.在派生类中对基类成员的访问应该是唯一的,但在多继承下,可能造成对基类中某个成员的访问出现了不唯一的情况,称为对基类成员访问的二义性问题。一般解决方法是采用作用域运算符::。四、虚基类1.虚基类说明格式:virtual继承方式基类其中,virtual是虚基类的关键字。虚基类的说明用在定义派生类时,写在派生类名后面。例7:classx{protected:inta;public:x(){a=10;}};classx1:publicx{public:x1(){coutaendl;}};classx2:publicx{public:x2(){coutaendl;}};classy::x1,x2{public:y(){coutaendl;}//二义性,是x1::a还是x2::a};voidmain(){yobj;}此时,通过引入虚基类消除二义性。引入虚基类后,派生类的对象中只存在一个虚基类的子对象。当一个类有虚基类时,编译系统将为该类的对象定义一个指针成员,让它指向虚基类的子对象。该指针叫虚基类指针。上面程序应改为:classx1:virtualpublicx{public:x1(){coutaendl;}};classx2:virtualpublicx{public:x2(){coutaendl;}};2.虚基类的初始化和多继承类的语法一样,但调用派生类构造函数的顺序应遵守以下原则:(1)虚基类的构造函数在非虚基类前调用。(2)若同一层次中包含多个虚基类,则虚基类的构造函数按它们说明的顺序调用。(3)若虚基类由非虚基类派生而来,则仍先调用基类构造函数,再调用派生类中构造函数的执行顺序。例7:classbase1{public:base1(){cout”classbase1”endl;}};classbase2{public:base2(){cout”classbase2”endl;}};classlevel1:publicbase2,virtualpublicbase1{public:level1(){cout”classlevel1”endl;}};classlevel2:publicbase2,virtualpublicbase1{public:level2(){cout”classlevel2”endl;}};classtoplevel:publiclevel1,virtualpubliclevel2{public:toplevel(){cout”classtoplevel”endl;}};voidmain(){toplevelobj;}整个obj对象的各构造函数的执行顺序为:base1()、base2()、level2()、base2()、level1()、toplevel().执行结果为:classbase1classbase2classlevel2classbase2classlevel1classtoplevel3.一般,当定义虚基类的构造函数时,虚基类只允许定义不带参数的或带默认参数的构造函数。C+

1 / 6
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功