当前位置:首页 >> 数学 >>

实验5(2) 参考答案


实验 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> using namespace std; class Vehicle //定义基类 { protected: int MaxSpeed; //最大速度 int Weight; //重量 public: Vehicle(int m, int w) //初始化成员变量的值 { MaxSpeed=m; Weight=w; cout << "Constructing Vehicle...\n"; } ~Vehicle( ) { cout << "Destructing Vehicle...\n"; } void Run( ) { cout << "The vehicle is running!\n"; } void Stop( ) { cout << "Please stop running!\n"; } void Show( ) { cout << "It\'s maxspeed is:" << MaxSpeed << endl; cout << "It\'s weight is:" << Weight << endl; } }; class Bicycle: public Vehicle //定义派生类,公有继承 { protected: int Height; //高度,单位:厘米 public: Bicycle(int m, int w, int h):Vehicle(m,w) //调用基类构造函数 { Height=h; //为本类中新增成员提供初始值 cout << "Constructing Bicycle...\n"; } ~Bicycle( )

{ cout << "Destructing Bycycle...\n"; } void Show( ) //改造基类的 Show 函数 { Vehicle::Show();//调用基类 Show 输出 MaxSpeed 和 Weight 值 cout<<"It\'s Height is:"<<Height<<endl; //输出本类高度 } }; 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,公有继承

(9) cout << "Constructing Car...\n"; } ~Car( ) { cout << "Destructing Car...\n"; } void Show( ) { (10) (11) } };

//为本类中新增成员提供初始值

//改造基类的 Show 函数 //调用基类 Show 输出 MaxSpeed 和 Weight 值 //输出本类座位数

在主函数增加 Car 类对象的定义并调用相应函数,主函数代码如下。
int main( ) { Bicycle b.Run( ); b.Stop( ); b.Show ( ); Car c.Run ( ); c.Stop( ); c.Show ( ); return 0; } 参考程序如下: (13) //定义汽车类对象 (12) //定义自行车类对象

class Car: public Vehicle //定义派生类 Car,公有继承 { protected: int SeatNum; //座位数 public: Car (int m, int w, int s) : Vehicle(m,w) //调用基类构造函数 { SeatNum=s; //为本类中新增成员提供初始值 cout << "Constructing Car...\n"; } ~Car( ) { cout << "Destructing Car...\n"; } void Show( ) //改造基类的 Show 函数 { Vehicle::Show(); //调用基类 Show 输出 MaxSpeed 和 Weight 值 cout<<"It\'s SeatNum is:"<<SeatNum<<endl; //输出本类座位数

} }; 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 层两个类公有继承

