《C++程序设计》实验报告(四)之继承与派生、多态性与虚函数

一、实验目的:

1.理解继承与派生的概念,掌握多重继承。

2.掌握派生类的声明方式、构成。

3.掌握派生类成员的访问属性。

4.掌握派生类的构造函数和析构函数。

5.了解多态性的概念;

6.掌握虚函数、纯虚函数、抽象类。

二、实验内容

1.分析以下程序的执行结果。

#include <iostream.h>

class base

{ int n;

public:

base(int a)

{ cout<<"constructing base class "<<endl;

n=a;

cout<<"n="<<n<<endl;

}

~base(){ cout<<"destructing base blass"<<endl; }

};

class subs:public base

{ int m;

public:

subs(int a,int b):base(a)

{ cout<<"constructing sub class "<<endl;

m=b;

cout<<"m="<<m<<endl;

}

~subs(){ cout<<"destructing sub blass"<<endl;   }

};

void main()

{ subs s(1,2);  }

2.分析以下程序的执行结果。

#include <iostream.h>

class A

{ int a;

public:

A(int i){ a=i;   cout<<"constructing class A"<<endl;  }

void print(){  cout<<a<<endl; }

~A(){ cout<<"destructing class A"<<endl; }

};

class B1:public A

{ int b1;

public:

B1(int i,int j):A(i)

{ b1=j; cout<<"constructing class B1"<<endl;   }

void print()

{   A::print();     cout<<b1<<endl; }

~B1(){ cout<<"constructing class B1"<<endl;  }

};

class B2:public A

{ int b2;

public:

B2(int i,int j):A(i)

{ b2=j; cout<<"constructing class B2"<<endl;   }

void print()

{   A::print();     cout<<b2<<endl; }

~B2(){ cout<<"constructing class B2"<<endl;  }

};

class C:public B1,public B2

{ int c;

public:

C(int i,int j,int k,int l,int m):B1(i,j),B2(k,l),c(m)

{ cout<<"constructing class C"<<endl; }

void print()

{ B1::print();

B2::print();

cout<<c<<endl;

}

~C(){  cout<<"destructing class C"<<endl;}

};

void main()

{ C c1(1,2,3,4,5);

c1.print();

}

3.编写程序

分别声明Teacher(教师)类和Cadre(干部)类,采用多重继承方式由这两个类派生出新类Teacher_Cadre(教师兼干部)类。

要求及实现方法:

(1)在两个基类中都包含姓名、年龄、性别、地址、电话等数据成员。

(2)在Teacher类中还包含数据成员title(职称),在Cadre类中还包含数据成员post(职务)。在Teacher_Cadre类中还包含数据成员wages(工资)。

(3)对两个基类中的姓名、年龄、性别、地址、电话等数据成员用相同的名字,在引用这些数据成员时,指定作用域。

(4)在类体中声明成员函数,在类外定义成员函数。

(5)在派生类Teacher_Cadre的成员函数show中调用Teacher类中的display函数,输出姓名、年龄、性别、 职称、地址、电话,然后再用cout语句输出职务与工资。

程序:

#include<iostream>

#include<string>

using namespace std;

class Teacher {

public:

    Teacher(string na, int a, char s, string ad, int te, string t) :name(na), age(a), sex(s), address(ad), tell(te), title(t) {

    }

    void display();

protected:

    string name;

    int age;

    char sex;

    string address;

    int tell;

    string title;

};

void Teacher::display() {

    cout << "name=" << name << endl;

    cout << "age=" << age << endl;

    cout << "sex=" << sex << endl;

    cout << "address=" << address << endl;

    cout << "tell=" << tell << endl;

    cout << "title=" << title << endl;

}

class Grade {

public:

    Grade(string na, int a, char s, string ad, int te, string p) {

        name1 = na;

        age1 = a;

        sex1 = s;

        address1 = ad;

        tell1 = te;

        post = p;

    }

    void display1();

protected:

    string name1;

    int age1;

    char sex1;

    string address1;

    int tell1;

    string post;

};

void Grade::display1() {

    cout << "name=" << name1 << endl;

    cout << "age=" << age1 << endl;

    cout << "sex=" << sex1 << endl;

    cout << "address=" << address1 << endl;

    cout << "tell=" << tell1 << endl;

    cout << "post=" << post << endl;

}

class Teacher_Grade :public Teacher, public Grade {

public:

    Teacher_Grade(string na, int a, char s, string ad, int te, string t, string p, float w) :Teacher(na, a, s, ad, te, t), Grade(na, a, s, ad, te, p), wage(w) {

    }

    void show();

private:

