实验四:类的继承、派生和多态

实验目的

1. 理解类的继承和派生机制

2. 掌握派生类的定义和使用

3. 理解和掌握派生类成员的标识和访问中同名覆盖原则、二元作用域分辨符和虚基类的用法

4. 掌握派生类构造函数和析构函数的定义及调用次序

5. 理解运算符重载的目的,掌握运算符重载函数的编写方法

实验内容 

1. 车辆基本信息管理 问题场景描述如下: 为了对车量基本信息进行管理,对现实世界车量基本信息抽象后,抽象出Car类、ElectricCar类、Battery类, 它们之间的关系描述如下:基于Car类派生出ElectricCar类,派生类ElectricCar中新增数据成员为Battery类 对象。

基于以下描述设计并实现Battery类

· 每个Battery类对象有如下信息:

    车载动力电池容量(batterySize)

· 要求Battery类提供成员函数实现以下要求:

    带有默认形参值的构造函数。

    实现Battery类对象的构造,在构造对象时对电池容量batterySize 进行初始化,默认参数值为70(单位: kWh)。

    返回当前电池容量。

基于以下描述设计并实现Car类

· 每辆汽车有如下信息:

    制造商(maker), 型号(model), 生产年份(year), 行车里程数(odometer)。

· 要求Car类提供成员函数实现以下要求:

    带参数的构造函数。实现Car类对象的构造,并在构造对象时实现对制造商、型号、生产年份的 初始化。初始构造时,行车里程数总是0。

    重载运算符<<为Car类友元。实现车辆信息显示输出,输出信息包括:制造商、型号、生产年 份、当前行车里程数。

    更新行车里程数。更新后的行车里程数通过参数传递。要求能对参数进行合理性检查,如果更 新后的行车里程数值小于当前行车里程数,打印警告信息,提示更新数值有误。

基于以下描述设计并实现ElectricCar类

· ElectricCar类继承自Car类,新增数据成员电池(battery)。其中,battery是Battery类对象。

· 带参数的构造函数。

· 实现ElectricCar类对象的构造,并在构造时实现对制造商、型号、生产年份以及 新增数据成员电池的初始化。初始构造时,行车里程数总是0。

· 重载运算符<<为ElectricCar类友元。实现车辆信息显示输出,包括:制造商、型号、生产年份、当前 行车里程数、当前电池容量。

#ifndef Battery_h
#define Battery_h

#include<iostream>
using namespace std;

class Battery{
public:
    Battery(int battertSize0=70);
    int getbatterySize();
    friend class ElectricCar;
private:
    int batterySize;
};

#endif
battery.h
#ifndef CAR_H
#define CAR_H

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

class Car{
public:
    Car(string maker0, string model0, int year0, int odometer0=0);
    friend ostream & operator<<(ostream &out,const Car &c);
    void updateOdometer(double odometer);
    string getmaker() { return maker; }
    string getmodel() { return model; }
    int getyear() { return year; }
    double getodometer() { return odometer; }
private:
    string maker;
    string model;
    int year;
    double odometer;
};

#endif
car.h
#ifndef ElectricCar_H
#define ElectricCar_H

#include"car.h"
#include"battery.h"
#include<string>
#include<iostream>
using namespace std;
class Battery;
class ElectricCar:public Car
{
public:
    ElectricCar(string maker0,string model0,int year0,int odometer0=0);
    void batt(int battery);
    friend ostream & operator<<(ostream &out,ElectricCar &d);
private:
    Battery battery;
    int b;
};

#endif
electricCar.h
#include"battery.h"
#include<iostream>
using namespace std;

Battery::Battery(int batterySize0){
    batterySize=batterySize0;
}
    
battery.cpp
#include"car.h"
#include<iostream>
using namespace std;

ostream & operator<<(ostream &out,const Car &c){
    out<<"maker:"<<c.maker<<endl<<"model:"<<c.model<<endl<<"year:"<<c.year<<endl<<"odometer:"<<c.odometer<<endl;
    return out;}
Car::Car(string maker0, string model0,int year0,int odometer0){
    maker=maker0;
    model=model0;
    year=year0;
    odometer=odometer0;}
void Car::updateOdometer(double odometer0){
    while(odometer>odometer0){
        cout<<"Data error,please enter again:";
        cin>>odometer0;}
    odometer=odometer0;
}
car.cpp
#include"electricCar.h"
#include<iostream>
using namespace std;

ostream & operator<<(ostream &out,ElectricCar &d){
    out<<"maker:"<<d.getmaker()<<endl<<"model:"<<d.getmodel()<<endl<<"year:"<<d.getyear()<<endl<<"odometer:"<<d.getodometer()<<endl<<"batterySize:"<<d.b<<"-kWh"<<endl;
    return out;}

ElectricCar::ElectricCar(string maker0, string model0, int year0, int odometer0) :Car(maker0, model0, year0, odometer0) {
    battery.batterySize = 70;
    b=battery.batterySize;
}
electricCar.cpp
#include <iostream>
using namespace std;

#include "car.h"
#include "electricCar.h" 

int main() {
    // 测试Car类 
    Car oldcar("Audi","a4",2016);
    cout << "--------oldcar's info--------" << endl;
    oldcar.updateOdometer(25000);
    cout << oldcar << endl;

    // 测试ElectricCar类 
    ElectricCar newcar("Tesla","model s",2016);
    newcar.updateOdometer(2500);
    cout << "\n--------newcar's info--------\n"; 
    cout << newcar << endl;

    system("pause");
    
    return 0;
}
main.cpp

运行结果

 

2.补足程序,重载运算符[]为一维动态整形数组类ArrayInt的成员函数,使得通过动态整形数组对象名和下标可以 访问对象中具体元素。

 

#ifndef ARRAY_INT_H
#define ARRAY_INT_H

class ArrayInt{
    public:
        ArrayInt(int n, int value=0);
        ~ArrayInt();
        // 补足:将运算符[]重载为成员函数的声明
        // ×××
        int &operator[](int i);
        void print(); 
    private:
        int *p;
        int size;
};

#endif
arrayInt.h

 

#include "arrayInt.h"
#include <iostream>
#include <cstdlib>
using std::cout;
using std::endl;

ArrayInt::ArrayInt(int n, int value): size(n) {
    p = new int[size];
    
    if (p == nullptr) {
        cout << "fail to mallocate memory" << endl;
        exit(0); 
    } 
    
    for(int i=0; i<size; i++)
        p[i] = value;
}

ArrayInt::~ArrayInt() {
    delete[] p;
}

void ArrayInt::print() {
    for(int i=0; i<size; i++)
        cout << p[i] << " ";
    cout << endl;
}

// 补足:将运算符[]重载为成员函数的实现
// ×××
int& ArrayInt::operator[](int i){
    return p[i];
}
arrayInt.cpp
#include <iostream>
using namespace std;

#include "arrayInt.h"

int main() {
    // 定义动态整型数组对象a,包含2个元素,初始值为0
    ArrayInt a(2);
    a.print();
    
    // 定义动态整型数组对象b,包含3个元素,初始值为6
    ArrayInt b(3, 6);
    b.print();

    // 通过对象名和下标方式访问并修改对象元素
    b[0] = 2;
    cout << b[0] << endl;
    b.print();

    system("pause");

    return 0;
}
main.cpp

运行结果

 实验总结与体会

继承与派生较能理解,运算符重载只会照搬书上的框架和套路,比较生疏。

整体掌握较弱,第一个实验需要同学的帮助才能够解决问题。

 

posted @ 2019-05-19 20:06  小啵  阅读(324)  评论(1编辑  收藏  举报