C++——实验3:类的多态性的实现实验报告

本文详细描述了一次关于类的多态性实现的实验,包括实验目的、原理、使用友元函数重载运算符、动态联编、虚函数和纯虚函数的应用,以及如何通过C++编程实现学生类的多态表现,如成绩计算和输出。涉及到了STL容器multimap的使用以及迭代器的操作。
摘要由CSDN通过智能技术生成

类的多态性的实现实验报告

实验名称:类的多态性的实现                   学时安排:3

实验类别:设计性实验                       实验要求:1人1组  

 

目录

类的多态性的实现实验报告

一、实验目的

二、实验原理介绍

三、实验设备介绍

四、实验内容

五、程序清单

 5.1  头文件

   (1) Student.h

   (2) CStudent.h

   (3) FStudent.h

   (4) Report.h

5.2  源文件

   (1) Student.cpp

   (2) CStudent.cpp

   (3) FStudent.cpp

   (4) Report.cpp

5.3  主函数

六、运行结果

1、分类别显示所有学生绩点记录表

2、输入类别,显示该类别学生绩点记录表

3、输入学号,删除相应记录

4、删除所有学生的记录

5、插入新学生信息

七、实验心得


 

一、实验目的

        1.理解重载运算符的意义。

        2.掌握使用友元函数重载运算符的特点。

        3.掌握重载运算符函数的调用方法。

        4.掌握动态联编的概念。

        5.掌握虚函数和纯虚函数的使用方法。

二、实验原理介绍

        设计性实验

        具体原理请见实验内容和步骤

        实现对抽象类的继承,通过operator函数调用的形式,实现运算符的重载

三、实验设备介绍

        软件需求: Visual Studio C++或Codeblocks或Dev C++或其他C++ IDE

        硬件需求: 能够流畅运行C++ IDE的计算机一台。

四、实验内容

        某大学班级有本科生CStudent、留学生FStudent,他们的绩点计算方法如下:本科生绩点计算方法是: 英语*0.03+数学*0.04+计算机*0.03。留学生绩点计算方法:  中文*0.03+数学*0.04+计算机*0.03。成绩均为百分制,绩点总计10。

        每类学生都有学号、姓名、性别、年龄、类别等数据,类别分为本科生和留学生,各类人员使用统一接口getPoint()计算各类人员的绩点,重载<<运算符实现学生信息的输出。其次,设计一个统计并输出该班级每个人员绩点信息的报表类Report,该类提供insert接口向Report类的容器中添加学生信息,并提供print接口用于输出所有学生的学号、姓名、性别、年龄和绩点。为了方便实现查找功能,为Report类重载[]运算符的功能,下标值为学生类别,能根据类别查找出所有该类别的学生,并重载print接口,输出指定类别的学生信息。存储学生对象的容器请选用合适的STL容器。

        初始成绩表里可以先固定添加4个本科生和4个留学生信息。各个指令和对应功能如下:

        指令1:输入学号,删除相应记录;

        指令2:删除所有学生的记录;

        指令3:分类别显示所有学生绩点记录表;

        指令4:输入类别,显示该类别学生绩点记录表;

        指令-1:退出。

五、程序清单

 5.1  头文件

   (1) Student.h

#pragma once
#include <iostream>
#include <string>
using namespace std;

//学生类
class Student{
public:
    Student(string id, string name, string sex, int age, string type, double math, double computer); 
//构造函数
    virtual ~Student() = default;         //虚析构函数
    virtual double getPoint() const=0;   //计算绩点
    virtual Student *clone() const = 0;  //深拷贝

    friend ostream &operator << (ostream &os, const Student &stu);  //重载<<运算符
    friend class Report;

protected:
    string id_, name_, sex_, type_;  //学号、姓名、性别、类别
    int age_;  //年龄
    double math_, computer_;  //数学成绩、计算机成绩
};

   (2) CStudent.h

#pragma once
#include <iostream>
#include <string>
#include "Student.h"
using namespace std;

//本科生类
class CStudent:public Student {
public:
    explicit CStudent(const string &id = "", const string &name = "", const string &sex = "男", int age = 18, const string &type = "本科生", double english = 0, double math = 0, double computer = 0);  //构造函数
    double getPoint() const override;   //计算绩点
    CStudent* clone() const override;  // 深拷贝

    friend istream &operator>>(istream &is, CStudent &student);     //输入运算符重载

private:
    double english_;  //英语成绩
};

   (3) FStudent.h

#pragma once
#include <iostream>
#include <string>
#include "Student.h"
using namespace std;

//留学生类
class FStudent:public Student{
public:
    explicit FStudent(const string &id = "", const string &name = "", const string &sex = "男", int age = 18,const string &type = "留学生", double chinese = 0, double math = 0, double computer = 0);  //构造函数
    double getPoint() const override;   //计算绩点
    FStudent *clone() const override; // 深拷贝
    friend istream &operator>>(istream &is, FStudent &student);     //输入运算符重载

private:
    double chinese_;  //语文成绩
};

   (4) Report.h

#pragma once
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include "Student.h"
#include "CStudent.h"
#include "FStudent.h"
using namespace std;

