第4章C++派生类与继承_第1页
第4章C++派生类与继承_第2页
第4章C++派生类与继承_第3页
第4章C++派生类与继承_第4页
第4章C++派生类与继承_第5页
已阅读5页,还剩95页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

C++面向对象程序设计教程(二版)讲稿

第4章派生类与继承(书P111)

一、派生类的概念(书P111)

1、继承概念和派生类的引入

在现实世界中,许多实体或概念不是孤立的,它们具

有共同的特征,但也有差别。人们常使用层次分类的方法

来描述这些实体或概念之间的相似点。例如(书PH1)

图4.1

在这个分类树中建立一个层次结构,最高层是最普遍,

最一般的,抽象的。以下一层比一层更具体,低层含有高

层的特性,也与高层有细微的不同。例如,汽车有轮子,

运输汽车有载重的设备,到了客车不必再提它有轮子及载

C++4章_P1

重设备,但客车载人与货车载货就有区别等等。客车从运

输车派生出来,运输车从汽车派生。所以客车继承汽车的

一般特性。

在面向对象程序设计中,继承是针对类而言,类可以

从另一个类中继承特性。在C++中,一个类是从另一个类

继承特性,称为派生出一个类,这个类称为派生类。而被

继承的类称为基类。

2、类继承的目的

在OOP程序设计中,类继承有什么好处?

如果有一个程序员接到公司分配一个任务“为公司人

事管理程序增加一个功能,把只适用于普通职工的人事记

录扩展为可适用于管理人员”。完成此任务,程序员有两种

途径可以实现:

(1)把原来设计的类全部推倒重来,按照新的要求重新设

置类的私有和公有数据成员和成员函数。这样做风险很大,

一旦修改过程有错,不仅无法实现新增类的功能,原来的

功能也可能无法恢复。公司人事系统受到破坏。

(2)另一种办法是,在原有人事系统类中生成一个派生类,

派生类可以继承基类的特性。例如,管理人员也有普通职

工的姓名、性别等特性字段,可以继承下来。然后再扩充

一些普通职工没有的特性。例如,管理人员的职别。这样

C++4章_P2

基类保证了公司原有的程序功能继续运作。把新的功能加

入到派生类中。在调试阶段只需针对新增进去的功能调试

派生类。一但调试成功,就可以全面使用派生类工作,而

不影响原有程序的运行。既可防止出错造成无法恢复的危

险,更可以缩短扩充程序的调试时间。

继承性是C++同C之间最大区别之一。继承机制允许

类从一个或多个简单的普通的类中继承其特性和行为,允

许根据需要进行更具体的定义。派生类提供了继承的基础,

并为裁剪基类提供了一种手段。C++允许派生类继承或修改

基类的部分或全部属性,并可以增加基类中没有的新的属

性(包括数据成员和成员函数)以满足派生类的需要。

3、单一继承和多继承

在第1章已讲过,单一继承即派生类只继承一个基类,

是从一个基类派生出来的。而多继承则派生类继承多个基

类。是从多个基类派生出来的。

4、派生类定义格式

先讲单一继承的派生类。

C++4章_P3

class派生类名:[访问权限指明符]基类名

[private:]

新增私有成员及其他

public:

新增公有成员及其他

protected:

新增保护成员及其他

};

其中,“访问权限指明符”,书中使用“继承方式”

(i)访问权限是规定基类成员在派生类继承后,派生类成

员及类外对象可访问的权限。

访问权限指明符(继承方式)有以下三种:

private私有继承

public公有继承

protected继承

(ii)口是我认(也称为缺省)即不出现访问权限指明符,

此时对于类是私有的(即private)对于结构则是公有的

(即是public)o

例如(书PH3)下面定义各种继承方式的派生类

C++4章_P4

(1)公有继承

classemployee:publicperson

(

//-

);

(2)私有继承

classemployee:privateperson

(

//-

};

(3)保护继承

classemployee:protectedperson

{

//-

);

(4)默认访问权限指明符

classemployee:person

{

//•••

};

与(2)私有继承相同。

