上机报告3(7 多态性和运算符重载,8 继承与派生,9 C++ IO流)

一、 上机目的和要求

a. 实验七

  1. 了解多态性;
  2. 掌握算术运算符和关系运算符的重载;
  3. 掌握运算符重载的方法;
  4. 掌握作为成员函数的运算符重载和作为友元函数的运算符重载的不同特点。

b. 实验八

1. 理解继承的含义,掌握派生类的定义和实现方法。
2. 理解公有继承下基类成员对派生类成员和派生类对象的可见性,能正确地使用继 承层次中的各种类成员。
3. 理解保护成员在继承中的作用,能够在适当的时候使用保护成员以便派生类成员 可以访问基类的部分非公开成员。
4. 理解虚基类在类的继承层次中的作用,虚基类的引入对程序运行时的影响,能够 对使用虚基类的简单程序写出程序结果。

c. 实验九

  1. 掌握文件流的打开、关闭及使用的使用方法;
  2. 了解文本文件流与二进制文件流在操作上的区别。

二、 基本知识和原理

a. 实验七

概念理解

多态是指类族中具有相似功能的不同函数使用同一名称来实现,从而可以使用相同的调用方式来调用这些具有不同功能的同名函数。
C++中的多态的实现形式:函数重载、运算符重载、虚函数等。函数重载是指同一个函数可以操作于不同类型的对象:运算符重载是对已有的运算符赋予多重含义,使用已有运算符对用户自定义类型(比如类)进行运算操作,运算符重载实际上是函数重载;虚函数是实现类族中定义于不同类中的同名成员函数的多态行为。
多态从实现的角度可以分为两类:编译时的多态和运行时的多态,前者是在编译过程中确定了同名操作的具体操作对象,而后者则是在程序运行过程中才动态地确定所针对的具体对象。这种确定操作的具体对象的过程就是联编。
编译时的多态通过静态联编解决,如函数重载或运算符重载,它们在编译、链接过程中,系统就可以根据类型匹配等特征确定程序中操作调用与执行代码的关系,即确定了某一个同名标识到底要调用哪一段程序代码。
运行时的多态通过动态联编实现,虚函数是实现动态联编的基础,若定义了虚函数就可以通过基类指针或引用实现,执行时会根据指针指向的对象所属的类,决定调用哪个函数。虚函数具有继承性,其本质不是重载声明而是覆盖。
纯虚函数是在基类中说明的虚函数,它在该基类中可以不给出函数体,要求各派生类根据实际需要编写自己的函数体。带有纯虚函数的类是抽象类,抽象类的主要作用是通过它为一个类族建立一个公共的接口,使它们能够更有效地发挥多态特性。

2.运算符重载

运算符重载是指同样的运算符可以施加于不同类型的操作数上面,使同样的运算符作用于不同类型的数据导致不同类型的行为。
运算符重载的实质就是函数重载。在实现过程中,首先把指定的运算符表达式转化为对运算符函数的调用,运算对象转化为函数的形参,然后根据实参的类型来确定需要调用的函数,这个过程是在编译过程中完成的。
运算符重载的形式有两种,重载为类的成员函数和重载为类的友元函数。其一般语法为:
<函数类型>operator<运算符>(<参数表>)
{
<函数体;>
}
运算符重载为类的成员函数和运算符重载为类的友元函数,其语法基本相同,但参数的使用有所不同。
在运算符重载为类的成员函数时,对于前置单目运算符S,如果要重载S为类X的成员函数,用来实现表达式S xobj,其中xobj是类X的对象,经过重载后,表达式S xobj就相当于函数的调用xobj.operatorS()。对于后置运算符“++”和“–”,如果要将它们重载为类X的成员函数,用来实现xobj++和xobj–就相当于函数调用xobj.operator++(0)和obj.operator–(0)。
对于双目运算符D,如果要重载为类X的成员函数,实现表达式xobj1 D xobj2,则函数只有一个形参,形参的类型是xobj2所属的类型,经过重载后,表达式xobj1 D xobj2相当于函数调用xobj1.operator D(xobj2)。
在运算符重载为类的友元函数时,对于前置单目运算符S,如果要重载S为类X的友元函数,用来实现表达式S xobj,其中xobj是类X的对象,经过重载后,表达式S xobj就相当于函数的调用operator S(xobj)。对于后置运算符“++”和“–”,如果要将它们重载为类X的友元函数,用来实现xobj++或xobj–。重载后表达式xobj++和xobj–就相当于函数调用operator++(xobj,0)和operator–(xobj,0)。
对于双目运算符D,如果要重载为类X的成员函数,实现表达式xobj1 D xobj2,则函数有两个形参,经过重载后,表达式xobj1 D xobj2相当于函数调用xobj1.operator D(xobj2)。对于运算符重载为友元函数的情况,要在函数类型说明之前使用friend关键字来声明。
运算符重载的规则如下:
(1)C++中运算符除少数几个外,其余全部可重载,但只能重载C++中已有的运算符;
(2)重载之后的运算符的优先级和结合性都不改变;
(3)不能改变原运算符操作数的个数;
(4)不能改变运算符对预定义类型数据的操作方式。