{ cout << "Constructing MotorCycle...\n"; } ~MotorCycle( ) { cout << "Destructing MotorCycle...\n"; } void Show( ) { cout << "It\'s maxspeed is:" << MaxSpeed << endl; //错误 cout << "It\'s weight is:" << Weight << endl; cout << "It\'s height is:" << Height << endl; cout << "It\'s seatnum is:" << SeatNum << endl; } }; int main( ) { MotorCycle mc.Run ( ); mc.Stop( ); mc.Show ( ); return 0; } (15) //定义摩托车类对象 //错误 //错误 //错误 //输出 4 个成员变量的信息, 需消除二义性

程序为: class MotorCycle: public Bicycle, public Car //第 3 层类,从第 2 层两个类公有继承 { public: MotorCycle(int m, int w, int h, int s): Bicycle(m,w,h),Car(m,w,s) //调用两基类构造函数 { cout << "Constructing MotorCycle...\n"; } ~MotorCycle( ) { cout << "Destructing MotorCycle...\n"; } void Show( ) //输出 4 个成员变量的信息,需消除二义性 { cout << "It\'s maxspeed is:" << MaxSpeed << endl; //错误 cout << "It\'s weight is:" << Weight << endl; //错误 cout << "It\'s height is:" << Height << endl; cout << "It\'s seatnum is:" << SeatNum << endl; }

}; int main( ) { MotorCycle mc(120,1000,2,2); //定义摩托车类对象 mc.Run ( ); //错误 mc.Stop( ); //错误 mc.Show ( ); return 0; } 编译出错: E:\2012-2013(2)\C++教学\教案\Text1.cpp(113) : error C2385: 'MotorCycle::MaxSpeed' is ambiguous E:\2012-2013(2)\C++ 教 学 \ 教 案 \Text1.cpp(113) : warning C4385: could be the 'MaxSpeed' in base 'Vehicle' of base 'Bicycle' of class 'MotorCycle' E:\2012-2013(2)\C++教学\教案\Text1.cpp(113) : warning C4385: or the 'MaxSpeed' in base 'Vehicle' of base 'Car' of class 'MotorCycle' E:\2012-2013(2)\C++教学\教案\Text1.cpp(114) : error C2385: 'MotorCycle::Weight' is ambiguous E:\2012-2013(2)\C++教学\教案\Text1.cpp(114) : warning C4385: could be the 'Weight' in base 'Vehicle' of base 'Bicycle' of class 'MotorCycle' E:\2012-2013(2)\C++教学\教案\Text1.cpp(114) : warning C4385: or the 'Weight' in base 'Vehicle' of base 'Car' of class 'MotorCycle' E:\2012-2013(2)\C++教学\教案\Text1.cpp(125) : error C2385: 'MotorCycle::Run' is ambiguous E:\2012-2013(2)\C++教学\教案\Text1.cpp(125) : warning C4385: could be the 'Run' in base 'Vehicle' of base 'Bicycle' of class 'MotorCycle' E:\2012-2013(2)\C++教学\教案\Text1.cpp(125) : warning C4385: or the 'Run' in base 'Vehicle' of base 'Car' of class 'MotorCycle' E:\2012-2013(2)\C++教学\教案\Text1.cpp(126) : error C2385: 'MotorCycle::Stop' is ambiguous E:\2012-2013(2)\C++教学\教案\Text1.cpp(126) : warning C4385: could be the 'Stop' in base 'Vehicle' of base 'Bicycle' of class 'MotorCycle' E:\2012-2013(2)\C++教学\教案\Text1.cpp(126) : warning C4385: or the 'Stop' in base 'Vehicle' of base 'Car' of class 'MotorCycle' 执行 cl.exe 时出错. 即输出 MaxSpeed、Weigh 和调用函数 Run()和 Stop()函数时出现二义性问题。 修改程序中主要是为数据成员和成员函数限定其所属类即可。 程序为: class MotorCycle: public Bicycle, public Car //第 3 层类,从第 2 层两个类公有继承 { public: MotorCycle(int m, int w, int h, int s): Bicycle(m,w,h),Car(m,w,s) //调用两基类构造函数 {

cout << "Constructing MotorCycle...\n"; } ~MotorCycle( ) { cout << "Destructing MotorCycle...\n"; } void Show( ) //输出 4 个成员变量的信息,需消除二义性 { cout << "It\'s maxspeed is:" << Bicycle::MaxSpeed << endl; //修改后 cout << "It\'s weight is:" << Car::Weight << endl; //修改后 cout << "It\'s height is:" << Height << endl; cout << "It\'s seatnum is:" << SeatNum << endl; } }; int main( ) { MotorCycle mc(120,1000,2,2); //定义摩托车类对象 mc.Bicycle::Run ( ); //修改后 mc.Bicycle::Stop( ); //修改后 mc.Show ( ); return 0; } 运行结果: Constructing Vehicle... Constructing Bicycle... Constructing Vehicle... Constructing Car... Constructing MotorCycle... The vehicle is running! Please stop running! It's maxspeed is:120 It's weight is:1000 It's height is:2 It's seatnum is:2 Destructing MotorCycle... Destructing Car... Destructing Vehicle... Destructing Bycycle... Destructing Vehicle... Press any key to continue ⑤ 再将代码恢复至上一步未修改前,即存在 4 个错误、8 个警告的状态,再作一定的 修改,将 Vehicle 声明为虚基类以消除二义性,同时修改第三层类的构造函数,其余代码不 变,具体请参考实验指导 1 的⑤。观察运行结果,理解此时构造函数、析构函数的调用顺序 及用虚基类消除二义性的原理。