C++4章_P5

派生类除了可以从基类继承成员外,还可以增加自己的数

据成员和成员函数。这些新增的成员正是派生类不同于基

类的关键所在,这是派生类对基类的发展。从已有类派生

出新类时,可以在派生类内完成以下几种功能:

(1)可以增加新的数据成员。

(2)可以增加新的成员函数。

(3)可以重新定义基类中已有的成员函数。

(4)可以改变基类现有成员的属性。

例4」、例4」」

5、保护成员(书P112)

基类中受保护成员除了可以被本类成员函数访问外,

也可以被由本类派生出来的派生类成员直接访问。而类外

任何访问都是非法的。

为什么要引入成员?因为无论何种派生,基类的

私有成员,派生类都是不能直接访问的。为了使派生类能

够访问基类的私有成员,可以有以下两种方法:

(1)把私有成员公有化,就是定义在公有区,但这就破坏

了数据隐藏和封装。

(2)在基类提供公有函数来操作所需的私有数据。从而派

生类可以通过基类公有函数操作基类私有数据,这样做成

员函数冗长而低效。

C++4章_P6

为了解决这个问题,C++引入保』成员,即用关键字

protected作为访问权限指明符,来指明对基类成员的访

问权限。基类的保护成员只能由本类成员函数或由本类派

生的派生类的成员函数可直接访问,其它的任何访问都是

非法的。外部函数、甚至基类的对象也不能直接访问。这

就维护了隐蔽性,不过对派生类是开放的。所以只能说是

半隐蔽性。例4_4_1

二、继承方式及基类成员在派生类中的访问权限(属性)

1、表4.1参考书P114

基类成员在派生类中的访问权限

在基类中的访问权限继承方式在派生类中的访问权限

privatepublic不可直接访问

privateprivate不可直接访问

privateprotected不PJ直接访问

publicpublicpublic(公有)

publicprivateprivate(私有)

publicprotectedprotected(保护)

protectedpublicprotected(保护)

protectedprivateprivate(私有)

protectedprotectedprotected(保护)

C++4章_P7

从上表可归纳:

(1)基类中的私有成员

无论哪种继承方式,基类中的私有成员不允许派生类

继承。因此,派生类中是不可直接访问。

(2)基类中的公有成员

当继承是公有的,在派生类中仍是公有成员身份出现。

基类成员访问权限在派生类中完全相同。当继承是私有的,

基类公有成员在派生类中都以私有成员身份出现。当继承

方式是保护的,基类公有成员在派生类中都以保护身份出

现。

(3)基类中的保护成员

当继承是公有的,基类保护成员在派生类中仍是保护

成员身份出现。当继承是私有的,基类保护成员在派生类

中都以私有成员身份出现。当继承方式是保方的,基类保

护成员在派生类中仍以保拧身份出现。

2、派生类对基类成员的访问规则

派生类对基类成员的访问形式主要有以下两种:

(a)内部访问,由派生类中新增成员对从基类继承来的成

员的访问。

(b)对象访问,在派生类外部通过派生类创建的对象对从

基类继承来的成员的访问。

C++4章_P8

下面讨论三种继承方式,派生类对基类成员的访问规则

(1)公有继承(公有派生)的访问规则

(a)基类的public和protected成员在派生类中仍作

为public和protected成员。

(D派生类内的成员可直接访问。

(ii)在外部可通过派生类创建的对象访问public成员,

但不能访问protected成员。

(b)基类的private成员在公有派生中是不可直接访问。

所以无论派生类成员还是通过派生类的对象都不能直接访

问基类中的private成员。但可以通过基类提供的public

成员函数间接访问它们

例4.3(书P119)

^include<iostream.h>

classbase声明一个基类base

(

private:

intx;

protected:

inty;

public:

C++4章_P9

voidsetxy(intm,intn)基类定义成员函数setxy

{x=m;

y=n;

)

voidshowxyO基类定义成员函数showxy()

{cout«"x="<<x«endl;

cout«"y="<<y<<endl;

)

);

classderived:publicbase声明一个公有派生类

(

private:

intz;〃派生类新增私有数据成员

public:

voidsetxyz(intm,intn,int1)

//派生类新增公有成员函数setxyz()

(

setxy(m,n);

//成员函数setxy()在派生类中是public成员,可以访问

z=1;//最后初始化派生类私有数据成员z

)

C++4章_P10

voidshowxyz()〃派生类新增公有成员函数showxyz()

//cout<<"x="<<x«endl;

〃非法,基类base的私有数据成员x在派生类不能直接访问

cout«"y=«y«endl;

〃正确,基类base的保护成员y在公有派生类是保护成员

cout«"z="<<z<<endl;

)

);

