实验5(2) 类的继承与派生
参考答案
一、实验目的与实验要求
(1)掌握单继承和多重继承下派生类的定义方法,理解基类成员在不同的继承方式下不同的访问属性。
(2)正确定义派生类的构造函数与析构函数,理解定义一个派生类对象时构造函数、析构函数的调用次序。
(3)理解同名冲突的产生原因,会使用虚基类来解决第三类同名冲突问题,并理解引入虚基类后构造函数、析构函数的调用顺序。 (4)理解赋值兼容的相关使用方法。
二、实验内容
题目1:定义一个车基类,派生出自行车类和汽车类,并以自行车类和汽车类为基类共同派生出摩托车类,每个类都要定义带有参数的构造函数。自行车类分别使用private、protected、public三种方式来继承车基类,观察基类成员在派生类中的访问属性;观察自行车类、汽车类和摩托车类对象定义时构造、析构函数的调用顺序。最后将车基类定义为虚基类再观察程序运行结果。题目的具体要求如下。
① 定义基类Vehicle,它具有两个保护成员变量:MaxSpeed、Weight,有3个公有的成员函数:Run( )、Stop( )、Show( ),以及带参数的构造函数、析构函数;再定义一个从Vehicle公有继承的Bicycle类,增加保护属性的成员变量Height,定义Bicycle类的构造函数、析构函数,改造Show函数,用于输出本类中的完整信息。main( )函数中定义Bicycle类对象,观察构造函数和析构函数的执行顺序,以及各成员函数的调用。使用跟踪的方法观察程序运行的每一步究竟调用的是哪一个函数。
② 在上一步基础上,将继承方式分别修改为protected和private,再重新编译,观察这时的报错信息并进行分析。
③ 将Bicycle类的继承方式恢复为public,代码回到 ① 的状态,再在Bicycle类下面增加一个第二层汽车类Car的定义,Car也是公有继承基类Vehicle,其中增加了一个保护成员变量SeatNum,表示汽车有几个座位,其定义方式与类Bicycle类似。主函数中定义该类对象,观察运行结果。
④ 在上一步的基础上,再定义一个第三层类MotorCycle,该类以公有方式继承了第二层的Bicycle和Car类。定义其构造函数,要调用两个直接基类的构造函数,再改造函数Show( ),输出所有四个成员变量的信息。主函数中只定义类MotorCycle的对象并调用相应的函数,代码请参考实验指导1的④。程序进行编译,会产生4个错误、8个警告,因为存在二义性问题,在同名成员前增加“基类名::”以消除二义性直到程序正确,观察运行结果。
⑤ 再将代码恢复至上一步未修改前,即存在4个错误、8个警告的状态,再作一定的修改,将Vehicle声明为虚基类以消除二义性,同时修改第三层类的构造函数,其余代码不变,具体请参考实验指导1的⑤。观察运行结果,理解此时构造函数、析构函数的调用顺序及用虚基类消除二义性的原理。
参考程序如下:
#include
class Vehicle //定义基类 {
protected: int MaxSpeed; //最大速度 int Weight; //重量 public: Vehicle(int m, int w) //初始化成员变量的值 {
MaxSpeed=m; Weight=w; cout << \ } ~Vehicle( ) { cout << \ } void Run( ) { cout << \ } void Stop( ) { cout << \ } void Show( ) { cout << \ cout << \ } };
class Bicycle: public Vehicle //定义派生类,公有继承 {
protected: int Height; //高度,单位:厘米 public: Bicycle(int m, int w, int h):Vehicle(m,w) //调用基类构造函数 { Height=h; //为本类中新增成员提供初始值 cout << \ } ~Bicycle( )
{ cout << \ } void Show( ) //改造基类的Show函数 { Vehicle::Show();//调用基类Show输出MaxSpeed和Weight值 cout<<\ //输出本类高度 } };
int main( ) { Bicycle b(120,2,4); //定义派生类对象 b.Run ( ); //观察构造、析构函数调用顺序 b.Stop( ); b.Show ( ); return 0; }
运行结果:
Constructing Vehicle... Constructing Bicycle... The vehicle is running! Please stop running! It's maxspeed is:120 It's weight is:2 It's Height is:4
Destructing Bycycle... Destructing Vehicle... Press any key to continue
② 在上一步基础上,将继承方式分别修改为protected和private,再重新编译,观察这时的报错信息并进行分析。
答:继承方式是private或protected后,main函数中的语句:b.Run ( ); b.Stop( );等均不能通过编译,因为基类中的成员函数都是派生类的私有的或保护的成员函数,类外用派生类对象都不能再调用。
③ 将Bicycle类的继承方式恢复为public,代码回到 ① 的状态,再在Bicycle类下面增加一个第二层汽车类Car的定义,Car也是公有继承基类Vehicle,其中增加了一个保护成员变量SeatNum,表示汽车有几个座位,其定义方式与类Bicycle类似。主函数中定义该类对象,观察运行结果。
指导: 在Bicycle类下面增加Car类的定义,参考以下代码,划线部分自己完成。
class Car: public Vehicle { public:
int SeatNum; {
//座位数
//调用基类构造函数
Car (int m, int w, int s) : (8)
//定义派生类Car,公有继承
}; } ~Car( ) { }
void Show( ) { } (10) (11) //调用基类Show输出MaxSpeed和Weight值 //输出本类座位数
//改造基类的Show函数
cout << \ (9) cout << \
//为本类中新增成员提供初始值
在主函数增加Car类对象的定义并调用相应函数,主函数代码如下。
int main( ) { }
参考程序如下:
Bicycle (12) b.Run( ); b.Stop( ); b.Show ( );
Car (13) c.Run ( ); c.Stop( ); c.Show ( ); return 0;
//定义汽车类对象
//定义自行车类对象
class Car: public Vehicle //定义派生类Car,公有继承
{
protected: int SeatNum; //座位数 public: Car (int m, int w, int s) : Vehicle(m,w) //调用基类构造函数 { SeatNum=s; //为本类中新增成员提供初始值 cout << \ } ~Car( ) { cout << \ } void Show( ) //改造基类的Show函数 { Vehicle::Show(); //调用基类Show输出MaxSpeed和Weight值 cout<<\ //输出本类座位数
} };
int main( ) { Bicycle b(50,2,400); //定义自行车类对象 b.Run( ); b.Stop( ); b.Show ( ); Car c(120,2000,5); //定义汽车类对象 c.Run ( ); c.Stop( ); c.Show ( ); return 0; }
运行结果为:
Constructing Vehicle... Constructing Bicycle... The vehicle is running! Please stop running! It's maxspeed is:50 It's weight is:2 It's Height is:400
Constructing Vehicle... Constructing Car... The vehicle is running! Please stop running! It's maxspeed is:120 It's weight is:2000 It's SeatNum is:5 Destructing Car... Destructing Vehicle... Destructing Bycycle... Destructing Vehicle... Press any key to continue
④ 在上一步的基础上,再定义一个第三层类MotorCycle,该类以公有方式继承了第二层的Bicycle和Car类。定义其构造函数,要调用两个直接基类的构造函数,再改造函数Show( ),输出所有四个成员变量的信息。主函数中只定义类MotorCycle的对象并调用相应的函数,代码请参考实验指导1的④。程序进行编译,会产生4个错误、8个警告,因为存在二义性问题,在同名成员前增加“基类名::”以消除二义性直到程序正确,观察运行结果。
指导:增加的第3层类MotorCycle及修改以后的main( )函数。
class MotorCycle: public Bicycle, public Car { public:
MotorCycle(int m, int w, int h, int s): (14) //调用两基类构造函数
//第3层类,从第2层两个类公有继承