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
🤓思考:
- map作为一个容器模板类,可以直观、方便地描述现实世界中的键-值对(Key-Value)关系。
- 从task1_2.cpp可见,实验2中实践过的迭代器,它并非只对vector、array等少数容器有效,而是一种
通用的迭代器模板类,在有序类容器中,通常都可以使用。具体,请查看标准库手册。灵活地组合使用
这些标准库的组件,可以极大提升开发效率,同时,代码表达反映的逻辑性、可读性等也更好。
🕑任务二
验证性实验。
运行程序,观察结果。结合运行结果和代码,加深对以下内容的理解:
- 当派生类出现与基类同名成员时:同名覆盖原则,二元作用域分辨符
- 类型兼容原则:派生类对象可以被当作基类对象使用,但是,当作基类对象使用时,只能使用作为
基类的那一部分接口
📃代码:
#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 circleGraph::draw() : just as an interface
Graph::draw() : just as an interfacepointer 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 circleGraph::draw() : just as an interface
Graph::draw() : just as an interfacepointer 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类对象。
类图简化模型如图所示。
基于以下描述设计并实现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类图所示:
设计并实现一个机器宠物类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
🤓思考:
略