main()

{

derivedobj;创建派生类对象obj

obj.setxyz(30,40,50);

〃正确,派生类对象直接访问公有成员函数setxyz()

obj.showxyO;

正确,showxy()函数在派生类derived中是public成员函数

obj.showxyz();

正确,showxyz()函数在派生类derived中是public成员函数

return0;

C++4章_P11

程序的运行结果为:

x=30

y二40

y二40

z二50

本例派生类成员函数showxyz()中语句

cout<<"x=〃<<x«endl;

是非法的,尽管派生类derived以公有方式从基类base派

生,但基类base的私有数据成员x在派生类是不能直接

访问的。要解决这问题,只能调用基类base公有函数

showxy()o用例4_3_1来实现

^include<iostream.h>

classbase声明一个基类base

(

private:

intx;

protected:

inty;

public:

C++4章_P12

voidsetxy(intm,intn)基类定义成员函数setxy

x=m;

y=n;

)

voidshowxyO基类定义成员函数showxy()

(

cout«"x="<<x«endl;

cout«"y="<<y«endl;

)

);

classderived:publicbase声明一个公有派生类

(

private:

intz;//派生类新增私有数据成员

public:

voidsetxyz(intm,intn,int1)派生类新增公有成员函数

setxyz()

(

setxy(m,n);

成员函数setxy()在派生类中是public成员,可以访问

C++4章_P13

z=1;//最后初始化派生类私有数据成员Z

)

voidshowxyz()派生类新增公有成员函数showxyz()

(

showxy()调用基类base的公有成员函数showxy()输出经x,y

//cout«"x="<<x«endl;

〃非法,基类base的私有数据成员x在派生类不能直接访问

cout<<"y="<<y«endl;

〃正确,基类base的保护成员y在公有派生类是保护成员,但不必重复输出

cout«"z="<<z«endl;

)

);

main()

(

derivedobj;创建派生类对象obj

obj.setxyz(30,40,50);

〃正确,派生类对象直接访问公有成员函数setxyz()

obj.showxy();

正确,showxy()函数在派生类derived中是public成员函数

obj.showxyz();

正确,showxyz()函数在派生类derived中是public成员函数

C++4章_P14

return0;

程序的运行结果为:

x二30

y=40

x二30

y二40

z二50

(2)私有继承(私有派生)的访问规则

(a)基类的public和protected成员继承后在派生类均

为private(私有)的。

(i)派生类内新增成员函数可直接访问。

(ii)类外即使通过派生类创建的对象也不能访问。

(b)基类的private成员继承后在派生类中成为不可直接

访问的成员。

(i)派生类内的成员不可直接访问。

(ii)类外即使通过派生类创建的对象也不可直接访问。

(iii)可以通过基类提供的public成员函数间接访问。

例4.1(书PH5)

#include<iostream.h>

classbase〃声明一个基类

C++4章_P15

private:

intx//基类有一个私有数据成员x

public:

voidsetx(intn)〃基类定义成员函数setx

voidshowx()〃基类定义成员函数showx

{cout«x«endl;}

};

classderived:privatebase声明一个私有派生类derived

(

public:

voidsetxy(intn,intm)〃派生类新增成员函数setxy

{setx(n);/调用基类公有成员函数给基类私有数据成员x赋初值

y=m;//用参数m给派生类新增私有数据成员y赋初值

)

voidshowxy()派生类新增成员函数showxy

(

cout«X;〃非法,在派生类中不能直接访问基类私有数据成员X

cout«y«endl;正确,在派生类中访问新增私有数据成员y

)

C++4章_P16

private:

inty;〃派生类新增私有数据成员y

);

