版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第十一章派生类与继承11.1类的继承与派生11.2派生类的构造函数和析构函数11.3多重继承11.4虚基类11.5小结
继承是C++的一种重要机制,是程序可重用与扩充的一个重要方面。这一机制使得程序员可以在已有类的基础上建立新类。从而扩展程序功能、体现类的多态性特征。11.1类的继承与派生自然世界的类概念是抽象的,类的下面还有子类,子类继承父类的各种特征。面向对象程序设计允许你声明一个新类作为另一个类的派生。派生类(也称子类)可以声明新的属性(成员)和新的操作(成员函数)。继承可以让你重用父类代码,专注于为子类编写新代码。我们称最初的类为基类,根据它生成的类称为派生类(子类),这种派生可以是多层次的。11.1.1继承与派生的概念哺乳动物类猫类犬类波斯猫安哥拉猫西施犬沙皮犬为什么要使用继承?例如:classperson{private:charname[10];intage;charsex;public:voidprint();}classemployee{private:charname[10];intage;charsex;chardepartment[20];floatsalary;public:voidprint();}11.1.2派生类的声明声明一个派生类的一般格式为:class派生类名:派生方式基类名{ //派生类新增的数据成员和成员函数}“保护成员”是由protected声明的类成员。保护成员不能被外界引用,这点和私有成员类似,但它可以被派生类的成员函数引用。下面用派生关系改写person和employee类。基类classperson{private:charname[10];intage;charsex;public:voidprint();}派生类classemployee:publicperson{private:chardepartment[20];floatsalary;public://…}派生方式公有派生classemployee:publicperson{//…}私有派生classemployee:privateperson{//…}保护派生classemployee:protectedperson{//…}特点:公有继承:基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的状态,而基类的私有成员仍然是私有的。保护继承:基类的所有公有成员和保护成员都成为派生类的保护成员,并且只能被它的派生类成员函数或友元访问,基类的私有成员仍然是私有的。私有继承:基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问。缺省继承方式为private.继承方式基类特性派生类特性公有继承PublicprotectedprivatePublicProtected不可访问私有继承PublicprotectedprivatePrivatePrivate不可访问保护继承PublicprotectedprivateProtectedProtected不可访问例11.1派生类对基类的访问特性。#include<iostream.h>classA{public: voidf1();protected: intj1;private: inti1;};classB:publicA{public: voidfn2();protected: intj2;private: inti2;};classC:publicB{
public: voidf3();};问题:1.B中成员函数f2()能否访问基类A中的成员:f1(),i1,j1?2.B的对象b1能否访问A的成员?3.C的成员函数f3()能否访问直接基类B中的成员:f2(),i2,j2?4.派生类C的对象c1是否可以访问直接基类B的成员?能否访问间接其类A的成员:f1(),i1,j1?回答:1.可以访问f1(),j1,不可访问i1;2.可以访问f1(),不可访问i1,j1;3.可以访问f2(),j2,f1(),j1,不可访问i1,i2;4.可以访问f2(),f1(),其他的都不可以访问;结论:在公有继承时,派生类的成员函数可访问基类中的公有成员和保护成员;派生类的对象仅可访问基类中的公有成员。【例11.2】私有派生类对基类成员的访问。
#include<iostream.h> classbase{//声明一个基类 intx; public: voidsetx(intn){x=n;} voidshowx()
{cout<<x<<endl;} }; classderived:privatebase{//声明一个私有派生类 inty; public: voidsety(intn){y=n;} voidshowxy()
{cout<<x<<y<<endl;}
//非法,派生类不能访问基类的私有成员 };【例11.3】私有派生类对基类成员的访问。#include<iostream.h>classbase{intx;public:voidsetx(intn){x=n;}voidshowx()
{cout<<x<<endl;}};classderived:privatebase{inty;public:voidsety(intn){y=n;}voidshowy()
{cout<<y<<endl;}};main(){derivedobj;obj.setx(10);//非法
obj.sety(20);//合法
obj.showx();//非法
obj.showy();//合法
return0;}如果将derived类改为公有派生,则main函数中的调用合法否?(例11.4)如果将derived类改为保护派生,则main函数中的调用合法否?(例11.4)思考在派生类中声明的名字可以支配基类中声明的同名的名字。如果在派生类的成员函数中直接使用该名字的话,则表示使用派生类中声明的名字,例如: classX{public: intf();};
classY:publicX{public: intf(); intg();}; voidY::g(){f();//表示被调用的函数是Y::f(),而不是X::f()}
11.2派生类的构造函数和析构函数
基类都有显示的或隐式的构造函数和析构函数。当创建一个派生类对象时,如何调用基类的构造函数对基类数据初始化,以及在撤销派生类对象时,又如何调用基类的析构函数对基类对象的数据成员进行善后处理,是本节所要讨论的内容。11.2.1构造和析构的次序通常情况下,当创建派生类时,首先执行基类的构造函数,随后再执行派生类的构造函数;当撤销派生类对象时,则先执行派生类的析构函数,随后再执行基类的析构函数。参见例11.6【例11.6】掌握基类和派生类的构造函数和析构函数的执行顺序。#include<iostream.h>classbase{public: base() {cout<<"基类的构造函数"<<endl;} ~base() {cout<<"基类的析构函数"<<endl;}};classderive:publicbase{public: derive() {cout<<"派生类的构造函数"<<endl;} ~derive() {cout<<"派生类类的析构函数"<<endl;}};main(){ deriveop; return0;}11.2.2派生类的构造函数和析构函数的构造规则派生类构造函数的一般格式:在定义派生类对象时,构造函数的执行顺序如下:(1)基类的构造函数(2)对象成员的构造函数(3)派生类的构造函数例11.7派生类构造函数名(参数表):基类构造函数名(参数表),对象成员名1(参数表),…,对象成员名n(参数表)
{派生类中其它数据成员初始化}【例11.7】派生类构造函数给基类构造函数传递参数。#include<iostream.h> classbase{ intx; public: base(inta)
{cout<<"基类的构造函数"<<endl;
x=a; }
~base()
{cout<<"基类的析构函数"<<endl;}
voidshowx(){cout<<x<<endl;} };classderived:publicbase{ inty; public: derived(inta,intb):base(a)
//派生类的构造函数,要缀上基类的构造函数
{ cout<<"派生类的构造函数"<<endl; y=b; } ~derived(){cout<<"派生类的析构函数"<<endl;} voidshowy() {cout<<y<<endl;} }; voidmain() {derivedobj(10,20); obj.showx(); obj.showy(); return0; }含有对象成员的派生类构造函数当派生类中含有对象成员时,派生类必须负责该对象成员的构造,其构造函数的一般形式为:
派生类构造函数名(参数表):基类构造函数名(参数表),对象成员名1(参数表),…,对象成员名n(参数表){ //…}【例11.8】含有对象成员的派生类构造函数的执行情况
#include<iostream.h> classbase{ intx; public: base(inta) { cout<<"基类的构造函数"<<endl; x=a; } ~base()
{cout<<"基类的析构函数"<<endl;} voidshowx() {cout<<x<<endl;} };
classderived:publicbase{ public: based; //d为基类对象,作为派生类的对象成员
derived(inta,intb):base(a),d(b)
//派生类的构造函数,缀上基类构造函数
//和对象成员的构造函数
{cout<<"派生类的构造函数"<<endl; }
~derived(){cout<<"派生类的析构函数"<<endl;} }; voidmain() {
derivedobj(10,20); obj.showx(); obj.d.showx(); }说明当基类的构造函数不带参数时,派生类不一定需要定义构造函数,然而当基类的构造函数那怕只带有一个参数,它所有的派生类都必须定义构造函数,甚至所定义的派生类的构造函数的函数体有可能为空,仅仅起到参数传递作用。若基类使用缺省构造函数或不带参数的构造函数,则在派生类中定义构造函数时可略去,此时若派生类也不需要构造函数,则可以不定义构造函数。如果派生类的基类也是一个派生类,则每个派生类只需要负责直接基类的构造。由于析构函数是不带参数的,在派生类中是否要定义析构函数与它所属的基类无关。11.3多重继承多重继承:一个派生类具有多个基类。在多重继承中,公有继承和私有继承对于基类成员在派生类中的可访问性与单继承相同。玩具车玩具车class派生类名:继承方式1基类名1,…,继承方式n基类名n{派生类新定义成员};11.3.1多重继承的声明例11.9声明多重派生。#include<iostream.h>classX{ inta;public: voidsetX(intx) {a=x;} voidshowX(){cout<<"a="<<a<<endl;}};classY{ intb;public: voidsetY(inty) {b=y;} voidshowY() {cout<<"b="<<b<<endl;}};classZ:publicX,privateY{ intc;public: voidsetZ(intx,inty) { c=x; setY(y); } voidshowZ() { showY(); cout<<"c="<<c<<endl; }};voidmain(){ Zobj; obj.setX(3); obj.showX(); //obj.setY(4); //obj.showY(); obj.setZ(6,8); obj.showZ();}二义性对基类成员的访问必须是无二义性的。消除下例中的二义性,可写为obj.X::f();//调用类X的f()obj.X::f();//调用类Y的f()例11.10多重继承时,对基类访问存在二义性的情况。 #include<iostream.h> classbase1{ public: voidshow(){} }; classbase2{ public: voidshow(){} }; classderive:publicbase1,privatebase2{ public: voidshowderive() {} }; voidmain() { deriveobj; obj.show(); //二义性错误,不知调用的是//base1的show()//还是base2的show()}11.3.2多重继承的构造函数
多重继承构造函数定义的一般形式如下:
派生类构造函数名(参数表):基类构造函数名1(参数表),基类构造函数名2(参数表),…,基类构造函数名n(参数表){ //派生类中其它数据成员初始化}【例11.8】含有对象成员的派生类构造函数的执行情况。
#include<iostream.h> classbase{ intx; public: base(inta) { cout<<"基类的构造函数"<<endl; x=a; } ~base() {cout<<"基类的析构函数"<<endl;} voidshowx() {cout<<x<<endl;} };
classderived:publicbase{ public: based;//d为基类对象,作为派生类的对象成员 derived(inta,intb):base(a),d(b)
//派生类的构造函数,缀上基类构造函数 //和对象成员的构造函数 {cout<<"派生类的构造函数"<<endl; }
~derived(){cout<<"派生类的析构函数"<<endl;} }; voidmain() {derivedobj(10,20); obj.showx(); obj.d.showx(); }11.4虚基类当引用派生类的成员时,首先在派生类自身的作用域中寻找这个成员,如果没有找到,则在它的基类中寻找。如果一个派生类是从多个基类派生出来的,而这些基类又有一个共同的基类,则在这个派生类中访问这个共同的基类中的成员时,可能会产生二义性。virtual关键字,同继承方式关键字的先后顺序无关紧要。【例11.12】多重派生产生二义性的情况#include<iostream.h>classbase{protected: inta;public: base() {a=5;}};classbase1:publicbase{public: base1() {cout<<"base1a="<<a<<endl;}};classbase2:publicbase{public: base2() {cout<<"base2a="<<a<<endl;}};classderived:publicbase1,publicbase2{public: derived() {cout<<"de
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年计算机编程(Python高级编程)试题及答案
- 2026年营销策划(营销渠道设计)试题及答案
- 2025年高职第一学年(软件技术)Java编程综合试题及答案
- 2026年网络技术综合(多协议应用)试题及答案
- 2025年高职播音与主持艺术(节目主持技巧)试题及答案
- 2025年大学法医学(法医毒物分析)试题及答案
- 巴松介绍教学课件
- 2026年江汉区金融类国企招聘工作人员备考题库及一套答案详解
- 威宁介绍教学
- 会议考勤与出勤考核制度
- 公安特警测试题及答案
- ERCP治疗胆总管结石的护理
- 2025年国际政治格局:多极化与地缘政治风险
- 有害物质管控标准
- T-CSUS 69-2024 智慧水务技术标准
- 国家开放大学法学本科《商法》历年期末考试试题及答案题库
- UL583标准中文版-2018电动工业车辆UL中文版标准
- 2024年新华东师大版七年级上册数学全册教案(新版教材)
- 冀人版五年级科学上册期末测试卷4份(含答案)
- 菜肴造型与盛装工艺
- 甲状腺癌医学知识讲座
评论
0/150
提交评论