一、实验目的 虚函数是重载的另外一种形式,它是一种动态的重载方式,提供了一种更为灵活的多态性机制,它在运行时才决定如何动作。 对于基类和派生类中的函数重载,通过指针引起的普通成员函数调用,仅仅与指针的类型有关,而与此刻正指向什么对象无关(如:指向基类对象的指针,当其指向派生类对象时,只能利用它来直接访问派生类中从基类继承来的成员,不能直接访问公有派生类中自己特定的成员)。在这种情况下,必须采用显示的方式调用派生类中的函数成员。 要实现使用对象指针时,能使指针指向不同对象时能执行不同的操作的功能,就需要定义虚函数来实现。 虚函数是引入了派生类概念之后,用来表现基类和派生类的成员函数的关系的函数。虚函数定义在基类中进行,在基类中需要定义为虚函数的成员函数前加关键字virtual,从而提供了一个接口界面,在基类中的某个成员被声明为虚函数后,此虚函数就可在一个或多个派生类中被重新定义。在重新定义时,其函数原型、包括返回类型、函数名、参数个数及参数类型的顺序,都必须与基类中的原型完全一致。
二、实验内容
使用 Visual C++ 6.0 建立一个类A,A中定义一个虚函数,然后派生出两个类B和C。
三、实验要求
1、分别以public和private的方式派生出两个类B、C;
2、在基类A中添加一个虚函数和一个非虚函数,分别在派生类中对该虚函数进行重载;函数和非虚函数实现的功能要求由参加实验的同学自己决定; 3、设计主程序,要求其能够分别用一般对象和指针对象实现各类中虚函数的调用和非虚函数的对应调用;
4、对运行的结果进行分析并做出注释,对不能运行的代码注释并做出相应的原因分析。
实验代码:
//shuiguo.h
#ifndef SHUIGUO_H_
#define SHUIGUO_H_
class shuiguo//基类,水果
{
private:
int sum;//总数
int kind;//种类数量
public:
shuiguo():sum(0),kind(0){}
shuiguo(int s, int k) :sum(s), kind(k){}
virtual void display();
void change(int,int);
};
class banana:public shuiguo//香蕉,具有has-a关系的公有继承
{
private:
float cal;//卡路里
public:
banana() :shuiguo(), cal(0.0){}
banana(int s, int k, float c) :shuiguo(s, k), cal(c){}
virtual void display();
};
class maochong :private shuiguo//毛毛虫,具有is-a关系的私有继承
{
private:
int number;//毛虫数量
public:
maochong() :shuiguo(), number(0){}
maochong(int s, int k, int n) :shuiguo(s, k), number(n){}
virtual void display();
};
#endif
//shuiguo.cpp
#include<iostream>
#include"shuiguo.h"
using namespace std;
void shuiguo::display()
{
cout << "总数: " << sum << " " << "种类: " << kind << endl;
}
void shuiguo::change(int a,int b)
{
sum = a;
kind = b;
}
void banana::display()
{
shuiguo::display();
cout << "卡路里: " << cal << endl;
}
void maochong::display()
{
shuiguo::display();
cout << "总数; " << number << endl;
}
//user.cpp
#include"shuiguo.h"
#include<iostream>
using namespace std;
int main()
{
//一般对象实现
shuiguo a;
a.display();
a.change(100,10);
a.display();
shuiguo b(200, 20);
b.display();
banana c;
c.display();
c.change(100, 10);
c.display();
banana d(200, 20, 3);
d.display();
maochong e;
e.display();
maochong f(100, 10, 100);
f.display();
//指针对象实现(简化版)
shuiguo *g;
g= new shuiguo[1];
g[0]=shuiguo(100,10);
g[0].display();
banana *l;
l = new banana[1];
l[0] = banana(200, 20, 3);
l[0].display();
maochong *k;
k = new maochong[1];
k[0] = maochong(100, 10, 100);
k[0].display();
return 0;
}
思考题1:考虑虚函数在什么情况下调用不具有虚函数的特点?
答:派生类中的虚函数与基类虚函数的函数原型不同时.
思考题2:纯虚函数跟虚函数相比,有什么区别?有纯虚函数的类跟有虚函数的类相比,又有什么区别?
答:纯虚函数在构造函数中没有定义,定义又派生类去完成;类中拥有纯虚函数表示这个类是抽象类,不存在此类的对象。而虚函数仅表示派生类可以定义自己的版本,但是基类也可以有意义,若没有定义自己的版本,将使用基类的版本。