实 验 报 告 | |||
实验名称 | 继承与派生实验 | ||
实验类型 | 验证 | 实验学时 | 2 |
(1)掌握单继承和多重继承下派生类的定义方法,理解基类成员在不同的继承方式下不同的访问属性。 (2)正确定义派生类的构造函数与析构函数,理解定义一个派生类对象时各个构造函数、析构函数被调用的顺序。 (3)正确定义虚基类,消除在多层次多重继承方式下顶层基类中成员访问的二义性问题,关注此时各构造函数、析构函数的调用顺序。 (4)通过基类与公有派生类的定义,及基类对象、指针、引用与派生类的对象、地址间相互赋值的方法,正确理解赋值兼容的4种情况,通过程序理解其不可逆性。 | |||
二、实验环境(实验设备) 硬件: 微型计算机 软件: Windows 操作系统、Microsoft Visual Studio 2010 | |||
三、实验原理及内容 (中文五号宋体,英文五号Consolas字体,单倍行距) 实验题目1: 定义一个车基类,派生出自行车类和汽车类,又以自行车类和汽车类为基类共同派生出摩托车类,每个类都要定义带有参数的构造函数。对自行车类继承车基类的方式分别用private、protected、public,观察基类成员在派生类中的访问属性;观察自行车类、汽车类和摩托车类对象定义时构造、析构函数的调用顺序。最后将车基类定义为虚基类再观察程序运行结果。 实验解答:
( 1 ) MaxSpeed=m; ( 2 ) Weight=w; ( 3 ) Vehicle(m,w) ( 4 ) Height=h; ( 5 ) Vehicle::Show(); ( 6 ) cout<<"Height="<<Height<<endl; ( 7 ) b(100,5,10); 此时程序的运行结果是: Constructing Vehicle... Constructing Bicycle... The vehicle is running! Please stop running! It's maxspeed is:100 It's weight is:5 Height=10 Destructing Bicycle... Destructing Vehicle...
将继承方式改为private或protected后,main函数中的b.Run()和b.Stop()都不能通过编译,因为基类中的成员函数都是派生类的私有或者保护的成员函数,类外的派生类对象都不能再调用
( 8 ) Vehicle(m,w) ( 9 ) SeatNum=s; ( 10 ) Vehicle::Show(); ( 11 ) cout<<"It\'s seatnum is :"<<SeatNum<<endl; ( 12 ) b(100,5,10); ( 13 ) c(400,800,4);
( 14 ) Bicycle(m,w,h),Car(m,w,s) ( 15 ) m(200,200,1.2,2); ⑤ 将Vehicle声明为虚基类以消除二义性,具体要在上面的基础上修改3个地方。 · 将class Bicycle: public Vehicle 修改为 class Bicycle: virtual public Vehicle。 · 将class Car: public Vehicle 修改为 class Car: virtual public Vehicle。 · 在第3层类的构造函数MotorCycle(int m,int w,int h,int s): (16) 的初始化列表中增加对虚基类构造函数的调用。 ( 16 ) Vehicle(m,w),Bicycle(m,w,h),Car(m,w,s) 实验题目2:定义Base类及它的公有派生类Derived类,两个类中均定义带参数的构造函数,基类中定义函数Show( ),派生类中也定义一个同名的Show( ),二者输出内容有所区别。主函数中定义基类的对象、指针、引用,也定义派生类的对象。 ① 对赋值兼容的4种情况作测试,对每行的输出结果进行观察,理解赋值兼容何时调用基类的成员函数,什么情况下才会调用派生类的成员函数。 ② 在主函数的return 0;语句前增加4条语句,观察并记下编译时的报错信息,理解赋值兼容的不可逆性。 实验解答:
(1 ) b1(11); (2 ) d1(22,33); (3 ) d1=b1; (4 ) &b2=d1; (5 ) *b3=&d1; (6 ) new Derived(10); 程序的运行结果是: 基类对象 b1.show(): i in Base is: 11 基类 b1=d1,b1.show(): i in Base is: 22 派生类对象 d1.show(): i in Derived is: 22 引用 b2=d1,b2.show(): i in Base is: 22 基类指针 b3=&d1,b3->show(): i in Base is: 22 基类指针 b4=d4,b4->show(): i in Base is: 10 派生类指针 d4,d4->show(): i in Derived is: 10
Derived d5=b1; Derived &d6=b1; Derived *d7=&b1; d7=b3; 观察并记下编译时的报错信息,理解赋值兼容的不可逆性。 [Error] conversion from 'Base' to non-scalar type 'Derived' requested [Error] invalid initialization of reference of type 'Derived&' from expression of type 'Base' [Error] invalid conversion from 'Base*' to 'Derived*' [-fpermissive] [Error] invalid conversion from 'Base*' to 'Derived*' [-fpermissive] 四、实验小结(包括问题和解决方法、心得体会、意见与建议等) (中文五号宋体,英文五号Times new roman字体,1.25倍行距) (一)实验中遇到的主要问题及解决方法 1.在题目(1)中将Bicycle继承Vehicle类的方式分别修改为protected和private,再重新编译,请在小结中记录报错信息,解释原因。记录采取何种修改方式使程序正确运行? Vehicle::Run()不可访问,因为“Bicycle”使用“private”是从“Vehicle”继承的 Vehicle::Stop()不可访问,因为“Bicycle”的“private”是从“Vehicle”继承的 Vehicle::Stop()不可访问,因为“Bicycle”的“protected”是从“Vehicle”继承的 使用public方式可以使程序运行 2. 在题目(2)中观察运行结果,总结在有赋值兼容的情况下,何时调用基类的成员函数,何时才会调用派生类的成员函数。 对基类对象进行赋值时,调用的是基类的成员函数 对基类的对象应用和基类的对象指针进行赋值时,调用的是派生类的成员函数 3.其它问题及解决方法: (二)实验心得 要多练 (三)意见与建议(没有可省略) 多敲代码 |
10-29
7731
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)