    float wage;

};

void Teacher_Grade::show() {

    cout << "name=" << name1 << endl;

    cout << "age=" << age1 << endl;

    cout << "sex=" << sex1 << endl;

    cout << "address=" << address1 << endl;

    cout << "tell=" << tell1 << endl;

    cout << "post=" << post << endl;

    cout << "title=" << title << endl;

    cout << "wage=" << wage << endl;

}

int main() {

    Teacher_Grade tg1("qcy", 22, 'n', "nt", 123, "ilove", "zwj", 2.3);

    tg1.show();

    return 0;

}

4.编写程序。利用继承性与派生类来管理学生老师档案:由person(人员)类出发(作为基类),派生出student(学生)类及teacher(教师)类;而后又由student(学生)类出发(作为基类),派生出graduateStudent(研究生)类。可假定这几个类各自具有的数据成员为:

person(人员)类:姓名、性别、年龄。

student(学生)类:姓名、性别、年龄、学号、系别。

graduateStudent(研究生)类:姓名、性别、年龄、学号、系别、导师。

teacher(教师)类:姓名、性别、年龄、职称、主讲课程。

为简化起见,每个类可只设立构造函数以及显示类对象数据的成员函数display()。而后编写简单的主函数,说明上述有关的对象,并对其类成员函数进行简单使用(调用)。

实现方法:

(1)派生类继承了其基类的所有成员,而且还通过增添说明某些本派生类的特有成员来其基类的功能进行扩展。

(2)派生类的构造函数要负责其基类的初始化,通过初始化符表来完成这项工作。

(3)基类与各派生类中都使用了同名的成员函数display(),为避免二义性,凡调用从基类继承而来的同名函数时要使用类限定,如“person::”或“student::”等(调用本派生类的那个同名函数时则不必使用类限定)。

(4)四个有关类定义的程序“构架”如下:

class person{                    //person类,它将作为其他几个类的基类

      char name[30];          //姓名

      char sex;                      //性别

      int age;                       //年龄

   public:

      person(char *na,char sx,int ag);   //构造函数

      void display();                    //负责显示person类对象的有关数据

};

class teacher:public person{             //teacher类,由基类person所派生

      char post[30];                     //增添数据成员:职称

      char course[30];                   //增添数据成员:担任课程

public:

     ……

};

class student:public person{             //student类,由基类person所派生

      int Reg_Number;                    //增添数据成员:学号

      char department[30];               //增添数据成员:系别

   public:

     ……

};

class graduateStudent:public person    //graduateStudent类,由基类person所派生

{     char advisor[30];               //增添数据成员:导师

   public:

     ……

};

程序:

#include<iostream>

using namespace std;

typedef unsigned long long ULL;

class Person

{

public:

    Person(string n, char s, int a)

    {

        name = n;

        sex = s;

        age = a;

    }

    void display()

    {

        cout << "name:" << name << endl;

        cout << "sex:" << sex << endl;

        cout << "age:" << age << endl;

    }

protected:

    string name;

    char sex;

    int age;

};

class Teacher :public Person

{

public:

    Teacher(string n, char s, int a, string p, string c) :Person(n, s, a)

    {

        post = p;

        course = c;

    }

    void display()

    {

        cout << "name:" << name << endl;

        cout << "sex:" << sex << endl;

        cout << "age:" << age << endl;

        cout << "post:" << post << endl;

        cout << "course:" << course << endl;

    }

protected:

    string post;

    string course;

};

class Student :public Person

{

public:

    Student(string n, char s, int a, ULL num, string d) :Person(n, s, a)

    {

        number = num;

        department = d;

    }

    void display()

    {

        cout << "name:" << name << endl;

        cout << "sex:" << sex << endl;

        cout << "age:" << age << endl;

        cout << "number:" << number << endl;

        cout << "department:" << department << endl;

    }

protected:

    ULL number;

    string department;

};

class GraduateStudent :public Student

{

public:

    GraduateStudent(string n, char s, int a, ULL num, string d, string adv) :Student(n, s, a, num, d)

    {

        advisor = adv;

    }

    void display()

    {

        cout << "name:" << name << endl;

        cout << "sex:" << sex << endl;

        cout << "age:" << age << endl;

        cout << "number:" << number << endl;

        cout << "department:" << department << endl;

        cout << "advisor:" << advisor << endl;

    }

protected:

    string advisor;

};

int main()