main()

(

derivedobj;创建派生类derived的对象obj

obj.setx(10);

〃非法,setx()在派生类中为private成员,派生类对象不能直接访问

obj.showx();

〃非法,showx()在派生类中为private成员,派生类对象不能直接访问

obj.setxy(20,30);

〃正确,因setxy()是派生类新增公有函数,派生类创建的对象可以访问

obj.showxyO;非法,因showxy()函数内部操作非法

return0;

)

改为例4_1_1

例4.2(占P117)本程序引入保;成员在私有派生中的访

问属性。

ttinclude<iostream.h>

classbase声明一个基类base

(

protected:定义保护权限区

inta;//定义基类保护数据成员a

C++4章_P17

public:

voidseta(intsa)基类定义成员函数setx()

{a=sa;}〃初始化保护数据成员a

C++4章_P11

voidshowa()基类定义成员函数showa()

{cout«〃a="«a«endl;}〃基类操作保护数据成员a

);

classderivedl:privatebase声明一个私有派生类derivedl

(

protected://派生类新增保护权限区

intb;//派生类新增保护数据成员b

public:

voidsetab(intsa,intsb)定义派生类新增成员函数setab()

(

a=sa;〃正确,在派生类中给基类保护数据成员a初始化

b=sb;〃正确,给派生类保护数据成员b初始化

)

voidshowabO定义派生类新增成员函数showab()

(

cout«"a="<<a«endl;

〃正确,在派生类中输出基类保护数据成员a

C++4章_P18

cout«"b=z,«b«endl;

〃正确,在派生类中输出派生类保护数据成员b

)

);

classderived2:privatederivedl

声明一个基类为derivedl的私有派生类derived2

(

private:

intc;//派生类新增私有数据成员c

public:

voidsetabc(intsa,intsb,intsc)派生类新增成员函数setabc()

(

setab(sa,sb);调用基类成员函数showab()初始化a,b

c=sc;/,最后给私有数据成员c赋初值

)

voidshowabc()派生类新增成员函数showabc()

(

//cout«"a=«a«endl;

〃非法,派生类derived2不可直接访问上一层基类base保护数据成员a

cout«"b="<<b«endl;

〃正确,在派生类中输出基类derivedl保护数据成员b

C++4章_P19

cout«"c="<<c«endl;正确,输出本类的私有数据成员c

}

);

voidmain()

{baseopl;〃创建基类对象opl

opl.seta(1);〃对象opl调用基类base成员函数setxO

opl.showa();对象opl调用基类base成员函数showa()

derivedlop2;〃创建派生类对象op2

op2.setab(2,3);对象op2调用派生类derivedl成员函数setab()

op2.showab();对象op2调用派生类derivedl成员函数showab()

derived2op3;创建基类为derivedl的派生类derived2对象op3

op3.setabc(4,5,6);

对象op3调用派生类derived2成员函数setabc()

op3.showabc();对象op3调用派生类derived2成员函数showabc()

程序的运行结果为:

a=1

a=2

b=3

b二5

c=6

C++4章_P20

例4.2中函数showabc()出现非法,

改为例4_2」,也是非法,理由看程序说明。

#include<iostream.h>

classbase声明一个基类base

(

protected://定义保护权限区

inta;//定义基类保护数据成员a

public:

voidseta(intsa)〃基类定义成员函数setx()

{a=sa;}〃初始化保护数据成员a

voidshowa()基类定义成员函数showa()

{cout<<〃a=〃<<a«endl;}//基类操作保护数据成员a

};

classderivedl:privatebase声明一个私有派生类derivedl

protected:〃派生类新增保护权限区

intb;//派生类新增保护数据成员b

public:

voidsetab(intsa,intsb)定义派生类新增成员函数setab()

sa〃正确,在派生类中给基类保护数据成员a初始化

C++4章_P21

b=sb;〃正确,给派生类保护数据成员b初始化

)

voidshowabO定义派生类新增成员函数showab()

(

cout«"a="<<a«endl;

〃正确,在派生类中输出基类保护数据成员a

cout«"b="<<b«endl;

〃正确,在派生类中输出派生类保护数据成员b

)

);

