C++ 实验四 任务报告

📝实验四 任务报告

✨实验内容

🕐任务一

验证性实验。
C++标准库提供了一个容器类模板map,称为关联数组,或,字典,可以用来描述键-值对映射关系。
在C++编码环境中,输入代码task1_1.cpp和 task1_2.cpp,结合运行结果,了解和练习map基础用法。
task1_1.cpp

📃代码:

task1_1.cpp

#include <iostream>
#include <map>
#include <string>

int main()
{
    using namespace std;

    map<int, string> grade_dict{{5, "Excellent"},
                                {4, "Good"},
                                {3, "Average"},
                                {2, "Fair"},
                                {1, "Poor"}};

    int grade;

    while (cin >> grade)
    {
        if (grade >= 1 && grade <= 5)
            cout << grade << ": " << grade_dict[grade] << endl;
        else
            cout << "Invalid input. the number must be bewteen 1 and 5.\n";
    }
}

task1_2.cpp

#include <iostream>
#include <map>
#include <string>

int main()
{
    using namespace std;

    map<int, string> dec_hex_dict{{10, "A"},
                                  {11, "B"},
                                  {12, "C"},
                                  {13, "D"},
                                  {14, "E"},
                                  {15, "F"}};

    for (auto i = 10; i <= 15; ++i)
        cout << dec_hex_dict[i];
    cout << endl;

    string s1, s2;

    s1 = "FF17";

    s2 = string(s1.rbegin(), s1.rend());

    cout << "s1 = " << s1 << endl;
    cout << "s2 = " << s2 << endl;
}

🎨输出:

task1_1

2
2: Fair
6
Invalid input. the number must be bewteen 1 and 5.
3
3: Average

task1_2

ABCDEF
s1 = FF17
s2 = 71FF

🤓思考:

  1. map作为一个容器模板类,可以直观、方便地描述现实世界中的键-值对(Key-Value)关系。
  2. 从task1_2.cpp可见,实验2中实践过的迭代器,它并非只对vector、array等少数容器有效,而是一种
    通用的迭代器模板类,在有序类容器中,通常都可以使用。具体,请查看标准库手册。灵活地组合使用
    这些标准库的组件,可以极大提升开发效率,同时,代码表达反映的逻辑性、可读性等也更好。

🕑任务二

验证性实验。

运行程序,观察结果。结合运行结果和代码,加深对以下内容的理解:

  1. 当派生类出现与基类同名成员时:同名覆盖原则,二元作用域分辨符
  2. 类型兼容原则:派生类对象可以被当作基类对象使用,但是,当作基类对象使用时,只能使用作为
    基类的那一部分接口

📃代码:

#include <iostream>
#include <typeinfo>

// definitation of Graph
class Graph
{
public:
     virtual void draw() { std::cout << "Graph::draw() : just as an interface\n"; }
};


// definition of Rectangle, derived from Graph
class Rectangle : public Graph
{
public:
    void draw() { std::cout << "Rectangle::draw(): programs of draw a rectangle\n"; }
};


// definition of Circle, derived from Graph
class Circle : public Graph
{
public:
    void draw() { std::cout << "Circle::draw(): programs of draw a circle\n"; }
};


// definitaion of fun(): as a call interface
void fun(Graph *ptr)
{
    std::cout << "pointer type: " << typeid(ptr).name() << "\n";
    std::cout << "RTTI type: " << typeid(*ptr).name() << "\n";
    ptr -> draw();
}

// test 
int main()
{
    Graph g1;
    Rectangle r1;
    Circle c1;
    double i =0;
    std::cout << typeid(i).name()<<"\n";

    // call by object name
    g1.draw();
    r1.draw();
    c1.draw();

    std::cout << "\n";

    // call by object name, and using the scope resolution operator::
    r1.Graph::draw();
    c1.Graph::draw();

    std::cout << "\n";

    // call by pointer to Base class
    fun(&g1);
    fun(&r1);
    fun(&c1);
}

🎨输出:

不带virtual

d
Graph::draw() : just as an interface
Rectangle::draw(): programs of draw a rectangle
Circle::draw(): programs of draw a circle

Graph::draw() : just as an interface
Graph::draw() : just as an interface

pointer type: P5Graph
RTTI type: 5Graph
Graph::draw() : just as an interface
pointer type: P5Graph
RTTI type: 5Graph
Graph::draw() : just as an interface
pointer type: P5Graph
RTTI type: 5Graph
Graph::draw() : just as an interface

virtual

d
Graph::draw() : just as an interface
Rectangle::draw(): programs of draw a rectangle
Circle::draw(): programs of draw a circle

Graph::draw() : just as an interface
Graph::draw() : just as an interface