//报表类
class Report{
public:
    Report();  //默认构造函数
    void insert(const Student &student);    //插入新学生(左值)
    void print();     //输出所有学生的学号、姓名、性别、年龄和绩点
    void print(const string &type);  //输出类型为type的学生的学号、姓名、性别、年龄和绩点
    void erase(const string &id);  //删除学号为id的学生记录
    void clear();     //删除所有学生记录

    auto operator[](const string &type) {return students_.equal_range(type);}  
//重载[]运算符,寻找学生类型相同的数据范围

    static void menu();  //菜单

private:
    multimap<string, unique_ptr<Student>> students_;  //存储所有学生信息
    double minPoint_(const string &type) const;  //计算所有学生中的最低绩点
    double maxPoint_(const string &type) const;  //计算所有学生中的最高绩点
};

5.2  源文件

   (1) Student.cpp

#include <iostream>
#include <iomanip>
#include "Student.h"
using namespace std;

Student::Student(string id, string name, string sex, int age, string type, double math, double computer) :id_{id},name_{name},sex_{sex},age_{age},type_{type},math_{math},computer_{computer}{}

ostream &operator << (ostream &os, const Student &stu) {
    os << setw(12) << left << stu.id_ << setw(12) << left << stu.name_
       << setw(12) << left << stu.sex_ << setw(12) << left << stu.age_
       << fixed << setprecision(2) << stu.getPoint();
    return os;
}

   (2) CStudent.cpp

#include <iostream>
#include "CStudent.h"
using namespace std;

CStudent::CStudent(const string &id, const string &name, const string &sex, int age, const string &type, double english, double math, double computer):Student(id, name, sex, age, type, math, computer),english_{english}{}

double CStudent::getPoint() const{
    return english_ * 0.03 + math_ * 0.04 + computer_ * 0.03;
}

CStudent *CStudent::clone() const{
    return new CStudent{*this};
}

istream &operator>>(istream &is, CStudent &student) {
    string id, name, sex, type; int age; double english, math, computer;
    is >> id >> name >> sex >> age >> english >> math >> computer;

    student.id_ = id;
    student.name_ = name;
    student.sex_ = sex;
    student.age_ = age;
    student.english_ = english;
    student.math_ = math;
    student.computer_ = computer;

    return is;
}

   (3) FStudent.cpp

#include <iostream>
#include "FStudent.h"
using namespace std;

FStudent::FStudent(const string &id, const string &name, const string &sex, int age,const string &type, double chinese, double math, double computer):Student(id, name, sex, age, type, math, computer),chinese_{chinese}{}

double FStudent::getPoint() const {
    return chinese_ * 0.03 + math_ * 0.04 + computer_ * 0.03;
}

FStudent *FStudent::clone() const {
    return new FStudent{*this};
}

istream &operator>>(istream &is, FStudent &student) {
    string id, name, sex, type; int age; double chinese, math, computer;
    cin >> id >> name >> sex >> age >> chinese >> math >> computer;

    student.id_ = id;
    student.name_ = name;
    student.sex_ = sex;
    student.type_ = type;
    student.age_ = age;
    student.chinese_ = chinese;
    student.math_ = math;
    student.computer_ = computer;

    return is;
}

   (4) Report.cpp

#include <iostream>
#include <string>
#include "Report.h"

Report::Report() {
    //初始成绩表里固定有4个本科生和4个留学生的信息
    students_.insert(make_pair("本科生", new CStudent("001", "红小豆", "男", 18, "本科生", 90, 95, 94)));
    students_.insert(make_pair("本科生", new CStudent("002", "李建勋", "男", 19, "本科生", 70, 65, 59)));
    students_.insert(make_pair("本科生", new CStudent("003", "胡图图", "女", 19, "本科生", 84, 93, 85)));
    students_.insert(make_pair("本科生", new CStudent("004", "派大星", "男", 20, "本科生", 71, 83, 67)));
    students_.insert(make_pair("留学生", new FStudent("101", "Tom", "男", 19, "留学生", 82, 75, 84)));
    students_.insert(make_pair("留学生", new FStudent("102", "Jerry", "女", 18, "留学生", 94, 72, 88)));
    students_.insert(make_pair("留学生", new FStudent("103", "Lucy", "女", 19, "留学生", 91, 80, 69)));
    students_.insert(make_pair("留学生", new FStudent("104", "Peter", "男", 20, "留学生", 80, 90, 100)));
}

void Report::insert(const Student &student){
    students_.insert(make_pair(student.type_, student.clone()));
}

void Report::erase(const string &id){
    for(auto i = students_.begin(); i != students_.end();)
    {
        if(i->second->id_ == id) i=students_.erase(i);
        else ++i;
    }
}

void Report::clear(){
    students_.clear();
}

double Report::minPoint_(const string &type) const{
    auto x = students_.equal_range(type);
    double minPoint = INT_MAX;
    for(auto i = x.first; i != x.second; ++i)
    {
        if (i->second->getPoint() < minPoint)
        {
            minPoint = i->second->getPoint();
        }
    }
    return minPoint;
}