{

    Person p1("张三", '1', 18);

    Teacher t1("李四", '2', 22, "assiant", "Math");

    Student s1("王五", '1', 19, 20234091207, "English");

    GraduateStudent g1("赵六", '2', 24, 20254091207, "English", "abc");

    cout << "1.人员;2.教师;3.学生;4.研究生" << endl;

    cout << "请输入您要查找的对象(输入0即可退出查询):";

    int n;

    while (cin >> n && n)

    {

        if (n == 1) p1.display();

        else if (n == 2) t1.display();

        else if (n == 3) s1.display();

        else g1.display();

        cout << '\n' << "1.人员;2.教师;3.学生;4.研究生" << endl;

        cout << "请输入您要查找的对象(输入0即可退出查询):";

    }

    return 0;

}

5.编写程序。设计一个汽车类vehicle,包含的数据成员有:车轮个数wheels和车重weight。小车类car是它的私有派生类,其中包含载人数passenger_load。卡车类truck是vehicle的私有派生类,其中包含载人数passenger_load和载重量payload。每个类都有相关数据的输出方法。

实现方法:

(1)vehicle类是基类,由它派生出car类和truck类,将公共的属性和方法放在vehicle类中。

(2)可编写如下的主函数对功能进行测试,以确认其正确性。

void main()

{

car car1(4,2000,5);

truck tru1(10,8000,1,340000);

cout<<"输出结果"<<endl;

car1.show();

tru1.show();

}

程序:

#include<iostream>

using namespace std;

class vehicle

{

protected:

int wheels;

double weight;

};

class car :private vehicle

{

protected:

int passenger_load;

public:

car(int wh, double we, int pas)

{

wheels = wh;

weight = we;

passenger_load = pas;

}

void show()

{

cout << "车轮个数为:" << wheels << "  "

<< "车重为:" << weight << endl

<< "承载人数:" << passenger_load << endl;

}

};

class truck :private vehicle

{

protected:

int passenger_load;

double payload;

public:

truck(int wh, double we, int pas, double pay)

{

wheels = wh;

weight = we;

passenger_load = pas;

payload = pay;

}

void show()

{

cout << "车轮个数为:" << wheels << "  "

<< "车重为:" << weight << endl

<< "承载人数:" << passenger_load << "  "

<< "载重为:" << payload << endl;

}

};

void main()

{

car car1(4, 2000, 5);

truck tru1(10, 8000, 1, 340000);

cout << "输出结果" << endl;

car1.show();

tru1.show();

}

6.编写程序。求出租车收费的程序,输入起始站、终止站和路程,计费方式是起价8元,其中含3公里费用,以后每半公里收费0.7元。

实现方法:

(1)设计一个站类Station,用于设置起始站、终止站。

(2)设计路程类Mile,用于设置路程。

(3)由(1)(2)派生出收费类Price,用于计费。

(4) 可编写如下的主函数对功能进行测试,以确认其正确性。

void main()

{   Price A;

    A.getdata();

Price B("关山口","中山公园",32.6);

cout<<"输出结果:"<<endl;

A.disp();

B.disp();

}

程序:

#include <iostream>

using namespace std;

class Station {

protected:

    string start;

    string over;

public:

    Station() {}

    Station(string s, string o) :start(s), over(o) {}

};

class Mile {

protected:

    float journey;

public:

    Mile() {}

    Mile(float j) :journey(j) {}

};

struct Price :public Station, public Mile {

    Price() {}

    Price(string s, string o, float j) :Station(s, o), Mile(j) {}

    void getdata();

    void disp();

};

void Price::getdata() {

    cout << "请输入起始站" << endl;

    cin >> start;

    cout << "请输入终止站" << endl;

    cin >> over;

    cout << "请输入距离" << endl;

    cin >> journey;

}

void Price::disp() {

    if (journey <= 3)

    {

        cout << "从" << start << "站,到" << over << "站,共消费" << 8 << "元" << endl;

    }

    else cout << "从" << start << "站,到" << over << "站,共消费" << 8 + (journey - 3) * 1.4 << "元" << endl;

}

int main()

{

    Price A;

    A.getdata();

    Price B("关山口", "中山公园", 32.6);

    cout << "输出结果:" << endl;

    A.disp();

    B.disp();

    system("pause");

}

  1. 先建立一个Point(点)类,包含数据成员x,y(坐标点)。以它为基类,派生出一个Circle(圆)类,增加数据成员r(半径),再以Circle类为直接基类,派生出一个Cylinder(圆柱体)类,再增加数据成员h(高)。要求编写程序,重载运算符“<<”和“>>”,使之能用于输出以上类对象,在程序中使用虚函数和抽象基类。

程序:

#include<iostream>

using namespace std;

#define Pi 3.14//圆周率

//点类(x,y)