pointer type: P5Graph
RTTI type: 5Graph
Graph::draw() : just as an interface
pointer type: P5Graph
RTTI type: 9Rectangle
Rectangle::draw(): programs of draw a rectangle
pointer type: P5Graph
RTTI type: 6Circle
Circle::draw(): programs of draw a circle

🤓思考:

typeid可以用于获取运行时类型信息。
line3,获取运行时指针变量ptr的类型信息
line4,获取运行时指针变量ptr实际指向的对象的类型信息。RTTI,Runtime Type Info的首字母缩写,
运行时类型信息。
通过在Graph类的接口draw(),不加/加关键字virtual,可以观察到运行时ptr实际指向的对象的不同。

🕒任务三

使用类的组合和继承模拟简单的车辆信息管理。
问题场景描述如下:
为了对车量基本信息进行管理,对现实世界车量基本信息抽象后,抽象出Car类、ElectricCar类、
Battery类,它们之间的关系描述如下:ElectricCar类公有继承自Car类,ElectricCar中新增数据成员为
Battery类对象。
类图简化模型如图所示。

image-20211130185833705基于以下描述设计并实现Battery类
每个Battery类对象有如下信息:车载动力电池容量(capacity)
要求Battery类提供成员函数实现以下要求:
带有默认形参值的构造函数。实现Battery类对象的构造,在构造对象时对电池容量
capacity进行初始化,默认参数值为70(单位: kWh)。
返回当前电池容量的函数get_capacity()。
基于以下描述设计并实现Car类
每辆汽车有如下信息:制造商(maker), 型号(model), 生产年份(year), 行车里程数
(odometers)。
要求Car类提供成员函数实现以下要求:
带参数的构造函数。实现Car类对象的构造,并在构造对象时实现对制造商、型号、生产
年份的初始化。初始构造时,行车里程数总是0。
显示车辆信息的函数info()。实现车辆信息显示输出,输出信息包括:制造商、型号、生
产年份、当前行车里程数。
更新行车里程数的函数update_odometers()。更新后的行车里程数通过参数传递。要求
能对参数进行合理性检查,如果更新后的行车里程数值小于当前行车里程数,打印警告
信息,提示更新数值有误。
基于以下描述设计并实现ElectricCar类
ElectricCar类继承自Car类,新增数据成员电池(battery)。其中,battery是Battery类对象。
带参数的构造函数。实现ElectricCar类对象的构造,并在构造时实现对制造商、型号、生产年
份以及新增数据成员电池的初始化。初始构造时,行车里程数总是0。
显示车辆信息info()。实现车辆信息显示输出,包括:制造商、型号、生产年份、当前行车里
程数、当前电池容量。
在主程序中测试设计的类。
要求采用多文件组织代码,文件列表如下:
battery.hpp 电池类Battery的定义和实现
car.hpp 汽车类Car的定义和实现
electricCar.hpp 电动汽车类ElectricCar类的定义和实现
electricCar.cpp 电动汽车类ElectricCar类的实现
task3.cpp 主程序。测试Car类对象和Electric类对象。

📃代码:

battery.hpp

c#ifndef EXP4_BATTERY_HPP
#define EXP4_BATTERY_HPP
#include <iostream>
#include <string>
using namespace std;
class Battery
{
public:
    double capacity;

    Battery(double c = 70) : capacity(c) {}

    double get_capacity() const { return capacity; }
};
#endif //EXP4_BATTERY_HPP

car.hpp

#ifndef EXP4_ELECTRICCAR_HPP
#define EXP4_ELECTRICCAR_HPP

#include "battery.hpp"
#include "car.hpp"
#include <iostream>
#include <string>

using namespace std;


class Electric_Car : public Car, public Battery
{
public:
    Battery battery;

    Electric_Car(string mk, string md, int yr, int om = 0, Battery b = Battery(70)) : Car(mk, md, yr, om), battery(b) {}

    void info()
    {
        cout << "Capacty:" << capacity << "" << endl;
        cout << "Maker: " << maker << "" << endl;
        cout << "Model: " << model << "" << endl;
        cout << "Year: " << year << "" << endl;
        cout << "Odometers: " << odometers << "" << endl;
    }
};

#endif //EXP4_ELECTRICCAR_HPP

electricCar.hpp

#ifndef EXP4_ELECTRICCAR_HPP
#define EXP4_ELECTRICCAR_HPP

#include "battery.hpp"
#include "car.hpp"
#include <iostream>
#include <string>

using namespace std;


class Electric_Car : public Car, public Battery
{
public:
    Battery battery;

    Electric_Car(string mk, string md, int yr, int om = 0, Battery b = Battery(70)) : Car(mk, md, yr, om), battery(b) {}