指导:将 Vehicle 声明为虚基类以消除二义性,具体要在上面的基础上修改以下地方。 ? 将 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) 的初始化列 表中增加对虚基类构造函数的调用。 ? 原来注释出错的地方将类名的限制去掉,恢复原样。如: cout << "It\'s maxspeed is:" << Bicycle::MaxSpeed << endl; //错误 恢复为:cout << "It\'s maxspeed is:" << MaxSpeed << endl; 按题意,将 Vehicle 声明为虚基类以消除二义性,具体修改; ? 将 class Bicycle: public Vehicle 修改为 class Bicycle: virtual public Vehicle。 ? 将 class Car: public Vehicle 修改为 class Car: virtual public Vehicle。 程序修改为: class MotorCycle: public Bicycle, public Car //第 3 层类,从第 2 层两个类公有继承 { public: MotorCycle(int m, int w, int h, int s): Vehicle(m,w),Bicycle(m,w,h),Car(m,w,s)// 调用两基类构造函数 { cout << "Constructing MotorCycle...\n"; } ~MotorCycle( ) { cout << "Destructing MotorCycle...\n"; } void Show( ) //输出 4 个成员变量的信息,需消除二义性 { cout << "It\'s maxspeed is:" << MaxSpeed << endl; //正确 cout << "It\'s weight is:" << Weight << endl; //正确 cout << "It\'s height is:" << Height << endl; cout << "It\'s seatnum is:" << SeatNum << endl; } }; int main( ) { MotorCycle mc(120,1000,2,2); //定义摩托车类对象 mc.Run ( ); //正确 mc.Stop( ); //正确 mc.Show ( ); return 0; } 运行结果为: Constructing Vehicle... Constructing Bicycle...

Constructing Car... Constructing MotorCycle... The vehicle is running! Please stop running! It's maxspeed is:120 It's weight is:1000 It's height is:2 It's seatnum is:2 Destructing MotorCycle... Destructing Car... Destructing Bycycle... Destructing Vehicle... Press any key to continue 题目 2: 定义 Base 类及它的公有派生类 Derived 类, 两个类中均定义带参数的构造函数, 基类中定义函数 Show( ),派生类中也定义一个同名的 Show( ),二者输出内容有所区别。主 函数中定义基类的对象、指针、引用,也定义派生类的对象。 (① 中 6 个空各 0.3 分,②分 析 0.2 分) ① 对赋值兼容的 4 种情况作测试,对每行的输出结果进行观察,理解赋值兼容何时调 用基类的成员函数,什么情况下才会调用派生类的成员函数。 ② 在主函数的 return 0;语句前增加 4 条语句,观察并记下编译时的报错信息,理解赋 值兼容的不可逆性。 程序如下: #include <iostream> using namespace std; class Base { public: int i; Base(int x): i(x) { } void show( ) { cout << "i in Base is: " << i << endl; } }; class Derived: public Base { public: Derived(int x): Base(x) { } void show( ) { cout << "i in Derived is: " << i << endl;

} }; int main( ) { Base b1(1); //定义基类对象 b1 cout << "基类对象 b1.show( ):\n"; b1.show( ); Derived d1(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=new Derived(3); //定义派生类指针并生成新对象 Base *b4 = d4 ; //派生类指针赋给指向基类的指针 cout << "基类指针 b4 = d4, b4->show( ):\n"; b4->show( ); cout << "派生类指针 d4, d4->show( ):\n"; d4->show( ); delete d4; return 0; } 运行结果: 基类对象 b1.show( ): i in Base is: 1 基类 b1=d1, b1.show( ): i in Base is: 2 派生类对象 d1.show( ): i in Derived is: 2 引用 b2=d1, b2.show( ): i in Base is: 2 基类指针 b3=&d1, b3->show( ): i in Base is: 2 基类指针 b4 = d4, b4->show( ): i in Base is: 3 派生类指针 d4, d4->show( ): i in Derived is: 3

Press any key to continue ① 对赋值兼容的 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( ); 均调用的是派生类的成员函数。 ② 在主函数的 return 0;语句前增加 4 条语句,观察并记下编译时的报错信息,理解赋 值兼容的不可逆性。 //增加 4 条语句,理解赋值兼容规则的不可逆性 Derived d5 = b1; 该语句编译不能通过,因为不能用基类对象对派生类对象初始化 Derived &d6 = b1; 该语句编译不能通过,因为派生类对象不能用来作为基类对象的别名 Derived *d7 = &b1; 该语句编译不能通过,因为派生类对象指针不能指向基类对象 d7 = b3; 该语句编译不能通过,因为派生类对象指针不能被赋值为基类对象指针 题目 2 指导: ① //赋值兼容原则
#include <iostream> using namespace std; class Base { public: int i; Base(int x): i(x) { }

void show( ) { cout << "i in Base is: " << i << endl; }

}; class Derived: public Base { public: Derived(int x): Base(x) { }

void show( ) { cout << "i in Derived is: " << i << endl; } };