class Point {

public:

friend istream& operator>>(istream& cin, Point& p);

friend ostream& operator<<(ostream& cout, Point p);

Point() {

cout << "Point类构造函数" << endl;

}

Point(float x0, float y0) {

cout << "Point类有参构造函数" << endl;

x = x0;

y = y0;

}

~Point() {

cout << "Point类析构函数" << endl;

}

protected:

float x;

float y;

};

//圆类(x,y),r

class Circle :public Point {

public:

friend istream& operator>>(istream& cin, Circle& c);

friend ostream& operator<<(ostream& cout, Circle c);

Circle() {

cout << "Circle类构造函数" << endl;

}

Circle(float x0, float y0, float r0) :Point(x0, y0), r(r0) {

cout << "Circle类有参构造函数" << endl;

}

~Circle() {

cout << "Circle类析构函数" << endl;

}

protected:

float r;

};

//圆柱类(x,y),r,h

class Cylinder :public Circle {

public:

friend istream& operator>>(istream& cin, Cylinder& cy);

friend ostream& operator<<(ostream& cout, Cylinder c);

Cylinder() {

cout << "Cylinder类构造函数" << endl;

}

Cylinder(float x0, float y0, float r0, float h0) :Circle(x0, y0, r0), h(h0) {

cout << "Cylinder类有参构造函数" << endl;

}

~Cylinder() {

cout << "Cylinder类析构函数" << endl;

}

protected:

float h;

};

//输入点类

istream& operator>>(istream& cin, Point& p) {

cout << "输入x" << endl;

cin >> p.x;

cout << "输入y" << endl;

cin >> p.y;

return cin;

}

//输入圆类

istream& operator>>(istream& cin, Circle& c) {

cout << "输入x" << endl;

cin >> c.x;

cout << "输入y" << endl;

cin >> c.y;

cout << "输入r" << endl;

cin >> c.r;

return cin;

}

//输入圆柱类

istream& operator>>(istream& cin, Cylinder& c) {

cout << "输入x" << endl;

cin >> c.x;

cout << "输入y" << endl;

cin >> c.y;

cout << "输入r" << endl;

cin >> c.r;

cout << "输入h" << endl;

cin >> c.h;

return cin;

}

//输出点类

ostream& operator<<(ostream& cout, Point p) {

cout << "点(" << p.x << "," << p.y << ")" << endl;

return cout;

}

//输出圆类

ostream& operator<<(ostream& cout, Circle c) {

cout << "以点(" << c.x << "," << c.y << ")" << "为中心" << c.r << "为半径的圆" << endl;

cout << "面积是" << c.r * c.r * Pi << endl;

return cout;

}

//输出圆柱类

ostream& operator<<(ostream& cout, Cylinder c) {

cout << "以点(" << c.x << "," << c.y << ")" << "为底面中心" << c.r << "为底面半径" << c.h << "为高的一个圆柱" << endl;

cout << "体积是" << c.r * c.r * Pi * c.h << endl;

return cout;

}

int main() {

//Point p(1.2,2);

//Circle c(1.2,3,2);

Cylinder cy(1, 2, 2, 2);

cout << cy;

system("pause");

return 0;

}

分析与讨论:

  1. 比较类的三种继承方式之间的差别?

答:private和protected成员,在类外是不可以使用的.只有public成员可以在类外直接使用

公有继承时,基类的private成员派生类也不可用,基类的public和protected成员在派生类中可直接使用.只有public成员在派生类外可以直接使用

保护继承时,基类的private成员仍为有私有.基类的public和protected成员变成派生类的protected成员,这时在派生类外也不能直接使用原基类的public成员

私有继承时,基类的private成员仍为有私有.基类的public和protected成员将变成派生类的private成员

  1. 派生类的构造函数执行的次序是怎样的?

答:先执行基类构造函数,再执行子类的构造函数, 若有多个基类,则按照基类的基础顺序调用基类的构造函数,

  1. 派生类的析构函数执行的次序是怎样的?

答:派生类的析构函数先对其新增的一般成员进行析构,然后对新增的成员对象进行析构,最后按照与其继承基类的相反顺序来调用基类的析构函数。

  1. 虚函数的实质是什么?写出虚函数的定义格式。

答:在某基类中声明为virtual并在一个或多个派生类中被重新定义的成员函数,即被virtual关键字修饰的成员函数;

格式:“virtual 函数返回类型 函数名(参数表) {函数体}”。

5.抽象类是否只能基类?为什么?

答:是。抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出。

  • 19
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

了一li

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

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

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

打赏作者

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

抵扣说明:

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

余额充值