    void info()
    {
        cout << "Capacty:" << capacity << "" << endl;
        cout << "Maker: " << maker << "" << endl;
        cout << "Model: " << model << "" << endl;
        cout << "Year: " << year << "" << endl;
        cout << "Odometers: " << odometers << "" << endl;
    }
};

#endif //EXP4_ELECTRICCAR_HPP

task3.cpp

#include <iostream>
#include "electricCar.hpp"

int main()
{
    using namespace std;

    // test class of Car
    cout << "--------oldcar's info--------" << endl;
    Car oldcar("Audi", "a4", 2016);
    oldcar.update_om(-25000);
    oldcar.info();

    cout << endl;

    // test class of ElectricCar
    cout << "\n--------newcar's info--------\n";
    Electric_Car newcar("Tesla", "model 3", 2022);
    newcar.update_om(655335);
    newcar.info();
}

🎨输出:

--------oldcar's info--------
updating odometers..
Input Error: The new odometers should be more than the old one.
Maker: Audi
Model: a4
Year: 2016
Odometers: 0

--------newcar's info--------
updating odometers..
Odometers have been change successfully.
Capacty:70
Maker: Tesla
Model: model 3
Year: 2022
Odometers: 655335

🤓思考:

🕓任务四

使用类的继承,模拟简单的机器宠物。
问题场景描述如下:
对机器宠物进行抽象后,抽象出三个简单的类:机器宠物类MachinePets、宠物猫类PetCats、宠物狗
类PetDogs。它们之间的关系如UML类图所示:
image-20211130185820209
设计并实现一个机器宠物类MachinePets。
每个机器宠物有如下信息:昵称(nickname)
每个机器宠物有如下成员函数:
带参数的构造函数MachinePets(const string s),为机器宠物初始化昵称。
虚函数string talk()为机器宠物派生类提供宠物叫声的统一接口。(关于虚函数,参考实
验任务2)
设计并实现电子宠物猫类PetCats,该类公有继承自MachinePets。每个电子宠物猫类有如下成员
函数:
带参数的构造函数PetCats(const string s),为机器宠物猫初始化昵称。
string talk(),返回电子宠物猫叫声。
设计并实现电子宠物狗类PetDogs, 该类公有继承自MachinePets。每个电子宠物狗类有如下成
员函数:
带参数的构造函数PetCats(const string s),为机器宠物狗初始化昵称。
string talk(),返回电子宠物狗叫声。
在主程序中,测试类。
其中,在主程序中编写一个统一的接口函数void play(××),可以根据实参对象的类型,显示不同
宠物叫声。
要求采用多文件组织代码,文件列表如下:
pets.hpp 机器宠物类MachinePets、宠物猫类PetCats、宠物狗类PetDogs的定义和
实现
task4.cpp 主程序,测试上述类及其接口。

📃代码:

pets.hpp

#ifndef EXP4_PETS_HPP
#define EXP4_PETS_HPP

#include <iostream>
#include <string>

using namespace std;

class MachinePets
{
public:

    MachinePets(const string s) : nickname(s) {}

    virtual string get_nickname() { return nickname; }

    virtual string talk() { return voice; }

protected:
    string voice;
    string nickname;
};

class PetCats : public MachinePets
{
public:
    PetCats(const string s) : MachinePets(s) { voice = "miaomiao"; }

    string get_nickname() { return nickname; }

    string talk() { return voice; }
};

class PetDogs : public MachinePets
{
public:
    PetDogs(const string s) : MachinePets(s) { voice = "wangwang"; };

    string get_nickname() { return nickname; }

    string talk() { return voice; }

};

#endif //EXP4_PETS_HPP

task4.cpp

#ifndef EXP4_PETS_HPP
#define EXP4_PETS_HPP

#include <iostream>
#include <string>

using namespace std;

class MachinePets
{
public:

    MachinePets(const string s) : nickname(s) {}

    virtual string get_nickname() { return nickname; }

    virtual string talk() { return voice; }

protected:
    string voice;
    string nickname;
};

class PetCats : public MachinePets
{
public:
    PetCats(const string s) : MachinePets(s) { voice = "miaomiao"; }

    string get_nickname() { return nickname; }

    string talk() { return voice; }
};

class PetDogs : public MachinePets
{
public:
    PetDogs(const string s) : MachinePets(s) { voice = "wangwang"; };

    string get_nickname() { return nickname; }

    string talk() { return voice; }

};

#endif //EXP4_PETS_HPP

🎨输出:

miku says miaomiao
da huang says wangwang

🤓思考:

posted @ 2021-11-28 23:51  李柳星  阅读(57)  评论(2编辑  收藏  举报