int {

main( ) (1)

Base

//定义基类对象 b1

cout << "基类对象 b1.show( ):\n"; b1.show( ); Derived (3) cout << "基类 b1=d1, b1.show( ):\n"; b1.show( ); cout << "派生类对象 d1.show( ):\n"; d1.show( ); Base (4) //用派生类对象来初始化基类引用 (2) //定义派生类对象 d1 //用派生类对象给基类对象赋值

cout << "引用 b2=d1, b2.show( ):\n"; b2.show( ); Base (5) //派生类对象的地址赋给指向基类的指针

cout << "基类指针 b3=&d1, b3->show( ):\n"; b3->show( ); Derived *d4 = (6) //定义派生类指针并生成新对象 //派生类指针赋给指向基类的指针

Base *b4 = d4 ; cout << "基类指针 b4 = d4, b4->show( ):\n"; b4->show( );

cout << "派生类指针 d4, d4->show( ):\n"; d4->show( delete d4; return 0; } );

② //增加 4 条语句,理解赋值兼容规则的不可逆性
Derived d5 = b1; Derived &d6 = b1; Derived *d7 = &b1; d7 = b3;


相关文章:
实验二参考答案
实验二:参考答案 1、若有 a=3,b=4,c=5,x=1.2,y=2.4,z=-3.6,u=51274,n=128765,c1=’a’,c2=’b’。想得到以下的输出 格式和结果,请写出程序(包...
实验二 - 参考答案
实验二 - 参考答案_工学_高等教育_教育专区。上海电力学院 实验报告 课程名称 ...5 注:实验报告内容包括:实验目的与要求、实验原理与内容、实验步骤与记录、实验...
《C++程序设计1》实验5-2参考答案、程序
《C++程序设计1》实验5-2参考答案、程序_司法考试_资格考试/认证_教育专区。《C++程序设计 1》实验 5-2 参考程序与答案(1)填空题 1. 存储字符’a’和字符串...
答案_实验五 存储管理(二)
答案_实验五 存储管理(二) 隐藏>> 实验五 存储管理(二)学号: 实验目的: 1. 了解虚拟存储器。 2. 掌握分页存储管理的原理,熟悉段式存储和段页式存储管理。 3...
05实验五 符号计算实验(附答案)
05实验五 符号计算实验(附答案)_计算机软件及应用_IT/计算机_专业资料。实验五一、实验目的: 1、 掌握定义符号对象的方法 符号计算实验 2、掌握符号表达式的运算法...
2014级DS作业和实验参考答案(二)
2014级DS作业和实验参考答案(二)_计算机软件及应用_IT/计算机_专业资料。2014 ...Sample Input 1 8 18 7 cout<<A[i]<<" "; 1 3 5 10 17 19 25 ...
(大学计算机基础实验指导)模拟试题(二)参考答案
参考答案与评分标准 (大学计算机基础实验指导)模拟试题(二)参考答案(非计算机专业A卷) 一.填空题(共20分,每空1分) 1. 电子管 5. 实体 7. OSI/RM 10. ...
《土木工程实验》(二)答案
《土木工程实验(二)答案_从业资格考试_资格考试/认证_教育专区。姓 名: 报名...实验中每级荷载下记录的数据荷载 0 1 2 3 4 5 6 7 8 9 10 0 kN ...
C++程序设计实践教程(第二版)实验5答案
C++程序设计实践教程(第)实验5答案_工学_高等教育_教育专区。1. #include...喜欢此文档还喜欢 第三次实验报告 暂无评价 5页 1下载券 深圳大学实验报告...
大学物理实验理论考试题目及答案2
题库B-12 单项选择题(答案仅供参考) 1.两个直接测量值为 0.5136mm 和 10.0mm,它们的商是( C ) 最少为三个有效数字 2.在热敏电阻特性测量实验中,QJ23...
更多相关标签: