当前位置:文档之家› 实验五类的继承与派生

实验五类的继承与派生

实验五类的继承与派生
实验五类的继承与派生

第一节类的继承与派生

一、基本概念

继承是面向对象程序设计的一个特性,所谓继承就是在已有类的基础上创建新的类,新类可以从一个或多个已有类中继承成员函数或数据成员,而且新类还可以重新定义或加进新的数据和函数。其中,已有类称为基类或父类,新类称为派生类或子类。

在现实世界中许多事物都具有继承性。例如:“汽车”这个类中包括了许多类型,有运输汽车、专用汽车;运输汽车中又包括客车、货车…….;专用汽车中又包括巡逻车、消防车、救护车……..;所有这些类型的车都具有汽车的共同特性即都有发动机、车身、轮胎等共性,还都是自行驱动的。

而客车和货车又有所不同,客车用来载客,货车用来拉货,它们有自己不同于其它车的特性,这就是继承。我们把汽车称为基类,把运输汽车、客车、货车称为派生类。通过继承,派生类不仅拥有了基类的属性和行为,而且具有不同于它类的自己的特点。

二、派生类的定义与构成

当你去水果店买水果的时候,你经常会发现很多同类水果又有了新的品种。比如,“李子”既小又涩,嫁接在梨树上后长出来的李子却硕大、香甜、清脆,比没有嫁接的李子好吃,但它还是李子家族中的一员;所以,可以认为“嫁接李子”是从“李子”中派生出来的。当然,可以把“李子”嫁接在梨树上,也可以嫁接在苹果树上,结出来的都是“李子”,但是各自味道不同。

所谓派生就是从已有类中产生一个新的子类。

基类就是已存在的可以派生新类的类,如下图中的A、D、E都是基类。

派生类就是由基类派生出来的新类,如下图中的B、C、F都是派生类。

1. 单继承派生类的定义格式

class <派生类名> : <继承方式> <基类名>

{

派生类成员的定义;

};

其中,“派生类名”是新定义的一个类的名字,它是从“基类名”中派生的,并且按指定的“继承方式”派生。

例如:

class peach // 基类

{

datatype color , shape ;

};

class sweetpeach :public peach // 单继承

{

datatype color , shape, taste ;

};

sweetpeach类只是继承自peach类,即sweetpeach类只有一个基类,这就是单继承。

2. 多继承派生类的定义格式

class <派生类名> :<继承方式1> <基类名>,<继承方式2> <基类名>, …….

{

派生类成员的定义;

};

多继承与单继承在定义格式的区别仅在于它们的基类个数不同,单继承的基类只有一个,而多继承的基类有多个,相邻两个基类之间用逗号间隔,每个基类名前都应有一个该基类的继承方式的说明符。

例如:

class peach //定义基类:peach

{

datatype color , shape ;

};

class apple //定义基类:peach

{

datatype color, shape , weight ;

};

class sweetpeach : public peach, public apple // 多继承

{

datatype color, shape, taste;

};

类sweetpeach 同时继承自类peach 和类apple,这就是多继承。

3.继承的作用

有的读者可能会问为什么要有继承,继承有什么好处,继承的作用是什么?

为了解决这些疑问,我们一起来分析以下例子,从中领悟继承的奥妙。

【例10-1-1】分析以下代码。声明一个person 类,它包含的成员有name(姓名)、age(年龄)、gender(性别),和output函数,具体定义如下:

class person

{

public :

char name[8] ;

int age;

char gender ;

public :

void output() { }

};

现在要声明一个student类,它包含的成员有name(姓名),age(年龄),gender (性别),department(系),stuno(学号),address(住址),和output函数,具体定义如下:

class student

{

public :

char name[8] ;

int age;

char gender;

char department[20] ;

int stuno;

int address;

public :

void output() { }

};

