C++笔记610.docx
- 文档编号:30631230
- 上传时间:2023-08-18
- 格式:DOCX
- 页数:80
- 大小:76.82KB
C++笔记610.docx
《C++笔记610.docx》由会员分享,可在线阅读,更多相关《C++笔记610.docx(80页珍藏版)》请在冰豆网上搜索。
C++笔记610
第六章继承和派生
§6.1继承和派生的概念
一、派生
类的派生是指从一个或多个以前定义的类产生新类的过程,原有的类称为基类,新产生的类称为派生类,派生类继承了基类所有的数据成员和成员函数。
派生类使用两种基本的面向对象技术,一种称为性质约束,即对基类的性质进行限制;另一种称为性质扩展,即增加派生类的性质。
相对基类,派生类可以有以下变化:
增加新的成员;重新定义已有的成员函数;改变基类成员的访问权限。
二、继承
类的继承是指派生类继承基类的数据成员和成员函数为自己的成员,继承常用来表示类属关系,而不是构成关系。
C++中有两种继承方式:
单一继承和多重继承,对于前者,派生类只能有一个基类;对于后者,派生类可以有多个基类。
静态成员可以被继承,这时基类对象和派生类的对象共享该静态成员。
§6.2单一继承
一、单一继承的一般声明形式
class派生类名:
访问控制基类名{
private:
成员声明列表
protected:
成员声明列表
public:
成员声明列表
};
其中,访问控制是指如何控制基类成员在派生类中的访问属性,它是关键字private、protected和public中的一个,声明中的其余部分和类的声明类似。
二、派生类的构造函数和析构函数
1、定义派生类构造函数的一般定义形式:
派生类名:
:
派生类名(参数表0):
基类名(参数表){……//函数体}
冒号后“基类名(参数表)”称为成员初始化列表,参数表给出所调用的基类构造函数所需要的实参,实参的值可来自“参数表0”,也可由表达式给出。
2、派生类析构函数的一般定义形式:
派生类名:
:
~派生类名(){……//函数体}
构造函数和析构函数也都可在类体内直接定义为内联函数,这时的定义形式需把上述定义式中的“派生类名:
:
”去掉。
例1:
使用默认内联函数实现单一继承
#include
usingnamespacestd;
classPoint{
private:
intx,y;
public:
Point(inta,intb){x=a;y=b;cout<<"点"<<””;}
voidShowxy(){cout<<"x="< ~Point(){cout<<"删除点"<<””;} }; classRectangle: publicPoint{ private: intH,W; public: Rectangle(inta,intb,inth,intw): Point(a,b){H=h;W=w;cout<<"矩形"<<””;} //构造函数初始化列表 voidShow(){cout<<"H="< ~Rectangle(){cout<<"删除矩形"<<””;} }; voidmain(){ Rectangler1(3,4,5,6);//生成派生类对象r1,r1先后调用基类和派生类的构造函数进行初始化 r1.Showxy();//派生对象调用基类的成员函数, r1.Show();//派生对象调用派生类的成员函数 } 程序运行结果: 点矩形x=3,y=4H=5,W=6删除矩形删除点 3、小结 由上例可看出,构造函数和析构函数是不被继承的,所以一个派生类只能调用它的直接基类的构造函数,当定义派生类的一个对象时,首先调用基类的构造函数,对基类成员进行初始化,然后执行派生类的构造函数,如果某个基类仍是一个派生类,则这个过程递归进行。 当该对象消失时,析构函数的执行顺序和执行构造函数时的顺序正好相反。 三、类的保护成员 类的保护成员是指在类声明中以关键字protceted声明的成员,保护成员具有私有成员和公有成员的双重角色: 对派生类的成员函数而言,它是公有成员,可直接访问;而对其他函数而言,它是私有成员,不能直接访问,只能通过基类的对象访问。 这样就解决了使用公有方式产生的派生类的成员函数虽然可直接访问基类中定义的或从另一个基类继承来的公有成员,但不能访问基类的私有成员的问题。 例2: 演示使用protected成员的实例 #include usingnamespacestd; classPoint{ protected: intx,y; public: Point(inta,intb){x=a;y=b;}//Point类构造函数为内联函数 voidShow(){cout<<"x="< }; classRectangle: publicPoint{ private: intH,W; public: Rectangle(int,int,int,int);//声明Rectangle类的构造函数 voidShow(){cout<<"x="< }; Rectangle: : Rectangle(inta,intb,inth,intw): Point(a,b){H=h;W=w;} //派生类的内联构造函数定义形式: 派生类名(参数表0): 基类名(参数表){} voidmain(){ Pointa(3,4);//定义Point类对象a,并调用Point类构造函数初始化 Rectangler1(3,4,5,6);//定义Rectangle类对象r1,并初始化 a.Show();//基类对象a调用基类Show函数,输出“x=3,y=4” r1.Show();//派生类对象r1调用派生类Show函数,输出“x=3,y=4,H=5,W=6” } 说明: 程序演示了: 通过定义x、y为基类保护数据成员,从而使派生类的成员函数Show能直接访问x、y; 如何在类体内声明函数原型,并在类体外进行定义。 在程序中,派生类虽然继承了基类的成员函数Show,但却对其进行了改造,使其能显示所有数据,这并不影响基类函数原来的功能。 为了以后还可以派生新类,可将H、W也定义为保护成员,这样就可以放心的使用统一的Show函数了。 四、访问权限和赋值兼容规则 1、公有派生和赋值兼容规则 在公有派生情况下,可以通过定义派生类自己的成员函数来访问派生类对象继承来的公有和保护成员,但不能访问继承来的私有成员和不可访问成员(基类的基类的私有成员)。 所以当希望类的某些成员能够被派生类访问,而又不能被其他的外界函数访问的时候,就应当把它们定义为保护的,而千万不能把它们定义为私有的,否则在派生类中它们就会是不可访问的。 所谓赋值兼容规则,就是在公有派生情况下,通过将基类的成员都定义为公有或保护的,从而使每一个派生类的对象都可作为基类的对象来使用的情况。 比如,如果将基类的某个成员定义为私有的话,则派生类中继承的该成员就不能被派生类的成员函数访问,这样派生类的对象就不能作为基类的对象使用,也就不符合赋值兼容规则。 例3: 演示赋值兼容规则的实例 #include usingnamespacestd; classPoint{ protected: intx,y; public: Point(inta,intb){x=a;y=b;}//Point类构造函数为内联函数 voidShow(){cout<<"x="< }; classRectangle: publicPoint{ private: intH,W; public: Rectangle(int,int,int,int);//声明Rectangle类的构造函数 voidShow(){cout<<"x="< }; Rectangle: : Rectangle(inta,intb,inth,intw): Point(a,b){H=h;W=w;} voidmain(){ Pointa(1,2);//定义基类对象a,并调用基类构造函数进行初始化 Rectangleb(3,4,5,6);//定义派生类对象b,并调用构造函数初始化 a.Show();//输出“x=1,y=2” b.Show();//输出“x=3,y=4,H=5,W=6” Point&ra=b;//定义基类的引用ra,并用派生类对象对其初始化 ra.Show();//引用ra调用基类的成员函数Show,输出“x=3,y=4” Point*p=&b;//定义基类的指针p,并用派生类对象b的地址对其进行赋值 p->Show();//指针p调用基类的成员函数Show,输出“x=3,y=4” Rectangle*pb=&b;//定义派生类的指针pb,并用派生类对象b的地址对其进行赋值 pb->Show();//指针pb调用派生类的成员函数,输出“x=3,y=4,H=5,W=6” a=b;//派生类对象的属性值更新基类对象的属性值 a.Show();//输出更新后的保护成员数值“x=3,y=4” } 2、公有继承“isa”和分层“has-a”的区别 所谓“isa”,就是公有继承“就是一个”的含义,是指在公有继承的赋值兼容规则下,如果类B公有继承于类A,在可以使用类A的对象的任何地方,则类B的对象同样也能使用,即每一个类B的对象“就是一个”类A的对象,但反之则不然,即如果需要一个类B的对象,则类A的对象就不行。 所谓“has-a”,就是分层时“有一个”的含义,分层也称包含、嵌入或聚合,它是一种处理过程,通过让分层的类里包含被分层的类的对象作为其数据成员,以便把一个类建立在另一些类之上。 例如一个person对象有一个名字、一个地址和两个电话号码,那么person类表示的就是一种“has-a”的关系。 3、公有继承存取权限表 派生类一般都使用公有继承,对派生类而言,基类中的保护类型的成员介于私有和公有之间,派生类可以访问它,而类的对象、外部函数以及不属于本系类之外的类则不可访问它。 基类成员 派生类成员函数 基类和派生类对象 外部函数 Private 不可访问 不可访问 不可访问 Protected 可访问 不可访问 不可访问 public 可访问 可访问 可访问 4、私有派生 私有派生时,基类的私有和不可访问成员和公有派生时一样,在派生类中仍是不可访问的;而基类的公有和保护成员此时就成了派生类的私有成员,从而导致派生类的对象不能直接访问继承的基类成员,只能通过定义公有的成员函数作为接口。 更重要的是,虽然派生类的成员函数可通过自定义的函数访问基类的成员,但如果将该派生类作为基类再继续派生时,即使使用公有派生,原基类公有成员和保护成员在新的派生类中也将是不可访问的,只能通过调用派生类自定义的函数访问原基类的公有和保护成员,这样就切断了原基类与外界的联系。 私有派生的这种特点不利于进一步派生,因此实际中应用的不多。 例4: 私有派生的类继续派生的例子 #include usingnamespacestd; classPoint{ private: intx,y; public: Point(inta,intb){x=a;y=b;}//Point类构造函数为内联函数 voidShow(){cout<<"x="< }; classRectangle: privatePoint{//私有继承,其公有成员将成为派生类的私有成员 private: intH,W; public: Rectangle(inta,intb,inth,intw): Point(a,b){H=h;W=w;} voidShow(){Point: : Show();cout<<"H="< }; classTest: publicRectangle{//公有继承,仍能访问基类的公有成员 public: Test(inta,intb,inth,intw): Rectangle(a,b,h,w){} voidShow(){Rectangle: : Show();} voidmain(){ Pointa(1,2);//定义基类对象a,并调用基类构造函数进行初始化 Rectangleb(3,4,5,6);//定义派生类对象b,并调用构造函数初始化 Testc(7,8,9,10);//定义再次派生类对象c,并调用构造函数初始化 a.Show();//输出“x=1,y=2” b.Show();//输出“x=3,y=4”“H=5,W=6” c.Show();//输出“x=7,y=8”“H=9,W=10” 说明: 上例中,基类Point的公有成员函数Show通过私有派生成了派生类Rectangle的私有成员函数,虽然派生类通过定义公有成员函数Rectangle: : Show可以使用这时已是自己类私有成员的函数Point: : Show,但再次派生的类Test虽是公有派生,却已无法使用基类的公有成员函数Show,即不能通过“Point: : Show();”的方式使用Point类的Show函数,例中只能通过“Rectangle: : Show();”的方式间接达到显示x、y的目的。 5、保护派生 派生也可使用protected定义,这种派生使原来的权限都降一级使用,即private变为不可访问;protected变为private;public变为protected。 因为限制了数据成员和成员函数的访问权限,所以用的也很少。 它与私有派生的区别主要在于下一级的派生中,如果降上例中Rectangle类改为如下的保护继承方式: classRectangle: protectedPoint{//类体}; 则Test类中就可以使用基类的Show函数,即下面的函数定义是正确的: classTest: publicRectangle{//公有继承,仍能访问基类的公有成员 public: Test(inta,intb,inth,intw): Rectangle(a,b,h,w){} voidShow(){Point: : Show();Rectangle: : Show();} }; §6.3多重继承 多重继承可视为单一继承的扩展,一个类从多个基类派生的一般形式为: class类名1: 访问控制类名2,访问控制类名3,…,访问控制类名n{//类体} 其中,类名1继承了类名2到类名n的所有数据成员和成员函数,访问控制用于限制其派生类中的成员对基类的访问控制,规则和单一继承情况一样。 例5: 演示多重继承的实例 #include usingnamespacestd; classA{ private: inta; public: voidsetA(intx){a=x;}
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C+ 笔记 610