b. 实验八

1. 继承

继承是C++语言的一种重要机制,它允许在已定义的类的基础上产生新类。
从已定义类产生新类的过程称为派生。已存在的用来派生新类的类为基类,又称父类。从已存在的类派生出的新类称为派生类,又称为子类。如,从哺乳动物类派生出狗类,哺乳动物是父类,狗是子类;从汽车类派生出轿车类,汽车是父类,轿车是子类。
在C++语言中,一个派生类可以从一个基类派生,也可以从多个基类派生。从一个基类派生的继承称为单继承,从多个基类派生的继承称为多继承。

2. 派生类的定义格式

(1)单继承的定义格式
class<派生类名>:<继承方式><基类名>
{
<派生类新定义成员>
};
其中:
基类名是已经定义类的名称。派生类名是新定义的一个类的名字,它是从基类中派生的;
派生类是按指定继承方式从基类派生的,继承方式常用的有如下3种:
public 表示公有继承
private 表示私有继承
protected 表示保护继承
在单继承中,每个类可以有多个派生类,但是每个派生类只能有一个基类,从而形成树形结构。
(2)多继承的定义格式
class<派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,……
{
<派生类新定义成员>
};
其中继承方式1、继承方式2、……是3种继承方式public、private和protected之一。
多继承与单继承的主要区别从定义格式上看,主要是多继承的基类多于一个。

3. 派生类的3种继承方式

由下表来理解3种继承方式的各自特点。
基类 基类
内部函数 基类对象 private继承方式 protected继承方式 public继承方式
派生类
内部函数 派生类
对象 派生类
内部函数 派生类
对象 派生类
内部函数 派生类
对象
private成员 可访问 不可访问 不可访问 不可访问 不可访问 不可访问 不可访问 不可访问
protected成员 可访问 不可访问 可访问,转为private 不可访问 可访问,转为protected 不可访问 可访问,保持protected 不可访问
public成员 可访问 可访问 可访问,转为private 不可访问 可访问,转为protected 不可访问 可访问,保持public 可访问

4. 派生类和基类的关系

任何一个类都可以派生出很多个新类,派生类也可以再派生出新类,因此,基类和派生类是相对而言的。一个基类可以是另一个基类的派生类,这样便形成了复杂的继承结构,出现了类的层次。一个基类派生出一个派生类,它又做另一个派生类的基类,则原来基类为该派生类的间接基类。
基类和派生类之间的关系可以有以下3种描述。
(1)派生类是基类的具体化
类的层次通常反映了客观世界中某种真实的模型。基类是对若干个派生类的抽象,而派生类是基类的具体化。基类抽取了它的派生类的公共性,而派生类通过增加行为将抽象类变为某种有用的类型。
(2)派生类是基类定义的延续
先定义一个抽象基类,该基类中有些操作并未实现,然后定义非抽象的派生类,实现抽象基类中定义的操作。例如虚函数就属于此类情况。这时派生类是抽象的基类的实现,既可以看成是基类定义的延续,这也是派生类的一种常用方法。
(3)派生类是基类的组合。
在多重继承时,一个派生类有多于一个的基类,这时派生类将是所有基类行为的组合。

5. 虚基类的引入和说明

引进虚基类的真正目的是为了解决二义性的问题。
声明虚基类的方法是:在定义虚基类的直接派生类时,用关键字virtual引出基类名。

6. 二义性问题