从这两个类的声明中可以看出,它们中有些成员数据和成员函数是相同的。这样就存在代码的重复,为了提高代码的可重用性,就引入了继承。即,如果student类以共有继承的方式继承person类,那么student类就可以直接使用person类中的共有成员如name, gander,age和output() 函数,这样在student类中就不需要再定义与person 类中相同的变量了,只定义person类中没有的在student类中需要的变量。具体实现如下:class student : public person // student共有继承person类

{

public :

char department[20] ;

int stuno ;

int address ;

public :

void output() { }

};

提示

?student 类称为派生类,person类成为基类;

?关键字public 的作用是说明派生类公有继承了基类中的所有成员,即派生类可以直接访问基类的成员;

?继承可以使代码得以重用,提高工作效率。

三、派生类访问基类成员

通过前面的学习大家都知道基类的成员有public(公有)、protected(保护)、private (私有)3种访问属性,基类的自身成员可以对基类中任何一个其他成员进行访问,但是通过基类的对象就只能访问该类的公有成员。

派生类可以继承基类中除了构造函数和析构函数之外的全部成员,但是这些成员的访问属性在派生过程中是可以调整的。从基类继承来的成员在派生类中的访问属性是由继承方式控制的。不同的继承方式导致原来具有不同的访问属性的基类成员在派生类的访问属性也有所不同。

在派生类中,从基类继承来的成员可以访问属性有4种:不可直接访问的成员、public (公有成员)、protected(保护成员)、private(私有成员)。

1.三种继承方式的声明

public 公有继承

公有继承:在定义一个派生类时将基类的继承方式指定为public 的继承方式。

例如:class student : public person { }

private 私有继承

私有继承:在定义一个派生类时将基类的继承方式指定为private的继承方式。

例如:class student : private person { }

protected 保护继承

保护继承:在定义一个派生类时将基类的继承方式指定为protected的继承方式。

例如:class student : protected person { }

2.三种继承方式的区别

如表1指明了三种继承方式的区别,即派生类对基类成员的访问能力。

表1 三种继承方式的区别

在基类中的访问属性继承方式在派生类中的访问属性

private public 不可直接访问

private private 不可直接访问

private protected 不可直接访问

public public public

public private private

public protected protected

protected public protected

protected private private

protected protected protected

提示

?在任何继承方式中基类中的私有成员都不允许派生类继承,即在派生类中是不可直接访问基类中的私有成员。

?当类的继承方式为公有继承时:基类中的所有公有成员在派生类中仍为公有成员;基类中的所有保护成员在派生类中仍为保护成员。

?当类的继承方式为私有继承时:基类中的所有公有成员在派生类中都为私有成员;基

类中的所有保护成员在派生类中都为私有成员。

?当类的继承方式为保护继承时:基类中的所有公有成员在派生类中都为保护成员;基类中的所有保护成员在派生类中仍为保护成员。

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

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

(2) 对象访问:在派生类外部,通过派生类的对象对从基类继承的成员的访问。

现在分别讨论在公有继承、私有继承、保护继承这3种继承方式下,派生类对基类成员的访问规则。

一、公有继承

【例1】分析以下程序。

源代码:

#include

#include

class Base

{

private:

int pvx; //pvx为基类私有变量

protected :

int pty; //pty为基类保护变量

public :

float puf; //puf为基类公有变量

void Setxy(int q, int u, float w) //Setxy()为基类公有函数{

pvx = q ; pty = u; puf = w;

}

void Output() //Output()为基类公有函数

{

cout << "class Base output "<< endl;

cout << "pvx= " << pvx << endl;

cout << "pty= " << pty << endl;

cout << "puf= " << puf << endl;

}

};

class Derive : public Base //公有单继承