double Report::maxPoint_(const string &type) const {
    auto x= students_.equal_range(type);
    double maxPoint = 0;
    for (auto i = x.first; i != x.second; ++i)
    {
        if (i->second->getPoint() > maxPoint)
        {
            maxPoint = i->second->getPoint();
        }
    }
    return maxPoint;
}

void Report::print() {
    cout << string(52, '-') << endl;    //分割线
    print("本科生");   //输出本科生信息
    cout << string(52, '-') << endl;
    print("留学生");   //输出留学生生信息
    cout << string(52, '-') << endl;
}

void Report::print(const string &type){
    cout << "类别:" << type << endl;          //输出学生类别
    cout << setw(13) << left << "学号" << setw(12) << left << "姓名"
         << setw(12) << left << "性别" << setw(14) << left << "年龄" << "绩点" << endl;      //输出属性值
    for (auto i = (*this)[type].first; i != (*this)[type].second; ++i)
    {
        cout << *i->second << endl;     //输出该类所有学生信息
    }
    if ((*this)[type].first != (*this)[type].second)
    {
        cout << fixed << setprecision(2)
             << "最低绩点:" << minPoint_(type) << endl
             << "最高绩点:" << maxPoint_(type) << endl;   //输出该类学生的最高、最低绩点
    }
}

void Report::menu(){
 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED);
    cout << "--------------------------------------------------" << endl
         << "                    操作菜单项                      " << endl
         << "          输入1:输入学号,删除相应记录                  " << endl
         << "          输入2:删除所有学生的记录                     " << endl
         << "          输入3:分类别显示所有学生绩点记录表             " << endl
         << "          输入4:输入类别,显示该类别学生绩点记录表         " << endl
         << "          输入5:插入新学生信息                        " << endl
         << "          输入-1:退出                               " << endl
         << "--------------------------------------------------" << endl;
 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);
}

5.3  主函数

#include <iostream>
#include <string>
#include <Windows.h>
#include "Student.h"
#include "CStudent.h"
#include "FStudent.h"
#include "Report.h"
using namespace std;

int main(){
    Report report;
    int opt;
    do{
        Report::menu();
        cin >> opt;
        if (opt == 1)
        {
            SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_GREEN); //设置字颜色为绿色
            cout << "请输入需要删除的学生学号:";
            SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);   //设置字颜色为白色
            string id;
            cin >> id;
            report.erase(id);
        }
        else if (opt == 2)
        {
            report.clear();
        }
        else if (opt == 3)
        {
            report.print();
        }
        else if (opt == 4)
        {
            SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_GREEN); //设置字颜色为绿色
            cout << "请输入需要查看学生绩点的类别:";
            SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);   //设置字颜色为白色
            string type;
            cin >> type;
            report.print(type);
        }
        else if (opt == 5)
        {
            SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_GREEN); //设置字颜色为绿色
            cout << "请输入需要添加的学生类型:" << endl;
            string z;
            cin >> z;
            if (z == "本科生")
            {
                SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_GREEN); //设置字颜色为绿色
                cout << "请输入需要添加的学生信息(学号、姓名、性别、年龄、英语成绩、数学成绩、计算机成绩)" <<endl;
                SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);   //设置字颜色为白色
                CStudent student;
                cin >> student;
                report.insert(student);
            }
            else if (z == "留学生" )
            {
                SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_GREEN); //设置字颜色为绿色
                cout << "请输入需要添加的学生信息(学号、姓名、性别、年龄、语文成绩、数学成绩、计算机成绩)" <<endl;
                SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);   //设置字颜色为白色
                FStudent student;
                cin >> student;
                report.insert(student);
            }
        }
    } while (opt != -1);
    return 0;
}

六、运行结果

1、分类别显示所有学生绩点记录表

d3d232d8245143f3bd477e87791b43b0.png

2、输入类别,显示该类别学生绩点记录表

c68b94c8b1324143aaf97e315cd20c72.png

3、输入学号,删除相应记录

a29287adb92949838320333270d4f3ce.png

4、删除所有学生的记录

8750e80ec442486aa939a9697843222a.png

5、插入新学生信息

71cf20fc26374429ad5046e7c3b9bb0a.png

七、实验心得

        通过本次实验,我利用friend友元函数实现了输出运算符<<、数组下标运算符[]以及输入运算符>>的重载,使得运算符拥有了我们想要的功能需求;利用继承、virtual虚函数和指针完成了多态实现,如计算绩点时在CStudent、FStudent两个类中对基类的double getPoint()函数进行重写可以实现不同的运算效果。同时,我也熟悉了纯虚函数的使用,明白了其本身是没有意义的,当其被各个派生类继承下来时有了不同的含义。

        另外,我对c++中STL迭代器有了进一步的认识。由于本次实验我们需要区分学生类型进行分类输出,所以选择multimap容器,将学生类型作为主键进行存储和操作(multimap容器保存有序的键/值对,可以保存重复的元素)。在实验中,利用了迭代器本身拥有的eraser(),clear(),insert()实现删除、清空、插入操作,利用equal_range(type)实现对容器内type键的区间查找(返回值为一对迭代器,返回first和last之间等于type的元素区间)。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阮阮的阮阮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值