实验内容:利用继承、派生实现功能
(1)由“房间”基类派生“教室”、“办公室”、“实验室”三个派生类,要求如下:
“教室”类包含:楼号、房间号、座位数、责任人(由1名行政人员担任);
“办公室”类包含:楼号、房间号、人员数量、行政人员1、行政人员2、…;
“实验室”类包含:楼号、房间号、教师数量、学生数量、教师1、教师2、…、学生1、学生2、…;
(2)其中“学生”、“教师”、“行政”三个派生类由“人员”基类派生,要求如下:
“学生”类包含:姓名、性别、学院、年龄、入学年份、专业;
“教师”类包含:姓名、性别、学院、年龄、职称、研究方向;
“行政”类包含:姓名、性别、学院、年龄、负责工作;
根据以上需求描述定义相应的基类与派生类,根据需求定义构造、析构、显示信息等成员函数,编写主程序验证功能,定义以下对象并在控制台输出相关信息:
教室1间;
办公室1间(包含至少2名行政);
实验室1间(包含至少2名教师、3名学生);
一、实验代码
#include<iostream>
#include<string>
#include<iomanip> //包含setw()输出域宽函数
using namespace std;
/***************************************************************/
//定义“人员”基类
class Person
{
public:
string name; //定义姓名
string sex; //定义性别
string college; //定义学院
int age; //定义年龄
Person(string,string,string,int);//构造函数
Person(); //默认的构造函数
~Person(); //析构函数
virtual void OutputPerson(); //虚函数声明输出人员信息
};
Person::Person(string nametemp,string sextemp,string collegetemp,int agetemp)
{
name=nametemp;sex=sextemp;college=collegetemp;age=agetemp;
}
Person::Person(){}
Person::~Person(){}
//输出人员信息:属性包括姓名、性别、学院、年龄
void Person::OutputPerson()
{
//通过域宽setw()调整输出排版
cout<<setw(10)<<"姓名"<<setw(18)<<"性别"<<setw(18)<<"学院"<<setw(18)<<"年龄"<<endl;
cout<<setw(10)<<name<<setw(18)<<sex<<setw(18)<<college<<setw(18)<<age<<endl;
}
/***************************************************************/
//定义派生的“学生”类
class Student : public Person
{
public:
string year; //定义入学年份
string major; //定义专业
Student(string name,string sex,string college,int age,string year,string major);//构造函数
Student(); //默认的构造函数
~Student(); //析构函数
void OutputPerson();//输出学生信息
};
//构造函数:姓名、性别、学院、年龄属性继承“人员”类
Student::Student(string name,string sex,string college,int age,string yeartemp,string majortemp) :Person(name,sex,college,age)
{
year=yeartemp;
major=majortemp;
}
Student::Student(){}
Student::~ Student(){}
//打印学生情况函数
void Student::OutputPerson()
{
cout<<setw(10)<<"姓名"<<setw(18)<<"性别"<<setw(18)<<"学院"<<setw(18)<<"年龄"<<setw(18)<<"入学年份"<< setw(18) << "专业"<<endl;
cout<<setw(10)<<name<<setw(18)<<sex<<setw(18)<<college<<setw(18)<<age<<setw(18)<<year << setw(18) << major << endl;
}
/***************************************************************/
//定义派生的“教师”类
class Teacher : public Person
{
string title; //定义职称
string direction; //定义研究方向
public:
Teacher(string name,string sex,string college,int age,string title,string direction);//构造函数
Teacher(); //默认的构造函数
~Teacher(); //析构函数
void OutputPerson();//输出教师信息
};
//构造函数:姓名、性别、学院、年龄属性继承“人员”类
Teacher::Teacher(string name,string sex,string college,int age,string titletemp,string directiontemp) :Person(name,sex,college,age)
{
title=titletemp;direction=directiontemp;
}
Teacher::Teacher(){}
Teacher::~Teacher(){}
//打印教师情况函数
void Teacher::OutputPerson()
{
cout<<setw(10)<<"姓名"<<setw(18)<<"性别"<<setw(18)<<"学院"<<setw(18)<<"年龄"<<setw(18)<<"职称"<< setw(18) << "研究方向"<<endl;
cout<<setw(10)<<name<<setw(18)<<sex<<setw(18)<<college<<setw(18)<<age<<setw(18)<<title << setw(18) << direction << endl;
}
/*************************************************************/
//定义派生的行政类
class Admstaff : public Person
{
string work; //定义负责工作
public:
Admstaff(string name,string sex,string college,int age,string work);//构造函数
Admstaff(); //默认的构造函数
~Admstaff(); //析构函数
void OutputPerson();
};
//构造函数:姓名、性别、学院、年龄属性继承“人员”类
Admstaff::Admstaff(string name,string sex,string college,int age,string worktemp) :Person(name,sex,college,age)
{
work=worktemp;
}
Admstaff::Admstaff(){}
Admstaff::~Admstaff(){}
//打印行政人员情况函数
void Admstaff::OutputPerson()
{
cout<<setw(10)<<"姓名"<<setw(18)<<"性别"<<setw(18)<<"学院"<<setw(18)<<"年龄"<<setw(18)<<"负责工作"<<endl;
cout<<setw(10)<<name<<setw(18)<<sex<<setw(18)<<college<<setw(18)<<age<<setw(18)<<work<<endl;
}
/****************************************************************/
//定义“房间”类
class Room
{
public:
string build_number; //定义楼号
string room_number; //定义房间号
Room(string,string); //构造函数
Room(); //默认的构造函数
~Room(); //析构函数
virtual void OutputRoom(); //声明虚函数输出房间信息
};
//构造函数:属性包含楼号、房间号
Room::Room(string build_numbertemp,string room_numbertemp)
{
build_number=build_numbertemp;
room_number=room_numbertemp;
}
Room::Room(){}
Room::~Room(){}
//输出房间信息
void Room::OutputRoom()
{
cout<<setw(10)<<"楼号"<<setw(18)<<"房间号"<<endl;
cout<<setw(10)<<build_number<<setw(18)<<room_number<<endl;
}
/***************************************************************/
//定义房间类派生的“教室”类
class Classroom : public Room
{
public:
int seat_num; //定义座位数量
Admstaff adm1; //定义行政类的人员adm1
Classroom(string,string,int,Admstaff);//构造函数
Classroom(); //默认的构造函数
~Classroom(); //析构函数
void OutputRoom();
};
//构造函数:楼号、房间号属性继承“房间”类
Classroom::Classroom(string build_number,string room_number,int seat_numtemp,Admstaff adm1temp) :Room(build_number,room_number)
{
seat_num=seat_numtemp;
adm1=adm1temp;
}
Classroom::~ Classroom(){}
//打印教室情况函数
void Classroom::OutputRoom()
{
cout<<"教室信息:"<<endl;
cout<<setw(10)<<"楼号"<<setw(18)<<"房间号"<<setw(18)<<"座位数"<<endl;
cout<<setw(10)<<build_number<<setw(18)<<room_number<<setw(18)<<seat_num<<endl;
cout<<setw(10)<<"负责人:"<<endl;
adm1.OutputPerson();
cout<<endl;
}
/**************************************************************/
//定义房间类派生的“办公室”类
class Office : public Room
{
public:
int adm_num; //定义行政人员数量
Admstaff adm1,adm2; //定义行政类的人员adm1、adm2
Office(string,string,int,Admstaff,Admstaff);//构造函数
Office(); //默认的构造函数
~Office(); //析构函数
void OutputRoom(); //输出教师信息
};
//构造函数:楼号、房间号属性继承“房间”类
Office::Office(string build_number,string room_number,int adm_numtemp,Admstaff adm1temp,Admstaff adm2temp) :Room(build_number,room_number)
{
adm_num=adm_numtemp;
adm1=adm1temp;
adm2=adm2temp;
}
Office::~ Office(){}
//打印办公室情况函数
void Office::OutputRoom()
{
cout<<"办公室信息:"<<endl;
cout<<setw(10)<<"楼号"<<setw(18)<<"房间号"<<setw(18)<<"人员数量"<<endl;
cout<<setw(10)<<build_number<<setw(18)<<room_number<<setw(18)<<adm_num<<endl;
cout<<setw(10)<<"行政人员安排:"<<endl;
adm1.OutputPerson();
adm2.OutputPerson();
cout<<endl;
}
/****************************************************************/
//定义房间类派生的“实验室”类
class Laboratory : public Room
{
public:
int stu_num; //定义学生数量
int tea_num; //定义教师数量
Student stu1,stu2,stu3; //定义学生类的人员stu1,stu2,stu3
Teacher tea1,tea2; //定义教师类的人员tea1,tea2
Laboratory(string,string,int,int,Teacher,Teacher,Student,Student,Student);//构造函数
Laboratory(); //默认的构造函数
~Laboratory(); //析构函数
void OutputRoom(); //输出实验室信息
};
//构造函数:楼号、房间号属性继承“房间”类
Laboratory::Laboratory(string build_number,string room_number,int stu_numtemp,int tea_numtemp,Teacher tea1temp,Teacher tea2temp,Student stu1temp,Student stu2temp,Student stu3temp) :Room(build_number,room_number)
{
stu_num=stu_numtemp;
tea_num=tea_numtemp;
tea1=tea1temp;
tea2=tea2temp;
stu1=stu1temp;
stu2=stu2temp;
stu3=stu3temp;
}
Laboratory::~ Laboratory(){}
//打印实验室情况函数
void Laboratory::OutputRoom()
{
cout<<"实验室信息:"<<endl;
cout<<setw(10)<<"楼号"<<setw(18)<<"房间号"<<setw(18)<<"教师数量"<<setw(18)<<"学生数量"<<endl;
cout<<setw(10)<<build_number<<setw(18)<<room_number<<setw(18)<<tea_num<<setw(18)<<stu_num<<endl;
cout<<setw(10)<<"教师安排:"<<endl;
tea1.OutputPerson();
tea2.OutputPerson();
cout<<setw(10)<<"学生安排:"<<endl;
stu1.OutputPerson();
stu2.OutputPerson();
stu3.OutputPerson();
}
//主函数
int main()
{
// Person per("刘亦菲1",woman,"传播学院1",18);
// p.OutputPerson();
//为了调试方便,这里不采取键盘输入,直接定义相关人员信息及房间信息
Student stu1("刘小菲","女","传播学院",18,"2018","表演系");
Student stu2("陈小黄","男","电子学院",20,"2018","电子系");
Student stu3("钟小红","女","机电学院",20,"2018","自动化");
Teacher tea1("罗大广","男","传播学院",30,"教导主任","表演类");
Teacher tea2("蔡大晴","女","物理学院",28,"辅导员","法学");
Admstaff adm1("张中正","男","法学院",28,"部门协调");
Admstaff adm2("萸中莹","女","法学院",26,"档案管理");
// Room r("致理楼","505");
// r.OutputRoom();
Classroom cla1("教学楼","101",50,adm1);
Office off1("致文楼","303",2,adm1,adm2);
Laboratory lab1("致理楼","505",3,2,tea1,tea2,stu1,stu2,stu3);
Room* r1=&cla1; //指针类型根据等号后的引用类型确定
r1 -> OutputRoom(); //运行时指向基类,才确定输出的子类对象
cout<<"--------------------------------------------------------------------------"<<endl;
Room* r2=&off1;
r2 -> OutputRoom();
cout<<"--------------------------------------------------------------------------"<<endl;
Room* r3=&lab1;
r3 -> OutputRoom();
return 0;
}
二、实验结果
1.测试用例:
Student stu1("刘小菲","女","传播学院",18,"2018","表演系");
Student stu2("陈小黄","男","电子学院",20,"2018","电子系");
Student stu3("钟小红","女","机电学院",20,"2018","自动化");
Teacher tea1("罗大广","男","传播学院",30,"教导主任","表演类");
Teacher tea2("蔡大晴","女","物理学院",28,"辅导员","法学");
Admstaff adm1("张中正","男","法学院",28,"部门协调");
Admstaff adm2("萸中莹","女","法学院",26,"档案管理");
Classroom cla1("教学楼","101",50,adm1);
Office off1("致文楼","303",2,adm1,adm2);
Laboratory lab1("致理楼","505",3,2,tea1,tea2,stu1,stu2,stu3);
2.输出结果
3.实验分析
①“房间”基类中数据成员包含楼号build_number和房间号room_number
public:
string build_number;
string room_number;
②“人员”基类中数据成员包含姓名name、性别sex、学院college、年龄age
public:
string name;
string sex;
string college;
int age;
总结
- 结合需求,分析类与类之间的继承、聚合关系:
①继承关系指一个类(称为子类、子接口)继承另外的一个类(称为父类、父接口)的功能,并可以增加它自己的新功能的能力。因此在一个类需要另一个类的方法或者属性时需要用到继承、多重继承,本例中“教室”、“办公室”、“实验室”三个派生类需要使用“房间”的楼号与房间号属性信息,“学生”、“教师”、“行政”三个派生类需要使用“人员”的姓名、性别、学院、年龄的属性信息。
②聚合关系也是委托关系,一个类中包含另一个类的指针,你也同样拥有被包含类的全部功能体现的是整体与部分的关系。此时整体与部分之间是可分离的,它们可以具有各自的生命周期,部分可以属于多个整体对象,也可以为多个整体对象共享。例如“学生”和“教室”可以独立存在,但是“学生”也可以存在于“教室”中,其余派生同理。 - 赋值兼容原则:
①子类对象可以当作父类对象使用
②子类对象可以直接赋值给父类对象
③子类对象可以直接初始化父类对象
④父类指针可以直接指向子类对象
⑤父类引用可以直接引用子类对象 - 如何实现运行时的多态性:
通过虚函数实现运行时多态。虚函数是用来告诉编译器不要马上确定指针所指对象,把它留到运行时再做决定,虚函数声明只能出现在类定义中的函数原型声明中,而不能在成员函数实现的时候。虚函数一般不声明为内联函数,因为对虚函数的调用需要动态绑定,而对内联函数的处理是静态的。
//定义“房间”基类
class Room
{
public:
…… ……
virtual void OutputRoom(); //虚函数声明输出房间信息
};
//定义“人员”基类
class Person
{
public:
…… ……
virtual void OutputPerson(); //虚函数声明输出人员信息
};
//运行时多态输出教室、办公室、实验室:
Room* r1=&cla1; //指针类型根据等号后的引用类型确定
r1 -> OutputRoom(); //运行时指向基类,才确定输出的子类对象
Room* r2=&off1;
r2 -> OutputRoom();
Room* r3=&lab1;
r3 -> OutputRoom();