一般来说,在派生类中对基类成员的访问应该是唯一的,但是由于多继承情况下,可能造成对基类中某个成员的访问出现不唯一的情况,则称为对基类成员访问的二义性问题。
由多重继承引起的二义性问题是指:当一个派生类从多个基类派生,而这些基类又有一个共同的基类,则对该基类中说明的成员进行访问时,可能会出现二义性。

7. 派生类构造函数和析构函数

(1) 派生类的对象的数据成员是由基类中说明的数据成员和派生类中说明的数据成员共同构成。将派生类的对象中由基类说明的数据成员和操作所构成的封装体称为基类子对象,它由基类中的构造函数进行初始化。
(2) 构造函数不能够被继承,因此派生类的构造函数必须通过调用基类的构造函数来初始化基类子对象。所以在定义派生类的构造函数时除了对自己的数据成员进行初始化外,还必须负责调用基类构造函数使基类的数据成员得以初始化,如果派生类中还有子对象时,还应该包含对子对象初始化的构造函数。
(3) 派生类构造函数的一般格式如下
(派生类名)(<派生类构造函数总参数表>):<基类构造函数>(<参数表1>),<子对象名>(<参数表2>)
{
<派生类中数据成员初始化>
}
(4) 派生类构造函数的调用顺序如下:
基类的构造函数–>子对象类的构造函数–>派生类的构造函数
(5) 当对象被删除时,派生类的析构函数被执行。由于析构函数不能被继承,因此在执行派生类的析构函数时,基类的析构函数也将被调用。执行顺序是先执行派生类的析构函数,再执行基类的析构函数,其顺序与执行构造函数时的顺序正好相反。
(6) 派生类构造函数使用中应注意的问题:
派生类构造函数的定义中可以省略对基类构造函数的调用,其条件是在基类中必须有默认的构造函数或者根本没有定义构造函数。当然,如果基类中没有定义构造函数,那么派生类根本不必负责调用基类构造函数。
当基类的构造函数使用一个或多个参数时,则派生类必须定义构造函数,提供将参数传递给基类构造函数的途径。在某些情况下,派生类构造函数的函数体可能为空,仅起到参数传递作用。

c. 实验九

具体原理(略)

三.程序算法分析及实现(代码)(或问题解答)

a. 实验七

【实例1】调试chapter10例子程序。

#include<iostream>
using namespace std;
 class time24 //a simple class
 {    
     public:
         time24(int h = 0, int m = 0, int s = 0);
         void set_time(int h, int m, int s);
         void get_time(int &h, int &m, int &s) const;
         time24 operator+(int secs) const;
         time24 operator+(const time24& t ) const;
         time24 operator++();                //prefix前缀(我想是之前时间)
         time24 operator++(int);             //postfix后缀(我想是之后时间)
    private:
        int hours;   //0 to 23
        int minutes;   //0 to 59
        int seconds;  //0 to 59
 };

 //Constructor
 time24::time24(int h,int m,int s):
         hours(h),minutes(m),seconds(s)
         {}

//Mutator function
void time24::set_time(int h,int m,int s)
{
    hours = h;
    minutes = m;
    seconds = s;
}

//Inspector function
void time24::get_time(int &h,int &m,int &s) const
{
    h = hours;
    m = minutes;
    s = seconds;
}

//Overload + operators
time24 time24::operator+(int secs) const
{
    //读秒计数
    time24 temp;
    temp.seconds = seconds + secs;
    temp.minutes = minutes + temp.seconds / 60;
    temp.seconds %= 60;
    temp.minutes %= 60;
    temp.hours %= 24;
    return temp;
}

time24 time24::operator+(const time24& t) const
{
    //读秒计数
    time24 temp;
    int secs = t.hours * 3600 + t.minutes * 60 + t.seconds;
    temp.seconds = seconds + secs;
    temp.minutes = minutes + temp.seconds / 60;
    temp.seconds %= 60;
    temp.hours = hours + temp.minutes / 60;
    temp.minutes %= 60;
    temp.hours %= 24;
    return temp;//return the new time
}
int main()
{
    int h, m, s;
    time24 start_time(23, 0, 0);
    time24 elapse_time(1, 2, 3);
    time24 finish_time;

    finish_time = start_time + elapse_time ;
    finish_time.get_time(h, m, s);
    cout << "Finish Time is  " << h << ":" << m << ":" << s << endl;
    return 0;
}

