c++实验报告8.docx

上传人:b****2 文档编号:2362431 上传时间:2022-10-29 格式:DOCX 页数:36 大小:384.48KB
下载 相关 举报
c++实验报告8.docx_第1页
第1页 / 共36页
c++实验报告8.docx_第2页
第2页 / 共36页
c++实验报告8.docx_第3页
第3页 / 共36页
c++实验报告8.docx_第4页
第4页 / 共36页
c++实验报告8.docx_第5页
第5页 / 共36页
点击查看更多>>
下载资源
资源描述

c++实验报告8.docx

《c++实验报告8.docx》由会员分享,可在线阅读,更多相关《c++实验报告8.docx(36页珍藏版)》请在冰豆网上搜索。

c++实验报告8.docx

c++实验报告8

评语:

评分项目

评分内容

分值

评分结果

预习情况

是否完成预习工作。

要求按实验指导书进行预习、并完成实验报告初稿、编写程序。

20

实验方案

实验方案是否可行。

要求目的、任务明确、原理清楚、步骤可操作、对实验过程数据有记录方案、对可能的错误有预备方案。

30

实验过程

与结果

实验结果是否正确。

要求完成实验过程中的数据记录、记录要完整和准确、内容要详细,实验结果要与预期的正确结果一致。

35

实验结论

实验结论是否正确。

要求根据实验原理对实验过程中的数据、实验结果进行分析,得出实验结论。

15

总分

100

 

指导教师(签名)

年月日

说明:

指导教师评分后,实验报告交院(系)办公室保存。

实验8继承

一.实习目的及要求

1)掌握继承的实现方法;

2)继承中常见问题的处理方法。

二.预习

预习派生类的定义和使用、创建派生类对象时构造函数的调用次序、多重继承中的冲突、及虚基类。

预习笔记总结:

Class派生类名:

继承方式基类名1,继承方式基类名2,…{};

使

吸收基类成员

包含基类除构造和析构函数之外的所有成员

改造基类成员

新成员与基类成员同名则派生类(或其对象)只能访问派生类中同名的成员

添加基类成员

需要在派生类中加入新的构造和析构函数

继承方式

基类

公有成员

保护成员

私有成员

公有继承

公有成员

保护成员

无论是派生类成员还是派生类对象都无法直接访问基类的私有成员

私有继承

私有成员

私有成员

保护继承

保护成员

保护成员

类型兼容规则

在需要基类对象的任何地方,都可使用公有派生类的对象来替代。

在替代之后,派生类对象就可以作为基类的对象使用,但只能使用从基类继承的成员。

派生类的对象可以赋值给基类的对象;可以初始化基类的引用

派生类对象的地址可以赋给指向基类的指针。

派生类构造函数

语法

派生类名:

派生类名(参数表):

基类名1(参数表1),…,基类名n(参数表n),内嵌对象名1(内嵌对象参数表1),…内嵌对象名m(内嵌对象参数表m){}

执行次序

调用基类构造函数,调用顺序按照它们被声明的的顺序(从左向右)

调用内嵌成员对象的构造函数,调用顺序按它们在类中声明的顺序

派生类的构造函数体中的内容

如果基类声明了带有形参表的构造函数时,派生类应当声明构造函数,提供一个将参数传递给基类构造函数的途径,保证在基类惊醒初始化时能获得必要的数据。

多重继承

冲突

多继承同名隐藏:

派生类成员隐藏所有基类的同名成员

作用域

分辨符

如果访问被隐藏的成员,可以使用作用域分辨符和基类名来限定(基类名:

成员名),且必须使用直接基类来限定

虚函数

从不同路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数名也只有一个映射

三.实验内容

3.1分析下面的程序,指出程序运行的结果

1)分析下面的程序,指出程序运行的结果:

#include

classCBase

{

public:

voidfn1();

};

voidCBase:

:

fn1()

{cout<<"调用基类类的函数fn1()\n";

}

classCDerived:

publicCBase{

public:

voidfn1();

};

voidCDerived:

:

fn1()

{cout<<"调用派生类的函数fn1()\n";

}

voidmain()

{

CDerivedd1;//派生类对象

CBase*pb=&d1;//派生类对象的地

//址赋给指向基类的指针

CBase&pd=d1;//派生类的对象初始//化基类的引用

d1.fn1();

pb->fn1();

pd.fn1();

程序分析:

a)类分析:

此程序有两个类:

基类CBase和派生类CDerived。

类CDerived公有继承类CBase。

类的派生关系的UML图形和对象图表示如下:

b)main部分分析:

根据类型兼容原则,在替代之后,派生类对象就可以作为基类的对象使用,但只能使用从基类继承的成员。

派生类对象d1的地址赋给指向基类的指针pb,通过这个基类类型的指针只能访问从基类CBase继承的fn1(),也就是说虽然pb指向派生类CDerived的对象d1,fn1函数运行时通过这个指针pb这能访问CDerived从CBase继承过来的fn1(),而不是CDerived类中自己的同名成员函数。

同理,派生类的对象初始化基类的引用也是类型兼容替代的一种,通过pd.fn1();访问CDerived从CBase继承过来的fn1(),而不是CDerived类中自己的同名成员函数。

c)结合上述分析,结果预测:

调用派生类的函数fn1()

调用基类类的函数fn1()

调用基类类的函数fn1()

d)调试运行如下,和结果预测分析一致

