实验52 参考答案_第1页
实验52 参考答案_第2页
实验52 参考答案_第3页
实验52 参考答案_第4页
实验52 参考答案_第5页
已阅读5页,还剩27页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

试验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<iostream>usingnamespacestd;classVehicle //定义基类{protected: intMaxSpeed; //最大速度 intWeight; //重量public: Vehicle(intm,intw)//初始化组员变量的值 {MaxSpeed=m;Weight=w; cout<<"ConstructingVehicle...\n"; } ~Vehicle() { cout<<"DestructingVehicle...\n"; } voidRun() { cout<<"Thevehicleisrunning!\n"; } voidStop() { cout<<"Pleasestoprunning!\n"; } voidShow() { cout<<"It\'smaxspeedis:"<<MaxSpeed<<endl; cout<<"It\'sweightis:"<<Weight<<endl; }};classBicycle:publicVehicle //定义派生类,公有继承{protected: intHeight; //高度,单位:厘米public: Bicycle(intm,intw,inth):Vehicle(m,w) //调用基类构造函数 { Height=h; //为本类中新增组员提供初始值 cout<<"ConstructingBicycle...\n"; } ~Bicycle() { cout<<"DestructingBycycle...\n"; } voidShow() //改造基类的Show函数 { Vehicle::Show();//调用基类Show输出MaxSpeed和Weight值 cout<<"It\'sHeightis:"<<Height<<endl; //输出本类高度 }};intmain(){ Bicycleb(120,2,4); //定义派生类对象 b.Run(); //观测构造、析构函数调用次序 b.Stop(); b.Show(); return0;}运行成果:ConstructingVehicle...ConstructingBicycle...Thevehicleisrunning!Pleasestoprunning!It'smaxspeedis:120It'sweightis:2It'sHeightis:4DestructingBycycle...DestructingVehicle...Pressanykeytocontinue②在上一步基础上,将继承方式分别修改为protected和private,再重新编译,观测这时的报错信息并进行分析。答:继承方式是private或protected后,main函数中的语句:b.Run();b.Stop();等均不能通过编译,由于基类中的组员函数都是派生类的私有的或保护的组员函数,类外用派生类对象都不能再调用。③将Bicycle类的继承方式恢复为public,代码回到①的状态,再在Bicycle类下面增长一种第二层汽车类Car的定义,Car也是公有继承基类Vehicle,其中增长了一种保护组员变量SeatNum,表达汽车有几种座位,其定义方式与类Bicycle类似。主函数中定义该类对象,观测运行成果。指导:在Bicycle类下面增长Car类的定义,参照如下代码,划线部分自己完毕。classCar:publicVehicle //定义派生类Car,公有继承{public: intSeatNum; //座位数 Car(intm,intw,ints):(8) //调用基类构造函数 { (9) //为本类中新增组员提供初始值 cout<<"ConstructingCar...\n"; } ~Car() { cout<<"DestructingCar...\n"; } voidShow() //改造基类的Show函数 { (10) //调用基类Show输出MaxSpeed和Weight值 (11) //输出本类座位数 }};在主函数增长Car类对象的定义并调用对应函数,主函数代码如下。intmain(){ Bicycle(12) //定义自行车类对象 b.Run(); b.Stop(); b.Show(); Car(13) //定义汽车类对象 c.Run(); c.Stop(); c.Show(); return0;}参照程序如下:classCar:publicVehicle //定义派生类Car,公有继承{protected: intSeatNum; //座位数public: Car(intm,intw,ints):Vehicle(m,w) //调用基类构造函数 { SeatNum=s; //为本类中新增组员提供初始值 cout<<"ConstructingCar...\n"; } ~Car() { cout<<"DestructingCar...\n"; } voidShow() //改造基类的Show函数 { Vehicle::Show(); //调用基类Show输出MaxSpeed和Weight值 cout<<"It\'sSeatNumis:"<<SeatNum<<endl; //输出本类座位数 }};intmain(){ Bicycleb(50,2,400); //定义自行车类对象 b.Run(); b.Stop(); b.Show(); Carc(120,,5); //定义汽车类对象 c.Run(); c.Stop(); c.Show(); return0;}运行成果为:ConstructingVehicle...ConstructingBicycle...Thevehicleisrunning!Pleasestoprunning!It'smaxspeedis:50It'sweightis:2It'sHeightis:400ConstructingVehicle...ConstructingCar...Thevehicleisrunning!Pleasestoprunning!It'smaxspeedis:120It'sweightis:It'sSeatNumis:5DestructingCar...DestructingVehicle...DestructingBycycle...DestructingVehicle...Pressanykeytocontinue④在上一步的基础上,再定义一种第三层类MotorCycle,该类以公有方式继承了第二层的Bicycle和Car类。定义其构造函数,要调用两个直接基类的构造函数,再改造函数Show(),输出所有四个组员变量的信息。主函数中只定义类MotorCycle的对象并调用对应的函数,代码请参照试验指导1的④。程序进行编译,会产生4个错误、8个警告,由于存在二义性问题,在同名组员前增长“基类名::”以消除二义性直到程序对的,观测运行成果。指导:增长的第3层类MotorCycle及修改后来的main()函数。classMotorCycle:publicBicycle,publicCar //第3层类,从第2层两个类公有继承{public: MotorCycle(intm,intw,inth,ints):(14) //调用两基类构造函数 { cout<<"ConstructingMotorCycle...\n"; } ~MotorCycle() { cout<<"DestructingMotorCycle...\n"; } voidShow() //输出4个组员变量的信息,需消除二义性 { cout<<"It\'smaxspeedis:"<<MaxSpeed<<endl;//错误 cout<<"It\'sweightis:"<<Weight<<endl; //错误 cout<<"It\'sheightis:"<<Height<<endl; cout<<"It\'sseatnumis:"<<SeatNum<<endl; }};intmain(){ MotorCycle(15) //定义摩托车类对象 mc.Run(); //错误 mc.Stop(); //错误 mc.Show(); return0;}程序为:classMotorCycle:publicBicycle,publicCar//第3层类,从第2层两个类公有继承{public: MotorCycle(intm,intw,inth,ints):Bicycle(m,w,h),Car(m,w,s)//调用两基类构造函数 { cout<<"ConstructingMotorCycle...\n"; } ~MotorCycle() { cout<<"DestructingMotorCycle...\n"; } voidShow()//输出4个组员变量的信息,需消除二义性 { cout<<"It\'smaxspeedis:"<<MaxSpeed<<endl;//错误 cout<<"It\'sweightis:"<<Weight<<endl; //错误 cout<<"It\'sheightis:"<<Height<<endl; cout<<"It\'sseatnumis:"<<SeatNum<<endl; }};intmain(){ MotorCyclemc(120,1000,2,2); //定义摩托车类对象 mc.Run(); //错误 mc.Stop(); //错误 mc.Show(); return0;}编译出错:E:\-(2)\C++教学\教案\Text1.cpp(113):errorC2385:'MotorCycle::MaxSpeed'isambiguousE:\-(2)\C++教学\教案\Text1.cpp(113):warningC4385:couldbethe'MaxSpeed'inbase'Vehicle'ofbase'Bicycle'ofclass'MotorCycle'E:\-(2)\C++教学\教案\Text1.cpp(113):warningC4385:orthe'MaxSpeed'inbase'Vehicle'ofbase'Car'ofclass'MotorCycle'E:\-(2)\C++教学\教案\Text1.cpp(114):errorC2385:'MotorCycle::Weight'isambiguousE:\-(2)\C++教学\教案\Text1.cpp(114):warningC4385:couldbethe'Weight'inbase'Vehicle'ofbase'Bicycle'ofclass'MotorCycle'E:\-(2)\C++教学\教案\Text1.cpp(114):warningC4385:orthe'Weight'inbase'Vehicle'ofbase'Car'ofclass'MotorCycle'E:\-(2)\C++教学\教案\Text1.cpp(125):errorC2385:'MotorCycle::Run'isambiguousE:\-(2)\C++教学\教案\Text1.cpp(125):warningC4385:couldbethe'Run'inbase'Vehicle'ofbase'Bicycle'ofclass'MotorCycle'E:\-(2)\C++教学\教案\Text1.cpp(125):warningC4385:orthe'Run'inbase'Vehicle'ofbase'Car'ofclass'MotorCycle'E:\-(2)\C++教学\教案\Text1.cpp(126):errorC2385:'MotorCycle::Stop'isambiguousE:\-(2)\C++教学\教案\Text1.cpp(126):warningC4385:couldbethe'Stop'inbase'Vehicle'ofbase'Bicycle'ofclass'MotorCycle'E:\-(2)\C++教学\教案\Text1.cpp(126):warningC4385:orthe'Stop'inbase'Vehicle'ofbase'Car'ofclass'MotorCycle'执行cl.exe时出错.即输出MaxSpeed、Weigh和调用函数Run()和Stop()函数时出现二义性问题。修改程序中重要是为数据组员和组员函数限定其所属类即可。程序为:classMotorCycle:publicBicycle,publicCar//第3层类,从第2层两个类公有继承{public: MotorCycle(intm,intw,inth,ints):Bicycle(m,w,h),Car(m,w,s)//调用两基类构造函数 { cout<<"ConstructingMotorCycle...\n"; } ~MotorCycle() { cout<<"DestructingMotorCycle...\n"; } voidShow()//输出4个组员变量的信息,需消除二义性 { cout<<"It\'smaxspeedis:"<<Bicycle::MaxSpeed<<endl;//修改后 cout<<"It\'sweightis:"<<Car::Weight<<endl; //修改后 cout<<"It\'sheightis:"<<Height<<endl; cout<<"It\'sseatnumis:"<<SeatNum<<endl; }};intmain(){ MotorCyclemc(120,1000,2,2); //定义摩托车类对象 mc.Bicycle::Run(); //修改后 mc.Bicycle::Stop(); //修改后 mc.Show(); return0;}运行成果:ConstructingVehicle...ConstructingBicycle...ConstructingVehicle...ConstructingCar...ConstructingMotorCycle...Thevehicleisrunning!Pleasestoprunning!It'smaxspeedis:120It'sweightis:1000It'sheightis:2It'sseatnumis:2DestructingMotorCycle...DestructingCar...DestructingVehicle...DestructingBycycle...DestructingVehicle...Pressanykeytocontinue⑤再将代码恢复至上一步未修改前,即存在4个错误、8个警告的状态,再作一定的修改,将Vehicle申明为虚基类以消除二义性,同步修改第三层类的构造函数,其他代码不变,详细请参照试验指导1的⑤。观测运行成果,理解此时构造函数、析构函数的调用次序及用虚基类消除二义性的原理。指导:将Vehicle申明为虚基类以消除二义性,详细要在上面的基础上修改如下地方。将classBicycle:publicVehicle修改为classBicycle:virtualpublicVehicle。将classCar:publicVehicle修改为classCar:virtualpublicVehicle。在第3层类的构造函数MotorCycle(intm,intw,inth,ints):(16)的初始化列表中增长对虚基类构造函数的调用。本来注释出错的地方将类名的限制去掉,恢复原样。如: cout<<"It\'smaxspeedis:"<<Bicycle::MaxSpeed<<endl;//错误恢复为:cout<<"It\'smaxspeedis:"<<MaxSpeed<<endl;按题意,将Vehicle申明为虚基类以消除二义性,详细修改;将classBicycle:publicVehicle修改为classBicycle:virtualpublicVehicle。将classCar:publicVehicle修改为classCar:virtualpublicVehicle。程序修改为:classMotorCycle:publicBicycle,publicCar//第3层类,从第2层两个类公有继承{public: MotorCycle(intm,intw,inth,ints):Vehicle(m,w),Bicycle(m,w,h),Car(m,w,s)//调用两基类构造函数 { cout<<"ConstructingMotorCycle...\n"; } ~MotorCycle() { cout<<"DestructingMotorCycle...\n"; } voidShow()//输出4个组员变量的信息,需消除二义性 { cout<<"It\'smaxspeedis:"<<MaxSpeed<<endl;//对的 cout<<"It\'sweightis:"<<Weight<<endl; //对的 cout<<"It\'sheightis:"<<Height<<endl; cout<<"It\'sseatnumis:"<<SeatNum<<endl; }};intmain(){ MotorCyclemc(120,1000,2,2); //定义摩托车类对象 mc.Run(); //对的 mc.Stop();//对的 mc.Show(); return0;}运行成果为:ConstructingVehicle...ConstructingBicycle...ConstructingCar...ConstructingMotorCycle...Thevehicleisrunning!Pleasestoprunning!It'smaxspeedis:120It'sweightis:1000It'sheightis:2It'sseatnumis:2DestructingMotorCycle...DestructingCar...DestructingBycycle...DestructingVehicle...Pressanykeytocontinue题目2:定义Base类及它的公有派生类Derived类,两个类中均定义带参数的构造函数,基类中定义函数Show(),派生类中也定义一种同名的Show(),两者输出内容有所区别。主函数中定义基类的对象、指针、引用,也定义派生类的对象。(①中6个空各0.3分,②分析0.2分)①对赋值兼容的4种状况作测试,对每行的输出成果进行观测,理解赋值兼容何时调用基类的组员函数,什么状况下才会调用派生类的组员函数。②在主函数的return0;语句前增长4条语句,观测并记下编译时的报错信息,理解赋值兼容的不可逆性。程序如下:#include<iostream>usingnamespacestd;classBase{ public: inti; Base(intx):i(x) { } voidshow() { cout<<"iinBaseis:"<<i<<endl; }};classDerived:publicBase{public: Derived(intx):Base(x) {} voidshow() { cout<<"iinDerivedis:"<<i<<endl; }};intmain(){ Baseb1(1); //定义基类对象b1 cout<<"基类对象b1.show():\n"; b1.show(); Derivedd1(2); //定义派生类对象d1 b1=d1; //用派生类对象给基类对象赋值 cout<<"基类b1=d1,b1.show():\n"; b1.show(); cout<<"派生类对象d1.show():\n"; d1.show(); Base&b2=d1; //用派生类对象来初始化基类引用 cout<<"引用b2=d1,b2.show():\n"; b2.show(); Base*b3=&d1; //派生类对象的地址赋给指向基类的指针 cout<<"基类指针b3=&d1,b3->show():\n"; b3->show(); Derived*d4=newDerived(3); //定义派生类指针并生成新对象 Base*b4=d4; //派生类指针赋给指向基类的指针 cout<<"基类指针b4=d4,b4->show():\n"; b4->show(); cout<<"派生类指针d4,d4->show():\n"; d4->show(); deleted4; return0;}运行成果:基类对象b1.show():iinBaseis:1基类b1=d1,b1.show():iinBaseis:2派生类对象d1.show():iinDerivedis:2引用b2=d1,b2.show():iinBaseis:2基类指针b3=&d1,b3->show():iinBaseis:2基类指针b4=d4,b4->show():iinBaseis:3派生类指针d4,d4->show():iinDerivedis:3Pressanykeytocontinue对赋值兼容的4种状况作测试,对每行的输出成果进行观测,理解赋值兼容何时调用基类的组员函数,什么状况下才会调用派生类的组员函数。答:4种状况:基类对象=公有派生类对象b1=d1;b1.show();调用的是基类Base的组员函数show;指向基类对象的指针=公有派生类对象的地址Base*b3=&d1; b3->show();调用的是基类Base的组员函数show;指向基类对象的指针=指向公有派生类对象的指针Base*b4=d4;b4->show();调用的是基类Base的组员函数show;基类的引用=公有派生类对象,即派生类对象可以初始化基类的引用。Base&b2=d1;b2.show();调用的是基类Base的组员函数show;由此可知,只要是基类的对象或对象指针(引用)均调用的是基类的函数;只有在调用函数的对象或指针是派生类的时候才会调用派生类的组员函数。如d1.show();d4->show();均调用的是派生类的组员函数。在主函数的return0

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论