多态性和虚函数实验手册Word下载.docx
- 文档编号:21879701
- 上传时间:2023-02-01
- 格式:DOCX
- 页数:14
- 大小:43.44KB
多态性和虚函数实验手册Word下载.docx
《多态性和虚函数实验手册Word下载.docx》由会员分享,可在线阅读,更多相关《多态性和虚函数实验手册Word下载.docx(14页珍藏版)》请在冰豆网上搜索。
那么程序中应该实现的是将n对象中的value值加1后,再返回这个对象本身即可。
返回对象本身可以借用this指针来实现,代码如下:
return*this;
//再返回原对象
使用后增量时,必须在增量之前返回原有的对象值。
为此,需要创建一个时时对象,存放原有的对象,以便对操作数(对象)进行增量修改,所以,返回的应该是存放原有对象值的临时对象。
那么如果实现(n++).display(),应该产生的结果还是1。
原因是对象执行了增量操作但应该是先显示原来的值,然后再把增加后的值赋给value。
解决这一问题的方案是先保存原对象,然后再进行增量运算,但函数返回的应该还是原对象,这样在进行(n++).display()操作时才会是1,而不是2。
2)成员形式的重载
所谓成员就是在定义类的内部实现的方法。
我们先来看一下没有增加实现增量操作的类定义:
classIncrease
{
public:
Increase(intx):
value(x){}
voiddisplay()
{
cout<
<
"
thevalueis"
<
value<
endl;
}
private:
intvalue;
};
用以上定义的类定义一个对象Increasen(20);
是不能够实现n++或++n的操作的。
为了实现能让对象进行增量操作可以在类的内部重新定义操作符++的含义。
我们先来看如何实现++n操作,即在类中增加如下代码:
Increase&
Increase:
:
operator++()
value++;
//先增量
return*this;
}
我们再来看如何实现n++操作,即在类中增加如下代码:
IncreaseIncrease:
operator++(int)
Increasetemp(*this);
//临时对象存放原有对象值
//原有对象增量修改
returntemp;
//返回原有对象值
我们来看一下完整的程序代码:
#include<
iostream.h>
value(x){}
Increase&
operator++();
//前增量
Increaseoperator++(int);
//后增量
voidmain()
Increasen(20);
n.display();
(n++).display();
//显示临时对象值
//显示原有对象
++n;
++(++n);
(n++)++;
//第二次增量操作对临时对象进行
运行以上程序,运行结果如图5.1。
图5.1:
运行结果
3)非成员形式的重载
非成员形式实现增量操作的原理与成员形式的方式实现是类似的,不同之外是非成员形式实现是以外部函数的方式实现,但外部函数要想操作类中的私有成员需要在类中将本函数实现为友员函数。
在上述2)中的原始类的基础上,我们增加如下代码:
a.非成员函数的代码如下:
operator++(Increase&
a)
a.value++;
returna;
Increaseoperator++(Increase&
a,int)
Increasetemp(a);
//通过拷贝构造函数保存原有对象值
b.由于在上述非成员函数中都有对Increase中的私有成员变量value进行直接操作,所以需要在原类中增加如下代码:
friendIncrease&
);
friendIncreaseoperator++(Increase&
int);
c.完整的代码如下:
//第二次增量操作临时对象进行
编译运行上述代码,运行结果同图5.1所示.
2.动态绑定
虚函数是动态(在运行时)绑定的。
在动态绑定中,成员函数是根据对象的类型而不是根据指向对象的指针/引用的类型来动态地(在运行时)选择的。
在下面的程序中,我们将看到动态绑定是如何工作的。
使用动态绑定的步骤如下:
1.声明基类
声明一个名为person的基类。
在该类中,声明一个保存姓名的字符型指针变量,还有一个构造函数来初始化该字符型的指针变量。
函数print()被定义为一个虚成员函数,可以在派生类中重新实现它。
函数的定义前面有关键字virtual,它指示编译器对该函数使用动态绑定。
代码如下所示:
classPerson
protected:
char*name;
Person(char*n)
name=n;
virtualvoidprint()
我的名字是"
name<
2.声明派生类
从基类Person公有派生一个类Foreigner。
该类的构造函数调用基类的构造函数。
函数print()在该派生类中被重新定义。
这一部分的代码如下所示:
classForeigner:
publicPerson
Foreigner(char*n):
Person(n){}
voidprint()
mynameis"
};
3.声明另一个派生类
从基类Person公有派生一个名为Alien的类。
classAlien:
Alien(char*s):
Person(s){}
^*^*^**^*^$%%$%%#$#$^&
^&
*^*&
(*"
对不起,出现通信故障"
4.在main()函数中,声明Person类型的两个指针
Person*person1;
Person*person2;
5.Person类型的一个指针与基类的一个对象关联,另一个指针与派生类Foreigner的一个对象关联。
person1=newPerson("
王大明"
person2=newForeigner("
Lisa"
6.调用基类Person的函数
cout<
介绍人员:
"
person1->
print();
7.调用派生类Foreigner的函数。
编译器在运行时决定调用这两个函数中的哪一个,根据赋给指针person2的值来作出这个决定。
介绍外宾:
person2->
8.指针person1与派生类Foreigner的一个对象相关联,并将调用该派生类的成员函数。
person1=newForeigner("
Dave"
再次介绍外宾:
9.指针person3与派生类Alien的一个对象相关联,调用该类的print()函数。
Person*person3;
person3=newAlien("
Vector"
介绍侨胞:
person3->
下面来看一下完整的程序:
//voidprint()
编译通过后,运行程序结果如图5.2所示:
图5.2:
第二阶段——练习(60分钟)
习题:
虚析构函数
析构函数的作用是在对象撤消之前做必要的“清理现场”的工作。
当派生类的对象从内存中撤消时一般先调用派生类的析构函数,然后再调用基类的析构函数。
但是,如果用new运算符建立了一个临时对象,若基类中有析构函数,并且定义了一个指同该基类的指针变量。
在程序用带指针参数的delete运算符撤销对象时,会发生一个情况:
系统会只执行基类的析构函数,而不执行派生类的析构函数。
解决上述问题的方法就是把基类的析构函数声明为虚析构函数:
让我们来看下列代码:
iostream>
usingnamespacestd;
classPoint//定义基类Point类
Point(){}//Point类构造函数
~Point(){cout<
executingPointdestructor"
}//Point类析构函数
classCircle:
publicPoint//定义派生类Circle类
Circle(){}//Circle类构造函数
~Circle(){cout<
executingCircledestructor"
}//Circle类析构函数
intradius;
intmain()
Point*P=newCircle;
//用new开辟Circle类对象的动态存储空间
deleteP;
//用delete释放动态存储空间
return0;
请按下列要求修改以上代码:
a.把构造函数修改为带参数的函数,在建立对象时初始化。
运行程序,分析结果。
b.将析构函数声明为virtual,运行程序,分析结果。
第三阶段——作业
作业一
写一个程序,定义抽象基类Shape,由它派生出3个派生类:
Circle(圆形)、Rectangle(矩形)、Triangle(三角形),用一个函数printArea分别输出以上三者的面积,3个图形的数据在定义对象时给定。
作业二
Circle(圆形)、Rectangle(矩形)、Triangle(三角形)。
用虚函数分别计算几种图形面积,并求它们的和。
要求用基类指针数组,使它的每一个元素指向一个派生类对象。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 多态性 函数 实验 手册
