<center> 浙江理工大学信息学院 </center> <center> 实验指导书 <center> <center> 实验名称:类的继承机制的实现 学时安排:3 </center> <center> 实验类别:设计性实验 实验要求:1人1组 </center> <center>  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ </center> </center> </center>

一、实验目的
1.掌握单继承和多重继承的概念。
2.理解不同的继承类型:public、protected和private,掌握何时使用何种继承类型。
3.掌握类层次中构造函数的定义方式和建立对象时构造和析构次序
二、实验原理介绍
通过继承机制实现对类功能的扩展,合理设计派生类的构造函数、成员函数。
三、实验设备介绍
软件需求: Visual C++ 6.0
硬件需求: 对于硬件方面的要求,建议配置是Pentium III 450以上的CPU处理器,64MB以上的内存,200MB的自由硬盘空间、CD-ROM驱动器、能支持24位真彩色的显示卡、彩色显示器、打印机。
四、实验内容
实现对第一次实验结果Elevator类的功能扩展。在Elevator类已有功能的基础上派生AdvElevator类。AdvElevator类可以实现当多人在不同楼层等待乘坐上行或下行的同一部电梯时,能够合理的根据乘坐人的需求对电梯经停的楼层进行排序。
要求:
1.为了实现上的方便性,我们假设同一组要求乘坐电梯的乘客或者都是上行,或者都是下行。
2.在主函数中对该类的功能进行测试,测试方法是首先选择在某一时间段一组要乘坐电梯的乘客是上行还是下行,然后输入组中乘客的人数及每一个乘客所在楼层和目的楼层,由AdvElevator类实例化后的电梯对象在运作的过程中,如果电梯是上行,则能根据乘客所在的楼层和目的楼层从下向上依次停靠;如果电梯是下行,则能根据乘客所在的楼层和目的楼层从上向下依次停靠。
3.在测试的过程中,还需要注意测试当多个用户在同一楼层或多个用户的目的楼层为同一楼层时情况的处理。
程序要求的结果请运行elevator.exe
提示:
为了方便描述乘客,我们可以定义一个Person类,主要描述每一个乘客所在楼层和目的楼层。AdvElevator类从Elevator类继承而来,它从某一个时间段要乘坐电梯的每个乘客的信息当中提取其所在楼层和目的楼层信息,然后对它们进行排序,再由继承自基类Elevator的成员setFloorNumber对要停靠的楼层序列依次输出。
思考(可选)
如果加入乘客的体重信息,如何实现在停靠楼层对超载信息的提示。
五、注意事项和要求
要求学生要提前准备实验的内容
实验完成后要求写出实验报告
六、参考书目
【C++ Prime题解】侯捷译 华中科技大学出版社
【C++程序设计与应用】 张耀仁著 华中科技大学出版社

<center> 浙江理工大学信息学院 </center> <center> 实验指导书 </center> <center> 实验名称:类的继承机制的实现 学时安排:3 </center> <center> 实验类别:设计性实验 实验要求:1人1组 </center> <center> 学号: 2018329621200 姓名 申屠志刚 </center> <center>  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ </center>