【实例2】运算符重载。调试并运行以下程序,注意观察程序设计的基本思路和关键知识点。程序实现的基本功能:

(1)定义分数类Franc,包括分子和分母两个成员;
(2)定义成员函数void FranSimp,化简分数;
(3)定义成员函数void display,显示分数信息;
(4)定义成员函数Franc operator+(Franc &f),实现分数的加法运算;
(5)定义成员函数Franc operator++,实现前置++运算;
(6)定义成员函数bool operator==(Franc &f),实现两个分数相等的判断;
完善【实例2】程序,写出实现以下功能的代码并上机调试。
(1)编写成员函数实现两个分数的相减运算,并上机调试。
编程提示:
函数的原型为Franc operator-(Franc &f);
实现算法暂不考虑化简,返回结果值。
(2)编写成员函数实现后置运算符“–”运算,并上机调试。
编程提示:
函数的原型为Franc operator–(int);
实现算法是先将当前的分数保存,再将分数减1,然后再返回保存的分数。
(3)修改主函数,使其能显示上述运算符的执行情况,记录运行结果。

#include<iostream>
using namespace std;
 class Franc //a simple class
 {    
     public:
         Franc(int n=0 , int d=0 );
         void FranSimp();                     //化简分数
         void display();                      //显示分数
         Franc operator+(Franc &f);           //实现分数的加法运算
         Franc operator-(Franc &f);           //实现分数的减法运算
         Franc operator++();                  //实现前置++运算
         Franc operator--(int a);                  //实现后置置--运算
         bool operator==( Franc &f);              //实现两个分数相等的判断
    
    private:
        int numerator;  //分子
        int denominator;   //分母
 };

 //Constructor
 Franc::Franc(int n,int d):
         numerator(n),denominator(d)
         {}

//Mutator function
void Franc::FranSimp()
{
    int r;
    int x = numerator, y = denominator;

    r = x % y;
    while (r) // 求最大公约数
    {
        x=y;
        y=r;
        r = x % y;
    }
    numerator /= y ;
    denominator /= y;
}

//Inspector function
void Franc::display()
{
    cout << "This Franc is: " << numerator << "/" << denominator << " " << endl;
}

//Overload + operators
Franc Franc :: operator+(Franc &f)
{
    Franc temp;
    temp.numerator = f.numerator * denominator + numerator * f.denominator;
    temp.denominator = denominator * f.denominator;
    temp.FranSimp();
    return temp;
}

Franc Franc :: operator-(Franc &f)
{
    Franc temp;
    temp.numerator = numerator * f.denominator - f.numerator * denominator;
    temp.denominator = denominator * f.denominator;
    temp.FranSimp();
    return temp;
}

Franc Franc :: operator++()
{
    Franc temp;
    temp.numerator = numerator;
    temp.denominator = denominator;
    temp.numerator += denominator;
    numerator += denominator;
    temp.FranSimp();
    return temp;
}

Franc Franc :: operator--(int a)
{
    Franc temp;
    temp.numerator = numerator;
    temp.denominator = denominator;
    temp.numerator -= denominator;
    numerator -= denominator;
    temp.FranSimp();
    return temp;
}

bool Franc::operator==( Franc &f)
{
    f.FranSimp();
    Franc t;
    t.numerator = numerator;
    t.denominator = denominator;
    if (t.numerator != f.numerator || t.denominator !=f.denominator) return false;
    return true;
}
int main()
{
    Franc Franc_a(12,24);
    Franc Franc_b(1,2);
    Franc Franc_c(3,2);
    Franc Franc_d(1,1);

    Franc_a.display();
    if(Franc_b == Franc_a)
    {
        ++Franc_b;
        if(Franc_b==Franc_c)
            cout << "*********************************over*********************************" << endl;
        Franc_b--;
        if ((Franc_c - Franc_d) == Franc_b)
            cout<< "*********************************really over*********************************" << endl;        
    }else
        cout << "wrong" << endl;
    return 0;
}

b. 实验八

【实例1】编写一个学生和教师数据输入和显示程序,学生数据有编号、姓名、班级和成绩,教师数据有编号、姓名、职称和部门。要求将编号、姓名的输入和显示设计成一个类Person,并作为学生数据操作类Student和教师数据操作类Teacher的基类。