{

private :

float pvz;

public :

void Setvalue(int x, int y, float f, float z)

{

Setxy(x, y, f);

pvx = x; //非法访问,基类中的pvx为private属性,不能被继承

pty = y; //合法访问

puf = f; //合法访问

pvz = z;

}

void Print()

{

cout << "pvx= " << pvx << endl;// 非法访问,在基类中pvx为私有成员cout << "class Derive output " << endl;

cout << "pty= "<

cout << "puf= "<

}

运行输出:

class Base output

pvx= 3

pty= 5

puf= 8.9

class Derive output

pty= 5

puf= 8.9

pvz= 12.6

puf= 8.9

【简要分析】

①“class Derive : public Base { }”表明这是一个公有继承的例子,基类Base中有3个变量和两个函数:私有变量pvx、保护变量pty、公有变量puf和公有函数Setxy()、Output()。

其中:被Derive派生类继承后,pvx在派生类中不能直接访问,只能通过Base中具有public属性的函数对其间接访问;pty被Derive派生类继承之后仍为protected属性,派生类成员可以直接访问;puf、Setxy()、Output()这3个具有public属性成员被Derive 派生类继承后,仍为public属性,派生类成员可以对其直接访问。

②输出的前4行:调用“obj.Output();”的输出结果。

输出的后4行:调用“obj.Print();”的输出结果。

最后1行:调用“cout << "puf= " << obj.puf << endl;”的输出结果。

结论:在公有继承中,无论是派生类中的成员还是派生类对象都不能直接访问基类中的private成员;派生类的成员可以访问继承来的protected成员和public成员;但是,类的外部使用者只能通过派生类的对象访问继承来的public成员,不能访问继承于基类的

private和protected成员。

二、私有继承

【例2】任务1:分析以下程序。

a)找出非法语句并在程序中注释非法的原因。

b)写出删除非法语句后程序的运行结果。

源代码:

#include

#include

class Base

{

private:

int pvx;

protected:

int ptf;

public :

void Setxf(int w, int f)

{

pvx = w; ptf = f;

}

void Print()

{

cout << "pvx= " << pvx << endl;

cout << "ptf= " << ptf << endl;

}

};

class Derive:private Base //私有继承

{

private:

double pvy ;

protected:

double ptz;

public:

int pd;

void Setvalue(int a, int b, double c, double d) {

pvx = a;

ptf = b + 6;

Setxf(a, b);

pvy = c;

ptz = d;

pd = 90;

}

void Output()

{

cout << "pvx= " << pvx << endl;

Print();

cout << "pvy= " << pvy << endl;

cout << "ptz= " << ptz << endl;

}

};

void main()

{

Derive obj;

obj.Setvalue(1, 6, 5.3, 3.8);

obj.Output();

obj.Setxf(101, 87);

cout << "pvx= " << obj.pvx << endl;

cout << "pvy= " << obj.pvy << endl;

cout << "ptz= "<

obj.pd = 68;

cout << "pd= " << obj.pd << endl;

system("pause");

}

【简要分析】

“class Derive :private Base{ }”表明这是一个私有继承,Base基类中有3个变量和两个函数:私有pvx、保护ptf、公有函数Setxf()、公有函数Print()。

基类Base被私有继承之后,其protected成员在派生类中不能直接访问;而protected 成员和public成员都成了派生类的私有成员,只有派生类的成员才能直接访问;派生类对象也不能直接访问继承自Base的protected成员和public成员。

结论:私有继承中,基类中的protected、public成员都成为派生类中的private成员,派生类成员不能直接访问基类中的private成员,而派生类中的成员可以直接访问基类中的protected、public属性的成员;派生类对象不能直接访问基类中的任何成员。

三、保护继承

【例3】任务2:分析以下程序。

a)找出非法语句并在程序中注释非法的原因。

b)写出删除非法语句后程序的运行结果。

源代码:

#include

#include

class Base

{

private:

int pvx;

protected:

int pty;

public:

int puz;

void setx(int a)

{

pvx = a;

}

int getx()

{

return pvx;

}

};

class Derive:protected Base // 保护继承

{

private:

int pva;

protected:

int ptb;

public:

int puc;

void setvalue(int a, int b, int c, int d, int e, int f) {

pvx = a;

setx(a);

pty = b;

puz = c;

pva = d;

相关主题
文本预览
相关文档 最新文档