一、实验目的
1.掌握单继承和多重继承的概念。
2.理解不同的继承类型:public、protected和private,掌握何时使用何种继承类型。
3.掌握类层次中构造函数的定义方式和建立对象时构造和析构次序
二、实验原理介绍
通过继承机制实现对类功能的扩展,合理设计派生类的构造函数、成员函数。
三、实验设备介绍
软件需求: windows或linux下的c++编译器
硬件需求: 对于硬件方面的要求,建议配置是Pentium III 450以上的CPU处理器,64MB以上的内存,200MB的自由硬盘空间、CD-ROM驱动器、能支持24位真彩色的显示卡、彩色显示器、打印机。
四、实验内容
实现对第一次实验结果Elevator类的功能扩展。在Elevator类已有功能的基础上派生AdvancedElevator类。AdvancedElevator类可以实现当多人在不同楼层等待乘坐上行或下行的同一部电梯时,能够合理的根据乘坐人的需求对电梯经停的楼层进行排序。
要求:
1.为了实现上的方便性,我们假设同一组要求乘坐电梯的乘客或者都是上行,或者都是下行。
2.在主函数中对该类的功能进行测试,测试方法是首先选择在某一时间段一组要乘坐电梯的乘客是上行还是下行,然后输入组中乘客的人数及每一个乘客所在楼层和目的楼层,由AdvancedElevator类实例化后的电梯对象在运作的过程中,如果电梯是上行,则能根据乘客所在的楼层和目的楼层从下向上依次停靠;如果电梯是下行,则能根据乘客所在的楼层和目的楼层从上向下依次停靠。
3.在测试的过程中,还需要注意测试当多个用户在同一楼层或多个用户的目的楼层为同一楼层时情况的处理。
提示:
为了方便描述乘客,我们可以定义一个Person类,主要描述每一个乘客所在楼层和目的楼层。AdvancedElevator类从Elevator类继承而来,它从某一个时间段要乘坐电梯的每个乘客的信息当中提取其所在楼层和目的楼层信息,然后对它们进行排序,再由继承自基类Elevator的成员setFloorNumber对要停靠的楼层序列依次输出。
思考(可选)
如果加入乘客的体重信息,如何实现在停靠楼层对超载信息的提示。
五 程序清单
Person.h

#ifndef PERSON_H
#define PERSON_H


class Person
{
    public:
        Person();
        Person(int ID,int u,int v);
        Person(int ID,int u,int v,int w);
        virtual ~Person();
        void setID(int ID);
        void setform(int u);
        void setto(int v);
        void setweight(int w);
        int getID();
        int getform();
        int getto();
        int getweight();
        bool operator <(const Person & P );
    protected:

    private:
        int id;//乘客编号
        int form;//乘客起点
        int to;//乘客终点
        int weight;//乘客体重
};

#endif // PERSON_H

Person.cpp

#include "Person.h"

Person::Person()
{
    //ctor
}

Person::~Person()
{
    //dtor
}
Person::Person(int ID,int u,int v):id(ID),form(u),to(v),weight(50)
{
    //ctor
}
Person::Person(int ID,int u,int v,int w):id(ID),form(u),to(v),weight(w)
{
    //ctor
}
void Person::setID(int ID){
    id=ID;
}
void Person::setform(int u){
    form=u;
}
void Person::setto(int v){
    to=v;
}
void Person::setweight(int w){
    weight=w;
}
int Person::getID(){
    return id;
}
int Person::getform(){
    return form;
}
int Person::getto(){
    return to;
}
int Person::getweight(){
    return weight;
}
bool Person::operator <(const Person & P ){//重载运算符排序
    if(form==P.form)
        to<P.to;
    return form<P.form;
}

Elevator.h

#ifndef ELEVATOR_H
#define ELEVATOR_H
#include <iostream>
#include <windows.h>
#include <stdlib.h>
#include"date.h"
using namespace std;

class Elevator
{
    public:
        Elevator();
        virtual ~Elevator();
        Elevator(int floor);
        void setUpButton();   //按下上行按钮
        void setDownButton();  //按下下行按钮
        void setFloorNumber(int floorNumber);  //根据要进入的楼层电梯开始运行,并逐层显示经过的楼层
        int getCurrentFloor(); //获得当前所在楼层
        void setUp(bool up);
        void setDown(bool down);
        void setFloor(int floor);
        bool getup();
        bool getdown();
        int getFloor();
        void err();
        void init();
        void memu();
        void run();
    protected:
        int floor;  //电梯总的楼层数
        bool up;    //是否上行,bool为布尔类型,可取值true或false
        bool down;   //是否下行
        int currentFloor; //当前所在楼层
        CDate data;
    private:

};

#endif // ELEVATOR_H

Elevator.cpp

#include "Elevator.h"

Elevator::Elevator():floor(10),up(0),down(0),currentFloor(1)
{

}

