面向对象程序设计C++:继承、派生和多态

实验内容:利用继承、派生实现功能

(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;


总结

  1. 结合需求,分析类与类之间的继承、聚合关系:
    ①继承关系指一个类(称为子类、子接口)继承另外的一个类(称为父类、父接口)的功能,并可以增加它自己的新功能的能力。因此在一个类需要另一个类的方法或者属性时需要用到继承、多重继承,本例中“教室”、“办公室”、“实验室”三个派生类需要使用“房间”的楼号与房间号属性信息,“学生”、“教师”、“行政”三个派生类需要使用“人员”的姓名、性别、学院、年龄的属性信息。
    ②聚合关系也是委托关系,一个类中包含另一个类的指针,你也同样拥有被包含类的全部功能体现的是整体与部分的关系。此时整体与部分之间是可分离的,它们可以具有各自的生命周期,部分可以属于多个整体对象,也可以为多个整体对象共享。例如“学生”和“教室”可以独立存在,但是“学生”也可以存在于“教室”中,其余派生同理。
  2. 赋值兼容原则:
    ①子类对象可以当作父类对象使用
    ②子类对象可以直接赋值给父类对象
    ③子类对象可以直接初始化父类对象
    ④父类指针可以直接指向子类对象
    ⑤父类引用可以直接引用子类对象
  3. 如何实现运行时的多态性:
    通过虚函数实现运行时多态。虚函数是用来告诉编译器不要马上确定指针所指对象,把它留到运行时再做决定,虚函数声明只能出现在类定义中的函数原型声明中,而不能在成员函数实现的时候。虚函数一般不声明为内联函数,因为对虚函数的调用需要动态绑定,而对内联函数的处理是静态的。
    //定义“房间”基类
    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();
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值