1) 上机运行该程序。
2) 为Teacher类编写系别和职称的输入/输出函数;为Student类编写班级和成绩的输入/输出函数。

#include<iostream>
using namespace std;
class Person
{
protected:
    char name[10];
    int number;
public: 
    void input()
    {
        cout << "name: " << endl;
        cin >> name;
        cout << "number: " << endl;
        cin >> number;
    }
    void show()
    {   
          cout<<" name: "<<name<<endl;
        cout<<" number: "<<number<<endl;
    }
};
class Student :public Person
{
    private:
    char s_class[10];
    float score;

    public:
    void input()
    { 
        cout<<"This student: "; 
        Person::input();
        cout<<"s_class: "; 
        cin>>s_class;
        cout<<" score: "; 
        cin>>score;
    }   
    void show()
    {
        Person::show();
        cout<<" s_class: "<<s_class<<endl;
        cout<<" score: "<<score<<endl;
    }
};
class Teacher :public Person
{
    private:
    char dept[10];
    char title[6];

    public:
     void input()
    { 
        Person::input();
        cout<<" dept: "; 
        cin>>dept;
        cout<<" title: "; 
        cin>>title;
    }   
    void show()
    {
        cout<<"This Teacher: "; 
        Person::show();
        cout<<" dept: "<<dept<<endl;
        cout<<" title: "<<title<<endl;
    }
};
int main()
{
    Student s1;
    Teacher t1;
    cout<<"Please input the name and the number of a student:"<<endl;
    s1.input();
    s1.show();

    cout<<"Please input the name and the number of a teacher:"<<endl;
    t1.input();
    t1.show();
    return 0;
}

【实例2】给出下面程序的执行结果

#include<iostream>
using namespace std;
class A
{
public: 
    A (int i,int j) 
    {   a=i; 
        b=j;
    }
    void move(int x,int y) 
    {   a+=x;
        b+=y;
    }
    void show()
    {   cout<<"("<<a<<","<<b<<")"<<endl;
    }
private:
    int a,b;
};
class B : public A
{
public: 
    B(int i,int j,int k,int l) : A(i,j) 
    {   x=k; 
        y=l;
    }
    void show()
    {   cout<<x<<","<<y<<endl;
    }
    void fun() 
    {   move(3,5);
    }
    void f1() 
    {   A::show();
    }
private:
    int x,y;
};
int main()
{
    A a(1,2);
    a.show();
    B b(3,4,5,6);
    b.fun();
    b.show();
    b.f1();
    return 0;
}

【实例3】指出下面程序的错误并改正之。

#include<iostream>
using namespace std;
class Point
{   int x,y;
public: 
    Point (int xx,int yy)
    {   x=xx;
        y=yy;
    }
    void add(int xa,int ya)
    {   x+=xa;
        y+=ya;
    }
    void show()
    {   cout<<"x="<<x<<","<<"y="<<y<<endl;
    }
};
class Rect:public Point
{   int len,width;
public: 
    Rect (int x,int y,int ll,int ww) : Point (x,y)
    {
        len=ll;
        width=ww;
    }
    void showRect()
    {   show();
        cout<<"length="<<len<<","<<"width="<<width<<endl;
    }
};
int main()
{   Rect rect(0,2,3,6);
    rect.add(4,5);
    rect.showRect();
    return 0;
}
3.
#include<iostream>
using namespace std;
class A
{
    int i1;
    public: 
    void f1();
    private:
    int j1;
};
class B : public A
{
    int i2;
    public: 
    void f2();
    private:
    int j2;
};
class C : public B
{
    int i3;
    public: 
    void f3();
    private:
    int j3;
};

int main()
{
    A a;
    B b;
    C c;
    return 0;
}