Elevator::~Elevator()
{
    //dtor
}
Elevator::Elevator(int floor):floor(floor),up(0),down(0),currentFloor(1)
{

}
void Elevator::setUpButton()//按下上行按钮
{
    int now=getCurrentFloor(),to;
    cout<<"当前电梯停在"<<now<<"层"<<endl;
    cout<<"请输入要进入的楼层"<<endl;
    scanf("%d",&to);
    if(now>=to||to>floor||to<1){
        cout<<"您不能上行!"<<endl;
    }else{
        up=1;
        setFloorNumber(to);
        up=0;
    }
}
void Elevator::setDownButton()//按下下行按钮
{
    int now=getCurrentFloor(),to;
    cout<<"当前电梯停在"<<now<<"层"<<endl;
    cout<<"请输入要进入的楼层"<<endl;
    scanf("%d",&to);
    if(now<=to||to>floor||to<1){
        cout<<"您不能下行!"<<endl;
    }else{
        down=1;
        setFloorNumber(to);
        down=0;
    }
}
void Elevator::setFloorNumber(int floorNumber)//根据要进入的楼层电梯开始运行,并逐层显示经过的楼层
{
    if(up){
        for(int i=currentFloor;i<floorNumber;i++){
            cout<<"---"<<i<<"---"<<endl<<endl;
            Sleep(1000);
        }
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_INTENSITY);
        cout<<"第"<<floorNumber<<"层到了"<<endl;
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE|FOREGROUND_INTENSITY);
    }
    if(down){
        for(int i=currentFloor;i>floorNumber;i--){
            cout<<"---"<<i<<"---"<<endl<<endl;
            Sleep(1000);
        }
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_INTENSITY);
        cout<<"第"<<floorNumber<<"层到了"<<endl;
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE|FOREGROUND_INTENSITY);
    }
    currentFloor=floorNumber;
}
int Elevator::getCurrentFloor()//获得当前所在楼层
{
    return currentFloor;
}

void Elevator::setUp(bool up){
    this->up=up;
}
void Elevator::setDown(bool down){
    this->down=down;
}
void Elevator::setFloor(int floor){
    this->floor=floor;
}
bool Elevator::getup(){
    return up;
}
bool Elevator::getdown(){
    return down;
}
int Elevator::getFloor(){
    return floor;
}
void Elevator::err()
{
    cout<<"-----无效操作-----"<<endl;
}
void Elevator::memu()
{
    cout<<" ---请选择操作----"<<endl;
    cout<<"| 1.上升 |"<<endl;
    cout<<"| 2.下降 |"<<endl;
    cout<<"| 3.退出 |"<<endl;
    cout<<" -----------------"<<endl;
}
void Elevator::init()
{
    cout<<"今天是"<<data.format("DDD")<<endl;
    cout<<"该电梯一共"<<getFloor()<<"层, 欢迎您的使用!"<<endl;
}
void Elevator::run()
{
    init();
    bool online=1;
    while(online){
        int op;
        memu();
        scanf("%d",&op);
        switch(op){
            case 1:setUpButton();break;
            case 2:setDownButton();break;
            case 3:online=1;break;
            default:err();break;
        }
    }
}

AdvElevator.h

#ifndef ADVELEVATOR_H
#define ADVELEVATOR_H

#include <Elevator.h>
#include "Person.h"
#include <vector>
class AdvElevator : public Elevator
{
    public:
        AdvElevator();
        AdvElevator(int floor);
        AdvElevator(int floor,int weight);
        virtual ~AdvElevator();
        void setLimitWeight(int weight);
        int getLimitWeght();
        void setUpButton();
        void setDownButton();
        void init();
        void run();
    protected:
        int limitweight;
    private:

};
#endif // ADVELEVATOR_H

AdvElevator.cpp

#include "AdvElevator.h"
//构造函数 默认楼层数 默认载重
AdvElevator::AdvElevator():Elevator(10),limitweight(200)
{
    //ctor
}

