C++用cin接收不了中文字符、继承的实现原理、菱形继承的解决方法

今天写了一道题,就涉及到了3个问题,可谓是收获颇丰。话不多说,先上题目:
(1)定义人员类Person:
公有成员:姓名(Name);
保护成员:性别(Gender),年龄(Age);
实现构造函数和析构函数
(2) 从人员类Person派生学生记录类StudentRecord:
添加公有成员:学号(Number),班级(ClassName),
添加静态公有成员:学生总人数(TotalCount);
添加保护成员:平均成绩(Score);
实现构造函数和析构函数。
(3) 从人员类Person派生教师记录类TeacherRecord:
添加公有成员:学院(CollegeName),系(DepartmentName);
添加保护成员:教龄(Year);
实现构造函数和析构函数。
(4)从学生记录类StudentRecord和教师记录类TeacherRecord派生学生助教类TeachingAssistant:
添加公有成员:辅导课程(LectureName);
实现公有函数:显示人员信息(Show),屏幕打印 姓名,性别,年龄,学号,班级,学生总人数,平均成绩,学院,系,教龄,辅导课程。
实现构造函数和析构函数。为检验类间结构设计是否正确,设计函数void SetName(String name)实现更改一名助教的姓名的功能。
创建一个助教类的对象
助教
姓名 性别 年龄 学号 班级 平均成绩 学院 系 教龄 辅导课程
郑七 男 22 2010123 软20101 89 信息 软件 1 数据结构
显示其信息。
调用更改姓名的函数,更改其姓名为“郑八”,并再次显示其信息。

输入

输出
显示构造的信息和更改前和更改后的助教信息

助教类由学生类和教师类派生而来,学生类和教师类又都是从人员类派生而来。故这是一个菱形继承问题,为了避免助教类继承两份人员类数据,要使学生类和教师类的继承方式为虚继承(virtual)。

由派生类的实现原理,创建一个派生类对象时编译器先创建出一个基类对象,并调用基类构造函数,再创建一个派生类对象,继承基类里的数据,并调用派生类的构造函数。所以我们给这些类写构造函数的时候只用给类中原本就有的成员初始化,因为从基类继承来的成员已经在创建基类对象时就调用基类构造函数初始化好了。这个过程联系生活也很好理解,先有爸爸,才有儿子。但是销毁对象时析构函数的调用顺序和构造函数的调用恰恰相反,C++敢情是出悲情剧,白发人送黑发人。

至于学生类里的公有静态成员学生总人数,我个人认为应该是初始化为0,然后在构造函数里,每创建一个学生,就自增1,在析构函数里,每销毁一个学生,就自减1。这样才能实现实时记录学生总人数。

我本来打算在构造函数里用cin实时接收数据,但是编译运行时我发现C++无法做到接收中文字符,我再看一眼题目,发现原来题目没有输入信息。好吧,这个题目就是坑啊,根本不是让我们真正去思想实现人员管理系统的功能。既然如此,那就只好把数据用C++的字符串流istringsteam来进行传输了。

另外,我认为,每个类都应该有一个自己的Show函数,来显示成员的信息,要真考虑起来,还有…太多了一言难尽,等到真正去实现的时候再考虑吧,眼下只是要把这题写出来通过OJ测试,所以在此处代码不赘述了。

接下来附上已提交且通过测试的代码(我认为真正正经去实现的话应该的写法被我注释起来了):
必要的数据准备。

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

istringstream is_1("郑七 男 22");
istringstream is_2("2010123 软20101 89");
istringstream is_3("信息 软件 1");
istringstream is_4("数据结构");

人员类的实现。

class Person
{
public:
    string Name;
    Person()
    {
        // cin>>Name>>Gender>>Age;
        is_1>>Name>>Gender>>Age;
        cout<<"Person"<<Name<<"constructed"<<endl;
    }
    ~Person()
    {
        cout<<"Person"<<Name<<"destructed"<<endl;
    }
protected:
    string Gender;
    int Age;
};

**学生类的实现。**因为没有什么特殊要求,采用public继承。如果希望子类不能随意修改父类的公有成员(即通过对象直接访问),可以采用protected继承。

class StudentRecord:virtual public Person
{
    public:
    string Number;
    string ClassName;
    static int TotalCount;
    StudentRecord()
    {
        // cin>>Number>>ClassName>>Score;
        is_2>>Number>>ClassName>>Score;
        TotalCount++;
        cout<<"Student"<<Name<<"constructed"<<endl;
    }
    ~StudentRecord()
    {
        TotalCount--;
        cout<<"Student"<<Name<<"destructed"<<endl;
    }
    protected:
    int Score;
};
int StudentRecord::TotalCount=0;

**教师类的实现。**这里也没什么特殊要求,故采用public继承。

class TeacherRecord:virtual public Person
{
public:
    string CollegeName;
    string DepartmentName;
    TeacherRecord()
    {
        // cin>>CollegeName>>DepartmentName>>Year;
        is_3>>CollegeName>>DepartmentName>>Year;
        cout<<"teacher"<<Name<<"constructed"<<endl;
    }
    ~TeacherRecord()
    {
        cout<<"teacher"<<Name<<"destructed"<<endl;
    }
protected:
    int Year;
};

助教类的实现。 这同样没有什么特殊要求,采用public继承。

class TeachingAssistant:public StudentRecord,public TeacherRecord
{
    public:
    string LectureName;
    TeachingAssistant()
    {
        // cin>>LectureName;
        is_4>>LectureName;
        cout<<"teachingassistant"<<Name<<"constructed"<<endl;
    }
    ~TeachingAssistant()
    {
        cout<<"teachingassistant"<<Name<<"destructed"<<endl;
    }
    void Show()
    {
        cout<<"Name:"<<Name<<" Gender:"<<Gender<<" Age:"<<Age<<" Number:"<<Number
        <<" ClassName:"<<ClassName<<" TotalCount:"<<TotalCount<<" Score:"<<Score
        <<" CollegeName:"<<CollegeName<<" DepartmentName:"<<DepartmentName
        <<" Year:"<<Year<<" LectureName:"<<LectureName<<endl;
    }
    void SetName(string name)
    {
        Name=name;
    }
};

最后是main函数。

int main()
{
    TeachingAssistant item;
    item.Show();
    item.SetName("郑八");
    item.Show();
    return 0;
}

最后的最后,附上正确运行结果。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

赴星辰大海

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

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

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

打赏作者

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

抵扣说明:

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

余额充值