classderived2:privatederivedl

声明一个基类为derivedl的私有派生类derived2

(

private:

intc;//派生类新增私有数据成员c

public:

voidsetabc(intsa,intsb,intsc)派生类新增成员函数setabc()

(

setab(sa,sb);调用基类成员函数showabO初始化a,b

c=sc;//最后给私有数据成员c赋初值

)

C++4章_P22

voidshowabc()〃派生类新增成员函数

//showa();

〃非法,基类base公有成员函数showa()在私有派生

//类derivedl中是私有的,不能直接访问

cout«"b=〃<<b<<endl;

〃正确,在派生类中输出基类derivedl保护数据成员b

cout«"c=〃<<c«endl;〃正确,输出本类的私有数据成员c

)

);

voidmain()

(

baseopl;〃创建基类对象opl

opl.seta(1);〃对象opl调用基类base成员函数setxO

opl.showa();对象opl调用基类base成员函数showa()

derivedlop2;〃创建派生类对象op2

op2.setab(2,3);对象op2调用派生类derivedl成员函数setab()

op2.showab();对象op2调用派生类derivedl成员函数showab()

derived2op3;创建基类为derivedl的派生类derived2对象op3

op3.setabc(4,5,6);

对象op3调用派生类derived2成员函数setabc()

C++4章_P23

op3.showabc();

对象op3调用派生类derived2成员函数showabc()

程序的运行结果为:

a=1

a=2

b=3

b二5

c=6

改为例4_2_2才正确。理由看程序说明。

Winclude<iostream.h>

classbase声明一1个基类base

protected://定义保护权限区

inta;//定义基类保护数据成员a

public:

voidseta(intsa)//基类定义置初值成员函数setxO

ta=sa;〃初始化保护数据成员a

voidshowa()//基类定义成员函数showa()

{cout«〃a=〃<<a«endl;}〃基类操作保护数据成员a

};

C++4章_P24

classderivedl:privatebase声明一个私有派生类derivedl

protected://派生类新增保护权限区

intb;//派生类新增保护数据成员b

public:

voidsetab(intsa,intsb)定义派生类新增置初值成员函数setab()

(

a=sa;〃正确,在派生类中给基类保护数据成员a初始化

b=sb;〃正确,给派生类保护数据成员b初始化

)

voidshowabO定义派生类新增成员函数showab()

{

cout«"a=,z«a«endl;

//正确,在派生类中输出基类保护数据成员a

cout«"b="<<b«endl;

//正确,在派生类中输出派生类保护数据成员b

)

C++4章_P25

classderived2:privatederivedl

声明—t*基类为derivedl的私有派生类derived2

private:

intc://派生类新增私有数据成员c

public:

voidsetabc(intsa,intsb,intsc)

〃派生类新增置初值成员函数setabc()

setab(sa,sb);调用基类成员函数setab()初始化a,b

C=SC//最后给本派生类私有数据成员c赋初值

voidshowabc()〃派生类新增成员函数showabc()

showab();〃正确,调用直接基类derivedl中公有成员函

数showabO,派生类derived2可以调用

cout«"c=,z«c«endl;

//正确,输出本类的私有数据成员c

};

voidmain()

baseopl;〃创建基类对象opl

C++4章_P26

opl.seta(1);对象opl调用基类base成员函数setx()置a值为1

opl.showa();对象opl调用基类base成员函数showa()输出a=l

derivedlop2;创建派生类derivedl对象op2

op2.setab(2,3);

对象op2调用派生类derivedl成员函数setab()置a值为2,b值为3

op2.showab();

对象op2调用派生类derivedl成员函数showab()输出a=2,b=3

derived2op3;创建基类为derivedl的派生类derived2对象op3

op3.setabc(4,5,6);

