将我们学校C++课的实验报告copy上来,希望能给未来的学弟学妹做参考
教材:C++语言程序设计(第四版) 清华大学出版社
一、实验目的
1、学习声明和使用类的继承关系,声明派生类
2、熟悉不同继承方式下对基类成员的访问控制
3、学习利用虚基类解决二义性问题
二、实验任务
1、声明一个基类Animal,有私有整型成员变量age,构造其派生类dog,在其成员函数SetAge(int n)中直接给age赋值,看看有什么问题,把age改为公有成员变量,还会有问题吗?编程试试看。
2、声明一个基类BaseClass,有整型成员变量Number,构造其派生类DerivedClass,观察构造函数和析构函数的执行情况。
3、声明一个车(vehicle)基类,具有Maxspeed,Weight等成员变量,Run、Stop等成员函数,由此派生出自行车(bicycle)类,汽车(motorcar)类。自行车(bicycle)类有高度(Height)等属性,汽车(motorcar)类有座位数(SeatNum)等属性。从bicycle和motorcar派生出摩托车(motorcycle)类,在继承过程中,注意把vehicle设置为虚基类。如果不把vehicle设置为虚基类,会有什么问题?编程试试看。
三、实验步骤及内容
实验1. 实现基类Animal,派生类的dog的定义声明
1.1代码及注释说明
//age为aprivate时º
#include <iostream>
#include <string>
using namespace std;
classAnimal
{
private:
int age;
};
class dog:public Animal
{
public:
void SetAge(int n)
{
age=n;
}
}
问题:age无法访问
//age为public时
#include <iostream>
#include <string>
using namespace std;
classAnimal
{
public:
int age;
voidshowage()
{
cout<<age<<endl;
}
};
class dog:public Animal
{
public:
void SetAge(int n)
{
age=n;
}
};
intmain()
{
dog b;
b.SetAge(3);
b.showage();
return 0;
}
问题解决
1.2解析(算法设计思路,程序逻辑,流程图)
1.3运行结果及分析(测试用例,结果,截图,分析)
1.4故障和失败原因
结果截图(只保留有效内容)
原因及解决方案:dog类的大括号后忘记加分号,补上分号后问题解决
实验2. 实现基类BaseClass,派生类的DerivedClass的定义声明,观察构造函数和析构函数的执行情况。
2.1代码
#include<iostream>
#include<string>
usingnamespace std;
classBaseClass //基类
{
public:
BaseClass()//默认构造函数
{
Number=0;//number初始为0
cout<<"BaseClass's defaultconstructor is called"<<endl;
}
BaseClass(int n)//带参数的构造函数
{
Number=n;//输入的n赋值给number
cout<<"BaseClass's constructor is called"<<endl;
}
~BaseClass() //析构函数
{
cout<<"BaseClasaas'sdestructor is called"<<endl;
}
void GetNumber()//输出成员数据number
{
cout<<Number<<endl;
}
private:
int Number;
};
classDerivedClass:public BaseClass //派生类
{
public:
DerivedClass() //默认构造函数
{
c=0;
cout<<"DerivedClass'sdefault constructor is called"<<endl;
}
DerivedClass(int a,int b):BaseClass(a)//带参数的构造函数,第一个参数a传给继承下来的基类数据成员number
{
c=b;
cout<<"DerivedClass's constructor is called"<<endl;
}
~DerivedClass()//析构函数
{
cout<<"DerivedClass'sdestructor is called"<<endl;
}
void Getc()//输出继承的基类数据成员Nummber和自己的数据成员c
{
GetNumber();
cout<<c<<endl;
}
private:
int c;
};
intmain()
{
DerivedClass class1;//定义DerivedClass类对象 class1,不给参数,调用默认构造函数
class1.Getc() ;
DerivedClass class2(1,2);// 定义DerivedClass类对象 class2
class2.Getc();
return 0;
}
2.2解析(算法设计,程序逻辑,流程图)
(1).声明定义基类BaseClass
定义实现其构造函数,析构函数。
声明数据成员Number。
声明定义成员函数GetNumber();用以输出Number
(2).声明定义派生类DerivedClass(继承方式为public)
定义实现其构造函数,析构函数。
声明数据成员c
声明定义成员函数Getc();用以输出c
(3)主函数中定义DerivedClass类对象 class1,class2(1,2)
并分别调用其成员函数Getc
(4)观察结果.
2.3运行结果及分析(测试用例,结果,截图,分析)
第一、 二行:定义class1后,由于没有给参数。调用基类默认构造函数和派生类默认构造函数。
第二、 四行:由于在两个类的默认构造函数中,默认给数据成员Number和c赋值为0,所以调用Getc()后,输出两个0
第五、六行:定义 class2(1,2)。调用构造函数时输出提示语句
第七、八行:输出class2的Number和c的值
第九—十二行:调用析构函数(与调用构造函数的顺序相反)
2.4故障和失败原因
结果截图(只保留有效内容),并加以说明故障的原因以及解决方法
问题截图:
错误提示
问题代码
原因:定义对象时出错。
解决方法
DerivedClass class1();改为DerivedClass class1;
实验3. 声明一个车(vehicle)基类,具有Maxspeed,Weight等成员变量,Run、Stop等成员函数,由此派生出自行车(bicycle)类,汽车(motorcar)类。自行车(bicycle)类有高度(Height)等属性,汽车(motorcar)类有座位数(SeatNum)等属性。
3.1代码
#include <iostream>
#include <string>
using namespace std;
class vehicle//定义虚基类vehicle
{
public:
vehicle()//默认构造函数
{
cout<<"vehicle'sdefault constructor is called"<<endl;
Maxspeed=0;
Weight=0;
}
~vehicle()//析构函数
{
cout<<"vehicle'sdestructor is called"<<endl;
};
void SetV(float a,floatb)//改变maxspeed和weight的函数
{
Maxspeed=a;
Weight=b;
}
void run()
{
cout<<"caris running"<<endl;
}
void stop()
{
cout<<"caris stopping"<<endl;
}
void GetMaxspeed()//输出最大速度
{
cout<<"Maxspeed="<<Maxspeed<<endl;
}
void GetWeight()//输出重量
{
cout<<"Weight="<<Weight<<endl;
}
private:
float Maxspeed,Weight;
};
class bicycle:virtual public vehicle
{
public:
bicycle()//默认构造函数
{
Height=0;
cout<<"bicycle'sdefault constructor is called"<<endl;
}
~bicycle()//析构函数
{
cout<<"bicycle'sdestructor is called"<<endl;
}
void SetHeight(floata)//设置高度
{
Height=a;
}
void GetHeight()
{
cout<<"Height="<<Height<<endl;
}
private:
float Height;
};
class motorcar:virtual public vehicle
{
public:
motorcar()//默认构造函数
{
cout<<"motorcar'sdefault constructor is called"<<endl;
SeatNum=0;
}
~motorcar()//析构函数
{
cout<<"motorcar'sdestructor is called"<<endl;
}
void SetSeatNum(int a)//设置座位个数
{
SeatNum=a;
}
void GetSeatNum()
{
cout<<"SeatNum="<<SeatNum<<endl;
}
private:
int SeatNum;
};
class motorcycle:public bicycle,public motorcar
{
public:
motorcycle()//默认构造函数
{
cout<<"motorcycle'sdefault constructor is called"<<endl;
cost=0;
}
~motorcycle()
{
cout<<"motorcycle'sdestructor is called"<<endl;
}
void SetCost(float a)//设置花费的函数
{
cost=a;
}
void showcost()
{
cout<<"Cost="<<cost<<endl;
}
private:
int cost;
};
int main()
{
motorcycle Mymotorcycle;
Mymotorcycle.SetV(100,200);//设置 maxspeed和weight分别为00,200
Mymotorcycle.SetHeight(300);//设置height为100
Mymotorcycle.SetSeatNum(2);//设置座位个数为2;
Mymotorcycle.SetCost(520.11);//设置cost为520.11
Mymotorcycle.GetMaxspeed();//输出GetMaxspeed
Mymotorcycle.GetWeight();//输出weight
Mymotorcycle.GetSeatNum();//输出座位数
Mymotorcycle.showcost();//输出cost
return 0;
}
3.2解析(算法设计,程序逻辑,流程图)
(1)声明一个车(vehicle)基类,具有Maxspeed,Weight等成员变量,Run、Stop等成员函数。定义改变成员变量的函数和输出成员变量的函数。
(2)由车(vehicle)基类派生出自行车(bicycle)类,汽车(motorcar)类。自行车(bicycle)类有高度(Height)等属性,汽车(motorcar)类有座位数(SeatNum)等属性。定义改变成员变量的函数和输出成员变量的函数。
(3) 从bicycle和motorcar派生出摩托车(motorcycle)类,具有成员变量cost,以及改变成员变量的函数和输出成员变量的函数。
(4)在主函数中,定义motorcycle类对象Mymotorcycle。通过调用在直接基类和间接基类里定义的函数,设置和输出成员变量Maxspeed,Weight,SeatNum,Cost。
(5)观察结果
3.3运行结果及分析(测试用例,结果,截图,分析)
3.4故障和失败原因
结果截图(只保留有效内容),并加以说明故障的原因以及解决方法
故障原因:没有把vehicle设置为虚基类,导致出现二义性问题,大批报错。
解决方法,将vehicle设置为虚基类。
即将bicycle类和motorcar类的定义语句修改如下:
class bicycle:virtual public vehicle
class motorcar:virtual public vehicle
同时删去之前定义的带参数的构造函数(可以有不删的方法,但这次没有去实现)