实验题目1:
定义一个车基类,派生出自行车类和汽车类,又以自行车类和汽车类为基类共同派生出摩托车类,每个类都要定义带有参数的构造函数。对自行车类继承车基类的方式分别用private、protected、public,观察基类成员在派生类中的访问属性;观察自行车类、汽车类和摩托车类对象定义时构造、析构函数的调用顺序。最后将车基类定义为虚基类再观察程序运行结果。
实验解答:
① 根据提示进行填写完整实验指导223页代码对应位置内容如下:
MaxSpeed = m;
Weight = w;
Vechicle(m, h)
Height = h;
Vechicle::Show();
cout << “It\’s height is:” << Height << endl;
b;
此时程序的运行结果是:
Constructing Vehicle
Constructing Bicycle
The vehicle is runni
Please stop running
It's maxspeed is: 1
It's weight is: 2
It's height is: 3
Destructing Bicycle
Destructing Vehicle
② 将继承方式改为private或protected,观察并分析程序的编译结果。
变成protected的之后
“Vehicle::Run”不可访问,因为“Bicycle”使用“protected”从“Vehicle”继承
“Vehicle::Stop”不可访问,因为“Bicycle”使用“protected”从“Vehicle”继承
变成private的之后
“Vehicle::Run”不可访问,因为“Bicycle”使用“private”从“Vehicle”继承
“Vehicle::Stop”不可访问,因为“Bicycle”使用“private”从“Vehicle”继承
③ 在Bicycle类下面增加Car类的定义,参考实验教材给出的代码,划线部分自己完成。
Vehicle(m, w)
SetNum = s;
Vehicle::Show();
cout << "It\'s SetNum is: " << SetNum << endl;
Bicycle b(1, 2, 3);
Car c(4, 5, 6);
④ 增加第3层类MotorCycle及修改以后的main( )函数,代码见实验教材。
Bicycle(m, w, h), Car(m, w, s)
mc(100,100,1,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): 的初始化列表中增加对虚基类构造函数的调用。
Vehicle(m, w),Bicycle(m, w, h),Car(m, w, s);
实验题目2:
定义Base类及它的公有派生类Derived类,两个类中均定义带参数的构造函数,基类中定义函数Show( ),派生类中也定义一个同名的Show( ),二者输出内容有所区别。主函数中定义基类的对象、指针、引用,也定义派生类的对象。
① 对赋值兼容的4种情况作测试,对每行的输出结果进行观察,理解赋值兼容何时调用基类的成员函数,什么情况下才会调用派生类的成员函数。
② 在主函数的return 0;语句前增加4条语句,观察并记下编译时的报错信息,理解赋值兼容的不可逆性。
实验解答:
① 按提示将程序填写完整,代码参见实验教材,对应位置内容是:
b1(11)
d1(21);
b1 = d1;
&b2 = d1;
* b3 = &d1;
new Derived(4);
程序的运行结果是:
基类对象 b1.show():
i in Base is: 11
基类 b1 = d1, b1.show():
i in Base is: 21
派生类对象 d1.show():
i in Derived is: 21
引用b2 = d1, b2.show():
i in Base is: 21
基类指针 b3 = &d1, b3->show():
i in Base is: 21
基类指针 b4 = d4, b4->show():
i in Base is: 4
派生类指针d4, d4->show():
i in Derived is: 4
② 在主函数的return 0;语句前增加4条语句:
Derived d5=b1;
Derived &d6=b1;
Derived *d7=&b1;
d7=b3;
观察并记下编译时的报错信息,理解赋值兼容的不可逆性。
“初始化”: 无法从“Base”转换为“Derived”
“初始化”: 无法从“Base”转换为“Derived &”
“初始化”: 无法从“Base *”转换为“Derived *”
“=”: 无法从“Base *”转换为“Derived *”
四、实验小结(包括问题和解决方法、心得体会、意见与建议等)
1.在题目(1)中将Bicycle继承Vehicle类的方式分别修改为protected和private,再重新编译,请在小结中记录报错信息,解释原因。记录采取何种修改方式使程序正确运行?
报错: “Vehicle::Run”不可访问,因为“Bicycle”使用“private”方式从“Vehicle”继承
“Vehicle::Stop”不可访问,因为“Bicycle”使用“private”方式从“Vehicle”继承
“Vehicle::Stop”不可访问,因为“Bicycle”使用“protected”方式从“Vehicle”继承
因为基类中的成员函数都是派生类的私有的或保护的成员函数,类外用派生类对象都不能再调用。
采取 public 继承方式可以使程序正确运行。
2. 在题目(2)中观察运行结果,总结在有赋值兼容的情况下,何时调用基类的成员函数,何时才会调用派生类的成员函数。
对基类调用非虚函数时总是调用基类的成员函数。
对基类调用虚函数时:
1.对基类对象进行赋值时,调用的是基类的成员函数。
2.对基类的对象引用和基类的对象指针进行赋值时,调用的属是派生类的成员函数。
全部代码
实验一
#include <iostream>
#include <string>
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
{
private:
int Height;
public:
Bicycle(int m, int w, int h) :Vehicle(m, w)
{
Height = h;
cout << "Constructing Bicycle\n";
}
~Bicycle()
{
cout << "Destructing Bicycle\n";
}
void Show()
{
Vehicle::Show();
cout << "It\'s height is: " << Height << endl;
}
};
class Car: public Vehicle
{
protected:
int SetNum;
public:
Car(int m, int w, int s) : Vehicle(m, w)
{
SetNum = s;
cout << "Constructing Car\n";
}
~Car()
{
cout << "Destructing Car\n";
}
void Show()
{
Vehicle::Show();
cout << "It\'s SetNum is: " << SetNum << endl;
}
};
class MotorCycle : public Bicycle, public Car
{
private:
int Height;
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()
{
MotorCycle::Show();
cout << "It\'s height is: " << Height << endl;
}
};
int main()
{
Bicycle b(1, 2, 3);
b.Run();
b.Stop();
b.Show();
Car c(4, 5, 6);
c.Run();
c.Stop();
c.Show();
return 0;
}
实验二
#include <iostream>
#include <string>
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(11); //1
cout << "基类对象 b1.show():\n";
b1.show();
Derived d1(21); //2
b1 = d1; //3
cout << "基类 b1 = d1, b1.show():\n";
b1.show();
cout << "派生类对象 d1.show():\n";
d1.show();
Base &b2 = d1; //4
cout << "引用b2 = d1, b2.show():\n";
b2.show();
Base* b3 = &d1; //5
cout << "基类指针 b3 = &d1, b3->show():\n";
b3->show();
Derived* d4 = new Derived(4);
Base* b4 = d4;
cout << "基类指针 b4 = d4, b4->show():\n";
b4->show();
cout << "派生类指针 d4, d4->show():\n";
d4->show();
delete d4;
Derived d5=b1;
Derived &d6=b1;
Derived *d7=&b1;
d7=b3;
return 0;
}
/*
Derived d5 = b1;
Derived &d6 = b1;
Derived *d7 = &b1;
d7 = b3;
*/