对象op3调用派生类derived2成员函数setabc()

〃置a值为4,b值为5,c值为5

op3.showabc();

//对象op3调用派生类derived2成员函数

showabc()输出a=4,b=5,c值为6

}

程序的运行结果为:

a=1

a=2

b=3

a=4

b二5

c二6

(3)保护继承(保护派生)的访问规则(书P121)

(a)基类的public和protected成员被继承后在派生

类均作为protected成员。

C++4章_P27

(i)派生类内的成员可以直接访问它们。

(ii)类的外部也不能通过派生类的对象访问。

(b)基类的private成员,派生类不可直接访问。所以

无论派生类成员或派生类对象都不能直接访问基类的

private成员。

例4.4(书P121)

#include〈iostream.h>

classbase声明一个基类base

(

private:

intx;

protected:

inty;

public:

intz;

voidsetx(inti)基类定义成员函数setxy

{x=i;}

intgetxO

{returnx;}

);

C++4章_P28

classDerived:protectedbase声明—公有派生类

{private:

intm;〃派生类新增私有数据成员m

protected:

intn;〃派生类新增保护数据成员n

public:

intp;〃派生类新增公有数据成员P

voidsetall(inta,intb,intc,intd,inte,intf);

//派生类新增公有成员函数setall()

voidshowO;派生类新增公有成员函数show。

);

voidDerived::setall(inta,intb,intc,intd,inte,intf)

〃定义派生类新增成员函数setall()

{//x=a;

〃非法,在派生类Derived中,基类base的私有数据成员x不可以直接访问

setx(a);

〃正确,通过基类公有函数setx()可给私有数据成员x赋初值

y=b;//最后初始化派生类私有数据成员z

Z=C;

m=d;n=e;p=f;

C++4章_P29

voidDerived::show()〃定义派生类新增成员函数showO

cout«"x="<<x«endl;

〃非法,在派生类Derived中,基类base的私有数据成员x不可以直接访问

cout«"x="«getx()«endl;

cout«"y="<<y«endl;

cout<<"z="<<z«endl;

cout«"m="<<m«endl

cout<<"n="<<n«endl;

)

voidmain()

(

Derivedobj;创建派生类对象obj

obj.setall(1,2,3,4,5,6);

〃正确,派生类对象直接访问公有成员函数setall()

obj.showO;〃正确

cout«"p="<<obj.p«endl;

〃正确,可以通过派生类对象访问派生类公有数成员P

改为例4_4_1

C++4章_P30

程序的运行结果为:

X=1

y=2

z二3

m=4

n二5

p=6

三、派生类的构造函数和析构函数(书P123)

1、为什么要有派生类的构造函数和析构函数

派生类继承了基类的成员,实现了原有代码的重用。

但基类的构造函数和析构函数是不能继承的。另外,派生

类可以通过添加新的成员加入新的功能才发挥派生的作

用。

为此,派生类要有自己的构造函数和析构函数。构造

函数的任务是,一方面向基类的构造函数传递所需要的参

数(因为从基类继承来的成员的初始化工作仍由基类的构

造函数进行)。另方面为派生类新增成员进行初始化。析构

函数的任务是,当撤消派生类对象时完成扫尾和清理工作。

C++4章_P31

2、派生类的构造函数和析构函数的执行顺序

派生类创建对象时先执行基类构造函数,然后执行派

生类构造函数。

撤消派生类对象时先执行派生类的析构函数,然后执

行基类析构函数。

例4.5(书P123)可以看清楚构造函数和析构函数的执行

顺序。

ttinclude<iostream.h>

classbase〃声明一个基类

(

public:

base()〃定义基类构造函数

{cout«〃执行基类构造函数〃<<endl;}

/,输出构造函数标志

~base()〃定义基类析构函数

{cout«〃执行基类析构函数〃«endl;}

//输出析构函数标志

};

C++4章_P32

classderive:publicbase定义派生类derive

public:

derive()定义派生类derive构造函数

{cout«〃执行派生类构造函数〃«endl;}

//输出派生类构造函数标志

“derive()〃定义派生类析构函数

{cout«〃执行派生类析构函数〃<<endl;}

//输出派生类析构函数标志

);