回答下列问题:
(1) 派生类B中成员函数f2能否访问基类A中的成员函数f1和数据成员i1、j1?
(2) 派生类B的对象b能否访问基类A中的成员函数f1和数据成员i1、j1?
(3) 派生类C中成员函数f3能否访问直接基类B中的成员函数f2和数据成员j2?能否访问间接基类A中的成员函数f1和数据成员i1、j1?
(4) 派生类C的对象c能否访问直接基类B中的成员函数f2和数据成员j2?能否访问间接基类A中的成员函数f1和数据成员i1、j1?
(5) 从对(1)~(4)问题的回答可以得出对公有继承有什么结论?(在公有继承时,派生类的成员函数可以访问基类中的公有成员和保护成员,派生类的对象仅可以访问基类中的公有成员。)

  1. 派生类B中成员函数f2能访问基类A中的成员函数f1,能访问数据成员i1、不能访问j1。
  2. 派生类B的对象b不能访问基类A中的成员函数f1,能访问数据成员i1、不能访问j1。
  3. 派生类C中成员函数f3能访问直接基类B中的成员函数f2和不能访问数据成员j2,能问间接基类A中的成员函数f1和数据成员i1、不能访问j1。
  4. 派生类C的对象c不能访问直接基类B中的成员函数f2,能访问数据成员j2,不能访问间接基类A中的成员函数f1和数据成员j1,能访问i1.
  5. 在公有继承时,派生类的成员函数可以访问基类中的公有成员和保护成员,派生类的对象仅可以访问基类中的公有成员。

1. 定义一个哺乳动物类Mammal,并从中派生出一个狗类Dog.

下面给出Mammal类的定义,要求:
(1) 添加Dog类的颜色数据成员,访问属性为私有,通过SetColor和GetColor成员函数来对颜色进行设置和获取。
(2) 分别为基类和派生类添加相应的构造函数(有参、无参)和析构函数,并进行测试。

#include<iostream>
using namespace std;
class Mammal
{
protected:
    int itsAge;
    int itsWeight;
public:
    int GetAge(){return itsAge;}
    void SetAge(int age) {itsAge=age;}
    int GetWeight() { return itsWeight;}
    void SetWeight(int weight) {itsWeight= weight;} 
};
class Dog : public Mammal
{
    //定义Dog类的数据成员和成员函数
    private:
        char color[20];
    public:
        void SetColor(char* thecolor){
            for (int i = 0; *thecolor != NULL;i++)
                color[i] = *thecolor++;
        };
        char* GetColor(){
            return color;
        };
        void show(){
            int age=GetAge();
            int weight=GetWeight();
            char *color = GetColor();

            cout << "the age is " << age << endl;
            cout << "the weight is " << weight << endl;
            cout << "the color is " << color << endl;
        }
};

int main()
{
    Dog silly_dog;
    int age,weight;
    char color[20];

    cout << "input the age: " << endl;
    cin >> age;
    silly_dog.SetAge(age);

    cout << "input the weight: " << endl;
    cin >> weight;
    silly_dog.SetWeight(weight);
    
    cout << "input the color: " << endl;
    cin >> color;
    silly_dog.SetColor(color);

    silly_dog.show();

    return 0;
}

2. 设计人员基类Person。

其成员包括:
数据成员:姓名(字符数组)、性别(字符数组)和年龄(整型)
成员函数:SetPerson,设置人员数据函数;
DisplayPerson,显示人员数据函数;
设计派生类1:Teacher,派生于Person。新增成员包括:
数据成员:职称(字符数组)、教研室(字符数组)和所授课程(字符数组)
成员函数:SetTeacher,设置数据成员函数;
DisplayTeacher,显示数据成员函数;
设计派生类2:Student,派生于Person。新增成员包括:
数据成员:专业(字符数组)、班级(字符数组)和类别(int)
其中类别取值:1(本科生)、2(硕士生)、3(博士生)
成员函数:SetStudent,设置数据成员函数;
DisplayStudent,显示数据成员函数;
设计派生类3:PostDoctor(博士后),多重继承于Student与Teacher。新增成员包括:
数据成员:无
成员函数:SetPostDoctor,设置数据成员函数;
DisplayPostDoctor,显示数据成员函数;
主函数:
输入并输出一个教师、一个本科生、一个博士后数据。

#include<iostream>
using namespace std;
class Person
{
protected:
    char name[10];
    char sex[10];
    int age;

public: 
    void SetPerson()
    {
        cout << "name: " << endl;
        cin >> name;
        cout << "sex: " << endl;
        cin >> sex;
        cout << "age: " << endl;
        cin >> age;
    }
    void DisplayPerson()
    {   
          cout<<" name: "<<name<<endl;
        cout<<" sex: "<<sex<<endl;
        cout<<" age: "<<age<<endl;
    }
};
class Teacher :public Person
{
    private:
    char dept[10];
    char title[6];
    char course[20];