AdvElevator::~AdvElevator()
{
    cout<<"谢谢使用!"<<endl;
    //dtor
}
//构造函数 自定义楼层数 默认载重
AdvElevator::AdvElevator(int floor):Elevator(floor),limitweight(200)
{
    //ctor
}
//构造函数 自定义楼层数 自定义载重
AdvElevator::AdvElevator(int floor,int weight):Elevator(floor),limitweight(weight)
{
    //ctor
}
void AdvElevator::setUpButton()//按下上行按钮
{
    int now=getCurrentFloor();//获取当前电梯楼层
    //如果当前在顶楼不能上行
    if(now==floor){
        cout<<"本电梯已经到达顶楼"<<endl;
        return;
    }
    cout<<"请输入要乘坐电梯的人数"<<endl;
    int num=0;
    scanf("%d",&num);
    Person person[num];
    cout<<"请输入每个人所在楼层和目的楼层和此人体重"<<endl;
    cout<<"当前电梯停在"<<now<<"层"<<endl;
    int u,v,w;//临时记录乘客信息
    int nowW=0;//存储当前电梯负载
    int cnt[floor+1]={0};//桶排序数组
    bool vis[floor+1]={0};//标记乘客是否上电梯
    //in存储楼层上电梯的乘客,out存储楼层下电梯的乘客
    vector<Person>in[floor+1],out[floor+1];
    for(int i=0;i<num;i++){
        scanf("%d%d%d",&u,&v,&w);
        //判断乘客是否满足条件
        while(now>=v||v>floor||v<1||u<1||u>floor||now>u||u>=v||w>limitweight){//不满足条件重新录入
            if(u==v){
                cout<<"您不需要坐本电梯!"<<endl;
            }else if(w>limitweight){
                cout<<"您体重超出荷载!"<<endl;
            }else{
                cout<<"您不能上行!"<<endl;
            }
            scanf("%d%d%d",&u,&v,&w);
        }
        person[i]=Person(i+1,u,v,w);
        cnt[u]++;//桶排序
        cnt[v]++;
        in[u].push_back(person[i]);
        out[v].push_back(person[i]);
    }
    //处理当前楼层上电梯乘客
    for(int i=0,j=in[now].size();i<j;i++){
        if(limitweight-nowW>=in[now][i].getweight()){
            vis[in[now][i].getID()]=1;
            nowW+=in[now][i].getweight();
        }else{
            cout<<"已超重!!"<<endl;
            cout<<"第"<<in[now][i].getID()<<"位乘客不能上行!"<<endl;
        }
    }
    //运行电梯
    for(int i=now+1;i<=floor;i++){
        if(cnt[i]){
            up=1;
            //调用父类函数setFloorNumber();
            //电梯运行到下一个有乘客上下电梯的楼层
            setFloorNumber(i);
            up=0;
            //先下后上
            for(int j=0,k=out[i].size();j<k;j++){
                if(vis[out[i][j].getID()]){
                    vis[out[i][j].getID()]=0;
                    nowW-=out[i][j].getweight();
                }
            }
            for(int j=0,k=in[i].size();j<k;j++){
                if(limitweight-nowW>=in[i][j].getweight()){
                    vis[in[i][j].getID()]=1;
                    nowW+=in[i][j].getweight();
                }else{
                    cout<<"已超重!!"<<endl;
                    cout<<"第"<<in[i][j].getID()<<"位乘客不能上行!"<<endl;
                }
            }

        }
    }
}
void AdvElevator::setDownButton()//按下下行按钮
{
    int now=getCurrentFloor();//获取当前电梯楼层
    //如果当前在顶楼不能上行
    if(now==1){
        cout<<"本电梯已经到达底楼"<<endl;
        return;
    }
    cout<<"请输入要乘坐电梯的人数"<<endl;
    int num=0;
    scanf("%d",&num);
    Person person[num];
    cout<<"请输入每个人所在楼层和目的楼层和此人体重"<<endl;
    cout<<"当前电梯停在"<<now<<"层"<<endl;
    int u,v,w;//临时记录乘客信息
    int nowW=0;//存储当前电梯负载
    int cnt[floor+1]={0};//桶排序数组
    bool vis[floor+1]={0};//标记乘客是否上电梯
    //in存储楼层上电梯的乘客,out存储楼层下电梯的乘客
    vector<Person>in[floor+1],out[floor+1];
    for(int i=0;i<num;i++){
        scanf("%d%d%d",&u,&v,&w);
        //判断乘客是否满足条件
        while(now<=v||v>floor||v<1||u<1||u>floor||now<u||u<=v||w>limitweight){//不满足条件重新录入
            if(u==v){
                cout<<"您不需要坐本电梯!"<<endl;
            }else if(w>limitweight){
                cout<<"您体重超出荷载!"<<endl;
            }else{
                cout<<"您不能下行!"<<endl;
            }
            scanf("%d%d%d",&u,&v,&w);
        }
        person[i]=Person(u,v,w);
        cnt[u]++;//桶排序
        cnt[v]++;
        in[u].push_back(person[i]);
        out[v].push_back(person[i]);
    }
    //处理当前楼层上电梯乘客
    for(int i=0,j=in[now].size();i<j;i++){
        if(limitweight-nowW>=in[now][i].getweight()){
            vis[in[now][i].getID()]=1;
            nowW+=in[now][i].getweight();
        }else{
            cout<<"已超重!!"<<endl;
            cout<<"第"<<in[now][i].getID()<<"位乘客不能下行!"<<endl;
        }
    }
    //运行电梯
    for(int i=now-1;i>=1;i--){
        if(cnt[i]){
            down=1;
            //调用父类函数setFloorNumber();
            //电梯运行到下一个有乘客上下电梯的楼层
            setFloorNumber(i);
            down=0;
            //先下后上
            for(int j=0,k=out[i].size();j<k;j++){
                if(vis[out[i][j].getID()]){
                    vis[out[i][j].getID()]=0;
                    nowW-=out[i][j].getweight();
                }
            }
            for(int j=0,k=in[i].size();j<k;j++){
                if(limitweight-nowW>=in[i][j].getweight()){
                    vis[in[i][j].getID()]=1;
                    nowW+=in[i][j].getweight();
                }else{
                    cout<<"已超重!!"<<endl;
                    cout<<"第"<<in[i][j].getID()<<"位乘客不能下行!"<<endl;
                }
            }
        }
    }
}
void AdvElevator::setLimitWeight(int weight){//设置最大载重
    limitweight=weight;
}
int AdvElevator::getLimitWeght(){//返回最大载重
    return limitweight;
}
void AdvElevator::init()//重写初始化
{
    Elevator::init();//调用父类初始化
    cout<<endl;
    cout<<"该电梯最大载重"<<getLimitWeght()<<"KG"<<endl;//增加显示最大载重
}
void AdvElevator::run()//封装run
{
    init();
    bool online=1;
    while(online){
        int op;
        memu();
        scanf("%d",&op);
        switch(op){
            case 1:setUpButton();break;//上行
            case 2:setDownButton();break;//下行
            case 3:online=0;break;//退出
            default:err();break;//错误
        }
        system("pause");//按任意键继续...
    }
}

main.cpp

/* *@Author: STZG *@Language: C++ */
#include<iostream>
#include"AdvElevator.h"
using namespace std;
AdvElevator Adv_Elevator(10,200);
int main()
{
    Adv_Elevator.run();
    //cout << "Hello world!" << endl;
    return 0;
}

六 运行结果
输入数据

//上行测试
1
3
1 2 10
2 3 10
2 5 10
//下行测试
2
3
5 4 10
5 3 100
3 2 100
//超重测试
1
5
2 3 100
3 4 100
3 5 100
3 6 100
4 6 100
//数据错误测试
1
3
1 1 10
3 2 100
11 12 100
-1 2 100
1 2 10
2 -3 100
2 6 100
2 4 100


七 实验心得
1.掌握单继承和多重继承的概念。
2.理解不同的继承类型:public、protected和private,掌握何时使用何种继承类型。
3.掌握类层次中构造函数的定义方式和建立对象时构造和析构次序。
4.掌握桶排序。
5.掌握封装变量基本权限设置原则。
6.掌握通过接口函数访问私有变量。
7.掌握重载类内运算符。
8.掌握重写父类函数、父类与子类之间相同函数名的调用。