main()

{deriveobj;创建对象obj

return0;

}

C++4章_P33

程序的运行结果为:

执行基类构造函数

执行派生类构造函数

执行派生类析构函数

执行基类析构函数

3、派生类构造函数的构造规则

(1)若基类构造函数没有显式定义构造函数或构造函数没

有参数,派生类可以不向基类构造函数传递参数。若派生

类本身不必初始化,可以不定义构造函数。例4.5(书P123)

派生类构造函数就没向基类传递参数。

(2)当基类含有带参构造函数时,派生类必须定义构造函

数以提供向基类构造函数传递参数途径。

(3)派生类构造函数定义格式I(派生类无内嵌对象成员)

派生类名(参数总表):基类名(参数表)

〃派生类新增成员的初始化语句

其中,

(D基类名的参数表的参数是实参通常出现在参数总表

(参数总表的参数是形参)中,也可以用常数值表。

C++4章_P34

(ii)在创建派生类对象时构造函数执行时先传递参数执

行基类构造函数,然后执行派生类构造函数体为派生类新

增成员赋初值。

撤消派生类对象时,析构函数的执行顺序与构造函数

的执行顺序相反。

例4.6(书P124)

#include<iostream.h>

classbase//声明一个基类

(

inti;

public:

base(intn)〃定义基类带参构造函数

(

cout<〈〃执行基类构造函数〃<<endl;//输出构造函数标志

i=n;

)

~base()〃定义基类析构函数

{cout«〃执行基类析构函数〃«endl;}〃输出析构函数标志

voidshowi()〃定义输出基类私有数据成员i的函数showi()

{cout«“i=”«i«endl;}

};

C++4章_P35

classderive:publicbase定义公有派生类derive

{intj;

public:

derive(intn,intm):base(m)

〃定义派生类derive构造函数给基类构造函数传递参数m

(

cout«〃执行派生类构造函数〃«endl;

//输出派生类构造函数标志

j=n;〃给派生类私有数据成员j初始化

)

"derive()定义派生类derive析构函数

{cout«"执行派生类析构函数〃«endl;}

/输出派生类derive析构函数标志

voidshowj()〃定义输出派生类私有数据成员j的函数showj()

{cout«“j="<<j«endl;}

};

main()

{deriveobj(30,40);

〃创建对象obj,提供参数40初始化基类私有数据成员i

//提供参数30初始化派生类私有数据成员j

obj.showi();调用基类公有函数showi()输出i的值

C++4章_P36

obj.showj();//调用派生类公有函数showj()输出j的值

return0;

程序的运行结果为:

执行基类构造函数

执行派生类构造函数

i=40

j=30

执行派生类析构函数

执行基类析构函数

(4)派生类构造函数定义格式II(含内嵌对象成员)

派生类名(参数总表):基类名模数表TE嵌对象名口硒

嵌对象参数表1),…,内嵌对象名n(内嵌对象参数表n)

初始化列表

〃派生类新增成员的初始化语句

}

其中,

(i)基类名和内嵌对象的参数表的参数是实参通常出

现在参数总表中,也可以用常数值表。

(ii)在创建派生类对象时构造函数执行顺序:

(a)调用基类构造函数

C++4章_P37

(b)调用内嵌对象成员的构造函数(若有多个内嵌对象成

员时,调用顺序按它们在派生类中声明内嵌对象的顺序确

定,而不是按派生类构造函数初始化列表中的顺序)。

(C)执行派生类构造函数体为派生类新增成员赋初值。

撤消派生类对象时,析构函数的执行顺序与构造函数

的执行顺序相反。

例4.7(书P126)

ttinclude<iostream.h>

classbase声明一个基类base

(

intx;

public:

base(inti)〃定义基类构造函数

(

x=i;

cout<〈〃执行基类构造函数〃<<endl;〃输出构造函数标志

)

~base()〃定义基类析构函数

{cout<<〃执行基类析构函数〃6endl;}/输出析构函数标志

C++4章_P38

voidshow()

{cout«"x="<<x«endl;}

);

classderive:publicbase定义派生类derive

(

based;//d为基类base对象,作为派生类的对象成员

public:

derive(inti):base(i),d(i)

〃定义派生类derive构造函数给基类和内嵌对象成员构造函数传递参数

{

cout«〃执行派生类构造函数〃«endl;

//输出派生类构造函数标志

)

derive()//定义派生类析构函数

{cout«〃执行派生类析构函数〃«endl;}

//输出派生类析构函数标志

);

main()

{deriveobj(5);

〃创建对象。bj,提供参数5给基类和内嵌对象成员构造函数传递参数5

C++4章_P39

obj.show();

return0;

程序的运行结果为:

执行基类构造函数(调用基类构造函数)

执行对象类构造函数(调用内嵌对象成员的构造函数)

执行派生类构造函数(调用派生类构造函数)

x=5

执行派生类析构函数(调用派生类析构函数)

执行对象类析构函数(调用内嵌对象成员的析构函数)

执行基类析构函数(调用基类析构函数)

几点说明:

(i)当基类构造函数不带参数时,派生类不一定要定义构

造函数。若基类构造函数即使只有一个参数,即使派生类

本身没有初始化任务,派生类也一定要定义构造函数。例

如(书P127)下面的程序段中,派生类构造函数就不使用

参数n,n只是被传递给了基类构造函数base()

例4_7_3:

#include<iostream.h>

classbase声明一个基类base

inti;

C++4章_P40

public:

base(intn)〃定义基类构造函数

(

cout«〃执行基类构造函数〃«endl;〃输出构造函数标志

i=n;〃给i赋初值n

)

voidshowi()输出i的函数

{cout«"i="<<i«endl;}

);

classderive:publicbase

〃定义派生类derive,是基类base的公有派生

(

intj;//派生类的新增数据成员j

public:

derive(intn):base(n)

〃定义派生类derive构造函数给基类构造函数传递参数n

(

cout«〃执行派生类构造函数〃«endl;

〃输出派生类构造函数标志

j=0;派生类derive构造函数体内给j赋初值0

)

C++4章_P41

voidshowj()//派生类的新增输出j的函数

{cout«"j="<<j«endl;}

);

mainO

{deriveobj(5);

〃创建对象obj,提供参数5给基类构造函数传递赋初化i的值为5

obj.showi();

obj.showj();

return0;

)

程序的运行结果为:

执行基类构造函数(调用基类构造函数)

执行派生类构造函数(调用派生类析构函数)

i二5

j=0

若派生类没有新增数据成员需要初始化或新增数据成员不

必用派生类构造函数参数初始化,则派生类构造函数的函

数体可以是空的,参数表仅仅起到传递参数作用。

例如,下面的程序是上面(127)程序的修改为

C++4章_P42

例4_7_2:

^include<iostream.h>

classbase声明一个基类base

{inti;

public:

base(intn)定义基类构造函数

(

cout«”Constructingbaseclass"«endl;输出构造函数标志

i=n;〃给i赋初值n

)

voidshowi()〃输出i的函数

{cout«"i="«i«endl;}

};

classderive:publicbase

〃定义派生类derive,是基类base的公有派生

(

intj;〃派生类的新增数据成员j

public:

derive(intn):base(n)

//定义派生类derive构造函数给基类构造函数传递参数n

{}〃派生类的函数体是空的

C++4章_P43

voidsetj(intm)〃派生类的新增置j值的函数

{j=m;}

voidshowj()〃派生类的新增输出j的函数

{cout«"j="<<j«endl;}

);

mainO

{deriveobj(5);

〃创建对象obj,提供参数5给基类构造函数传递赋初化i的值为5

obj.showi();调用基类showi()函数输出i的值5

obj.setj(0);//调用派生类setj()函数给j赋值0

obj.showj();调用派生类showj()函数输出j的值0

return0;

)

程序的运行结果为:

执行基类构造函数(调用基类构造函数)

i二5

j

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论