    public:
    void SetTeacher()
    { 
        Person::SetPerson();
        cout<<" dept: "; 
        cin>>dept;
        cout<<" title: "; 
        cin>>title;
        cout<<" course: "; 
        cin>>course;
    }   
    void DisplayTeacher()
    {
        cout<<"This Teacher: "; 
        Person::DisplayPerson();
        cout<<" dept: "<<dept<<endl;
        cout<<" title: "<<title<<endl;
        cout<<" course: "<<course<<endl;
    }
};
class Student :public Person
{
    private:
    char majior[10];
    int s_class;
    int type;

    public:
    void SetStudent()
    { 
        cout<<"This student: "; 
        Person::SetPerson();
        cout<<"majior: "; 
        cin>>majior;
        cout<<"s_class: "; 
        cin>>s_class;
        cout<<" type: "; 
        cin>>type;
    }   
    void DisplayStudent()
    {
        Person::DisplayPerson();
        cout<<" majior: "<<majior<<endl;
        cout<<" s_class: "<<s_class<<endl;
        cout<<" type: "<<type<<endl;
    }
};
class PostDoctor :public Student,public Teacher
{
    public:
    void SetPostDoctor()
    { 
        Student::SetStudent();
        Teacher::SetTeacher();
    }   
    void DisplayPostDoctor()
    {
        Student::DisplayStudent();
        Teacher::DisplayTeacher();
    }
};
int main()
{
    PostDoctor bi_phd;
    Student s_b;
    Teacher t_a;
    t_a.SetTeacher();
    s_b.SetStudent();
    bi_phd.SetPostDoctor();

    t_a.DisplayTeacher();
    s_b.DisplayStudent();
    bi_phd.DisplayPostDoctor();

    return 0;
}

c. 实验九

1:编一个程序用于复制文本文件

#include<iostream>
#include<fstream>
using namespace std;
int main()
{
char s[40];
char s1[40];
cout<<"input the file name "<<endl;
cin>>s;
//输入文件名的格式为如下格式:
//G:\\my_users\\users\\abc.txt
ifstream input;
ofstream output;
input.open(s);

if(input.fail())
{
    cout<<"source file open fall! "<<endl;
}
else
{
    cout<<"input copy file name: "<<endl;
    cin>>s1;
    output.open(s1);

    if(output.fail())
    {
        cout<<"open copy file name fall"<<endl;
    }
    else
    {
        while(!input.eof())
        {
            output.put(input.get());
            //先使用input.get()读取一个字符,然后将这个字符作为output.put()的参数输出
        }
    }
}
input.close();
output.close();
cout<<"-----------------success----------------"<<endl;
return 0;
}

编一个程序从一个文本文件source.txt中读入若干整数,用选择法将这些数据排成升序,将排序后的结果写入另一个文件文本文件target.txt中。

注意两个文件均在d盘的data文件夹中。
在程序运行前,先准备好输入数据文件source.txt,放入d盘的data文件夹中,内容可以如下:
2 3 10 45
33 8 9 20
45 67 888 3
7 2 32 -2
0 -1

程序运行结束后,查看d盘的data文件夹中的结果文件target.txt内容是否正确。

#include<iostream>
#include<fstream>
using namespace std;
int main()
{
char s[40];
char s1[40];

int i,j,temp,r[18];
const int n=18;
cout<<"input the file name "<<endl;
cin>>s;
//输入文件名的格式为如下格式:
//G:\\my_users\\users\\source.txt
ifstream input;
ofstream output;
input.open(s);

if(input.fail())
{
    cout<<"source file open fall! "<<endl;
}
else
{
     for(i=0;i<n;i++)
        input>>r[i];

    for(i=0;i<n;i++)
    for(j=i+1;j<n;j++)
    {
        if(r[i]>r[j])
        {
           temp=r[j];
           r[j]=r[i];
           r[i]=temp;
        }
    }

    cout<<"input copy file name: "<<endl;
    cin>>s1;
    output.open(s1);

    if(output.fail())
    {
        cout<<"open copy file name fall"<<endl;
    }
    else
    {
        for(i=0;i<n;i++)
        {
            output << r[i] << " ";
            //先使用input.get()读取一个字符,然后将这个字符作为output.put()的参数输出
        }
    }
}
input.close();
output.close();
cout<<"-----------------success----------------"<<endl;
return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值