2)分析下面的程序,指出程序运行的结果:

#include

classCBase1

{

intx;

public:

CBase1()

{x=0;cout<<"调用构造函数CBase1()!

\n";}

CBase1(inta)

{x=1;cout<<"调用构造函数CBase1(int)!

\n";}

~CBase1(){cout<<"调用析构函数~CBase1()!

\n";}

};

classCBase2

{

inty;

public:

CBase2()

{y=0;cout<<"调用构造函数CBase2()!

\n";}

CBase2(inta)

{y=a;cout<<"调用构造函数CBase2(int)!

\n";}

~CBase2(){cout<<"调用析造函数~CBase2()!

\n";}

};

classA

{intx;

public:

A(){x=0;cout<<"调用构造函数A()!

\n";}

A(inta){x=a;cout<<"调用构造函数A(int)!

\n";}

~A(){cout<<"调用析构函数~A()!

\n";}

};

classCDerived:

publicCBase1,virtualpublicCBase2

{

Aa;

public:

CDerived()

{cout<<"调用构造函数CDerived()!

\n";}

CDerived(intx,inty,intz):

a(x),CBase1(y),CBase2(z)

{cout<<"调用构造函数CDerived(int,int)!

\n";}

~CDerived(){cout<<"调用析造函数~CDerived()!

\n";}

};

voidmain()

{

CDerived*x=newCDerived;

CDerivedy(2,3,4);

deletex;

cout<<"main()函数结束!

\n";

}

程序分析:

a)类分析:

本程序有三个类,其中类CDerived公有继承类CBase1和虚基类CBase2,类CDerived使用类A。

类图和对象图如下:

b)main部分分析:

首先,创建CDerived类指针对象指向CDerived类型数据的内存的首地址,同时按次序调用基类和内嵌对象成员的无参数构造函数初始化。

建立CDerived类对象y并通过构造函数CDerived(intx,inty,intz):

a(x),CBase1(y),CBase2(z)初始化基类和内嵌对象成员,参数表给出了基类及内嵌成员对象所需的全部参数:

根据构造函数调用次序,先调用虚基类CBase1的有参数构造函数,接着调用基类CBase2的有参数构造函数,再调用内嵌对象a的有参数构造函数。

在用delete清理对象x:

按构造函数相反的次序执行派生类析构函数体、调用派生类对象成员所在类的析构函数和调用基类析构函数。

最后自动按同样的次序清理对象y。

c)根据上述分析结果预测:

调用构造函数CBase1()!

调用构造函数CBase2()!

调用构造函数A()!

调用构造函数CDerived()!

调用构造函数CBase1(int)!

调用构造函数CBase2(int)!

调用构造函数A(int)!

调用构造函数CDerived(int,int)!

调用析造函数~CDerived()!

\

调用析构函数~A()!

调用析造函数~CBase2()!

调用析构函数~CBase1()!

main()函数结束!

调用析造函数~CDerived()!

\

调用析构函数~A()!

调用析造函数~CBase2()!

调用析构函数~CBase1()!

d)程序运行与结果演示,发现和预测的不一致:

e)错误分析:

对比结果演示和结果预测发现不同点在于类CBase1和类CBase2的构造和析构函数执行的次序问题。

调用基类构造函数,调用顺序按照它们被声明的的顺序(从左向右),但是基类CBase1在左,虚基类CBase2在右,它们构造函数调用次序从右到左了!

虚基类构造函数调用顺序优先于一般基类。

3.2编写并调试程序:

1).定义一个图形类,其中有保护类型的成员数据:

高度和宽度,一个公有的构造函数。

由该图形类建立两个派生类:

矩形类和等腰三角形类。

在每个派生类中都包含一个函数Area(),分别用来计算矩形和等腰三角形的面积。

a)编程实践方案:

分析

对象分析:

有几个对象,对象之间有什么关系

类分析:

确定类(是否有必要存在)、类名、类的成员和类间关系

设计

根据分析设计图形类、三角形类、矩形类和main的代码

代码测试

在VisualC++平台编译,调试。

如有语法错误,双击调试窗口错误的地方,纠正错误并作错误分析。

如有逻辑错误,重新审核代码设计是否符合要求。

结果预测

长10宽20的矩形的面积为200;长15宽10(底)的三角形的面积为75;长7.8宽8.9的矩形面积为68.42,三角形为34.71

实现

记录测试数据结果和最后的正确代码

b)对象分析

有两类对象:

矩形和等腰三角形。

矩形具有高度、宽度等静态属性,它的面积=高度*宽度;等腰三角形也具有高度、宽度(底)等静态属性,面积=高度*宽度/2。

它们共同的数据属性高度hight和宽度width,不同的面积操作,即动态属性。

所以,两个对象都是图形,但是它们的面积求法不同。

设置两个具体的对象长10宽20的矩形S和长15宽10(底)的三角形T。

c)类分析和设计

根据对象分析,可以抽象出图形类,类名为graph,它包括float类型的hight和width的保护类型数据成员和对数据初始化的构造函数。

同时图形是可被计算面积,因此根据面积求法不同派生出矩形类square和三角形类triangle,它们继承了图形类graph的hight和width数据成员,同时还添加Area()函数实现求面积的功能。

类设计代码如下:

classgraph{

protected:

floathight,width;

public:

graph(floata,floatb){hight=a;width=b;}

};

classtriangle:

publicgraph{

public:

triangle(float

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1