c++包含与继承

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

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

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

资源描述

C++C++包含与继承复用已有的类Contents包含的语法和用途1继承的语法和用途2赋值兼容规则3包含与继承的选择47.1包含——复用类的实现包含表示一个类含有一个基本数据元素或对象除了简单类型的数据成员之外,也可以将一个类的对象作为另一个类的成员包含语法有时也被称作“组合”,特指C++中的对象成员语法现象包含用来实现“has-a”关系classStudent{stringname;longstuID;Datebirth;//…};classEgnine{……};classWheel{……};classCar{Enginee;Wheelwheels[4];…};对象成员包含已有类的对象作为成员,可以通过成员对象使用已有类的功能,复用其实现如果将嵌入的对象作为新类的公有成员,那么除了使用新类接口中提供的功能之外,还可以向其中包含的成员对象发送消息程序7.1public对象成员更常用的方式是将嵌入对象作为新类的私有成员,这时它是新类内部实现的一部分。新类中的方法可以使用成员对象提供的功能,但新类只向外部提供自己的接口,隐藏了包含的成员对象程序7.2private对象成员对象成员的初始化在创建一个包含对象成员的组合对象时,会调用成员类的构造函数初始化对象成员成员对象的初始化使用初始化列表语法当组合对象被撤销时,会调用其析构函数,成员对象的析构函数也会被调用析构函数的调用次序和构造函数相反classMember{intx;public:Member(intiv):x(iv){}};classwithMembers{inty;Memberm;public:withMembers(inta,intb):m(a),y(b){}};对象成员的初始化成员对象的初始化表如果没有在初始化列表中对成员对象进行显式初始化,编译器会为成员对象调用缺省构造函数,如果成员对象所属的类不存在缺省构造函数,会引起编译错误类中如果包含多个对象成员,在初始化列表中将它们用逗号隔开成员初始化的次序和成员声明的次序相同,并不考虑它们在初始化列表中的排列顺序classMember1{intx;public:Member1(intiv):x(iv){}};classMember2{inty;public:Member2(intiv):y(iv){}};classwithMembers{Member1m1;Member2m2;public:withMembers(inta):m2(a),m1(a){}};包含的进一步讨论包含和类的复用如果希望复用一个类的实现,或使用一个类的功能,使用包含是一种简单而有效的方法。在新类中封装一个已有类的对象,让它作为新类实现的一部分去完成相关的操作,实现新类的功能按值包含包含已有类的对象作为新类的成员按指针(或引用)包含包含成员类对象的指针或引用作为新类的成员包含的进一步讨论组合在UML中,将“整体-部分”关系称为“组合(composition)”组合关系的特点是成员对象是组合对象的一部分,随着组合对象的创建而创建,随着组合对象的撤销而撤销,成员对象并不作为独立元素对外部展现按值包含用来实现“整体-部分”关系包含的进一步讨论聚合聚合也描述组成关系,但是比组合更松散聚合关系的特点是成员对象可以独立于聚合对象而存在。当聚合对象被创建或撤销时,其成员对象可以不受影响,而只是它们之间的关系受到影响聚合通常使用按指针(或引用)包含的语法实现包含的进一步讨论组合与聚合示例classMailBody{…};classAttachment{stringfilename;//其他成员…};classEmail{stringtitle;MailBodybody;vectorAttachment*attch;public:voidedit(){…}voidsave(){…}voidsend(stringreceiverAddr){…}voidaddAttch(Attachment*a){attch.push_back(a);…}};包含的进一步讨论关联关系除了组合与聚合之外,现实中的对象之间还存在着很多更广泛的关系UML中的关联(association)关系关联在C++中用按指针包含的语法实现classBankAccount{//银行账户类longaccountNo;doublebalance;stringclientName;public:BankAccount(longaNo,stringname,doublebal){……}};classClient{//客户类stringname;stringaddress;BankAccount*acc;//BankAccount*accounts[5];//vectorBankAccount*accounts//…public:Client(stringnm,BankAccount*a):name(nm){acc=a;}};//一种可能的银行开户操作如下:BankAccountba(18024,Xavi,5000);ClientXavi(Xavi,&ba);7.2继承——复用类的接口泛化和继承现实中的概念之间还存在另一类常见关系,描述概念的层次或分类如生物系统中的门、纲、目、科、属、种等在UML中用泛化描述这类关系,在C++中则用继承语法实现继承是面向对象的核心特征之一,也是一种复用已有类的机制。在已有类的基础上继承得到新类型,这个新类型自动拥有已有类的特性,并可以修改继承到的特性或者增加自己的新特性继承的语法classstudent{//学生stringname;intstudent_id;stringdepartment;public:student(stringnm,intid,stringdp);voidprint()const;};classgrad_student{//研究生stringname;intstudent_id;stringdepartment;stringthesis;public:grad_student(stringnm,intid,stringdp,stringth);voidprint()const;};继承的语法研究生类定义中存在的问题在grad_student类中包含了student类的所有成员,两个类的代码有部分重复现实中,研究生也是学生,但是上面的类定义并没有体现出这种关系。应该将grad_student是student的事实更明确地表达出来这样的“is-a”关系用继承实现classgrad_student:publicstudent{stringthesis;public:grad_student(stringnm,intid,stringdp,stringth);voidprint()const;};继承的语法继承的语法形式class派生类名字:[访问限定符]基类名字{成员声明};如果不指定访问限定符,则默认为private相关术语在C++中,被继承的已有类称为基类,继承得到的新类称为派生类派生类可以再被继承,这样构成的层次结构称为继承层次派生类继承了基类的数据成员和成员函数,只需要对自己不同于基类的行为或自己扩展的行为编写代码基类成员在派生类中的可见性基类成员在派生类中的可见性由两个因素决定:成员在基类中的访问限定和继承时使用的访问限定符基类成员的访问限定public成员在任何类和函数中都是可以访问的private成员只有本类或本类的友元可以访问,在其他类和函数中不可访问,在自己的派生类中也同样不可访问protected成员的访问权限介于public和private之间:对它的派生类来说,protected成员和public成员一样是可访问的,但对其他类和函数而言,protected成员就如同private成员一样不可访问基类成员在派生类中的可见性public——公有继承基类的public成员和protected成员分别作为派生类的public成员和protected成员被继承基类的private成员被继承,但在派生类中不可见ABCABCinvisibleprivateprotectedpublicC公有继承B,B公有继承A基类成员在派生类中的可见性private——私有继承基类的public成员和protected成员被派生类作为自己的private成员继承下来基类的private成员被继承,但在派生类中不可见ABCABCinvisibleprivateprotectedpublicC私有继承B,B私有继承A基类成员在派生类中的可见性protected——保护继承基类的public成员和protected成员都被派生类作为自己的protected成员继承下来基类的private成员被继承,但在派生类中不可见ABCABCinvisibleprivateprotectedpublicC保护继承B,B保护继承A基类成员在派生类中的可见性protected不可见protectedprotectedprivate不可见privateprivateprotected不可见publicpublicprotectedprivatepublic基类成员限定符继承方式基类成员在派生类中的可见性classBase{public:intm1;protected:intm2;private:intm3;};classD1:publicBase{//D1中的成员和访问权限如何?};classD2:privateBase{//D2中的成员和访问权限如何?};classD3:protectedBase{//D3中的成员和访问权限如何?};基类成员在派生类中的可见性继承和封装性通过继承基类,派生类就拥有了访问基类protected成员的特权。如果担心基类的封装性会因此被破坏,可以将基类中的所有数据成员都声明为private,而不是protected如果派生类真的需要访问基类的属性,就在基类中为其提供相应的protected访问器函数classBase{intattr;protected:intgetAttr();voidsetAttr(int);};访问声明如果要在派生类中对继承的基类成员的可见性进行调整,可以使用访问声明,语法形式为:classDerived:(public|private|protected)Base{public(|private|protected):Base::成员名;//…};访问声明的作用是在派生类中调整个别基类成员的访问限制,但是不能改变基类private成员的访问限制程序7.3基类成员访问声明公有继承和私有继承公有继承和公有派生类公有派生类继承了基类的接口,能够发送给基类对象的消息派生类对象也可以接收可以将公有派生类看作是基类的子类型,即“is-a(是)”关系。公有派生类的对象也是基类的实例,但反之不成立私有继承和私有派生类私有派生类虽然继承了基类的所有数据和功能,但这些只是作为派生类的部分私有实现,派生类的用户不能访问这些内部功能。基类和私有派生类之间不是类型和子类型的关系,私有派生类的对象也不能被看作是基类的实例公有继承和私有继承假定有Shape类的声明如下:classShape{public:voiddraw()const{…}doublearea()const{…}voidmove(int){…}};如果想通过继承Shape类来创建一个新类型Line,应该使用public继承还是private继承呢?公有继承和私有继承公有继承如果Line要复用Shape类的接口,则使用public继承。公有派生类Line会被看作是一种特殊的Shape,是Shape的子类型。Line类型的对象也是Shape类型的。Shape类中的area()操作显然不适合Line类型,可以通过私有

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

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

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

×
保存成功