c++ - 如何使用 boost 库反序列化和获取成员值
问题描述
首先,我想告诉你
- 我是序列化技术的新手
- 我对使用 boost 序列化并不完全空白,但是我经历的大多数示例都非常直接(例如,只有一个类,最多一个基类和一个派生类)。
我从这里举了一个例子。在这里,代码的编写者使用了 classsave
并load
使用了函数bus_schedule
。在此处调用的对象的帮助下,我遇到了获取所有成员变量的问题new_schedule
。我假设,这个对象将帮助我获取另一个类的所有成员(也许我在这一点上完全错了)。
除此之外,我已经看到,大多数成员变量都在这里private
,这意味着我无法从main
函数访问它们。这就是为什么,我设置了一些 getter 函数来返回一些成员值。例如,bus_schedule
如果我可以从类返回schedule
列表,那么我可以访问trip_info
结构值以及类型为 的指针bus_route
。
schedule
我使用的返回列表的函数是:
std::list<std::pair<trip_info, bus_route *> > return_schedule()
{
return schedule;
}
在main
我使用的功能中:
bus_schedule new_schedule;
auto returning_schedule = new_schedule.return_schedule();
for(auto i:returning_schedule)
{
cout<<(i.first)<<" ~~~~~~~ "<<(i.second)<<endl;
/*with i.first I can access the struct info, i.second pointer gives me the info of
bus_route pointer value ater dereferencing*/
}
但是在这里,我再次坚持从 i.second 指针中获取单独的值。我知道,bus_route
类有一个名为stops
. 这里也返回了这个。但在我看来,每次做这个反算都很麻烦。
我的问题是,反序列化后是否有任何直接的解决方案boost
可以访问所有成员变量?我将为所有班级设置吸气剂功能,但害怕找到使用这些功能的途径。
解决方案
这个问题实际上与序列化是分开的。这是没有序列化内容的数据结构。我对代码进行了现代化改造以使用 C++17 功能
auto
并移动语义default
ed特别会员[[nodiscard]]
,override
关键字- 显式构造函数和
emplace
- 带解构的 ranged-for 循环
make_unique<>
而不是new
/delete
- 扩展聚合初始化器
总而言之,它使代码更短、更简单、更高效¹。此外,它突出显示了您想知道的一些事情,我将在下面展示。
#include <iostream>
#include <list>
#include <memory>
#include <string>
struct gps_position {
int degrees;
int minutes;
float seconds;
friend std::ostream& operator<<(std::ostream& os, const gps_position& gp) {
return os << ' ' << gp.degrees << "º" << gp.minutes << "'" << gp.seconds << '"';
}
};
/////////////////////////////////////////////////////////////
// One bus stop
struct bus_stop {
gps_position latitude, longitude;
[[nodiscard]] virtual std::string description() const = 0;
virtual ~bus_stop() = default;
friend std::ostream& operator<<(std::ostream& os, const bus_stop& bs) {
return os << bs.latitude << bs.longitude << ' ' << bs.description();
}
protected:
explicit bus_stop(gps_position _lat, gps_position _long)
: latitude(_lat), longitude(_long) {}
};
/////////////////////////////////////////////////////////////
// Several kinds of bus stops
struct bus_stop_corner : bus_stop {
std::string street1, street2;
[[nodiscard]] std::string description() const override {
return street1 + " and " + street2;
}
explicit bus_stop_corner(gps_position _lat, gps_position _long, std::string _s1, std::string _s2)
: bus_stop(_lat, _long), street1(std::move(_s1)), street2(std::move(_s2)) {}
};
struct bus_stop_destination : bus_stop {
std::string name;
[[nodiscard]] std::string description() const override { return name; }
bus_stop_destination(gps_position _lat, gps_position _long, std::string _name)
: bus_stop(_lat, _long), name(std::move(_name)) {}
};
struct bus_route {
using bus_stop_pointer = bus_stop*;
std::list<bus_stop_pointer> stops;
void append(bus_stop* _bs) { stops.insert(stops.end(), _bs); }
friend std::ostream& operator<<(std::ostream& os, const bus_route& br) {
for (auto& stop : br.stops) {
os << '\n' << std::hex << "0x" << stop << std::dec << ' ' << *stop;
}
return os;
}
};
/////////////////////////////////////////////////////////////
// a bus schedule is a collection of routes each with a starting time
struct bus_schedule {
struct trip_info { int hour, minute; std::string driver; };
void append(const std::string& _d, int _h, int _m, bus_route* _br) {
schedule.emplace(schedule.end(), trip_info{_h, _m, _d}, _br);
}
private:
friend std::ostream& operator<<(std::ostream& os, const bus_schedule& bs) {
for (auto const& [k,v] : bs.schedule) { os << k << *v; }
return os;
}
friend std::ostream& operator<<(std::ostream& os, const bus_schedule::trip_info& ti) {
return os << '\n' << ti.hour << ':' << ti.minute << ' ' << ti.driver << ' ';
}
std::list<std::pair<trip_info, bus_route*>> schedule;
};
int main() {
// fill in the data
// make a few stops
auto bs0 = std::make_unique<bus_stop_corner>(
gps_position{ 34, 135, 52.560F }, gps_position{ 134, 22, 78.30F },
"24th Street", "10th Avenue");
auto bs1 = std::make_unique<bus_stop_corner>(
gps_position{ 35, 137, 23.456F }, gps_position{ 133, 35, 54.12F },
"State street", "Cathedral Vista Lane");
auto bs2 = std::make_unique<bus_stop_destination>(
gps_position{ 35, 136, 15.456F }, gps_position{ 133, 32, 15.300F },
"White House");
auto bs3 = std::make_unique<bus_stop_destination>(
gps_position{ 35, 134, 48.789F }, gps_position{ 133, 32, 16.230F },
"Lincoln Memorial");
// make the schedule
bus_schedule original_schedule;
bus_route route0;
bus_route route1;
{
// make a route
route0.append(bs0.get());
route0.append(bs1.get());
route0.append(bs2.get());
// add trips to schedule
original_schedule.append("bob", 6, 24, &route0);
original_schedule.append("bob", 9, 57, &route0);
original_schedule.append("alice", 11, 2, &route0);
}
{
// make aother routes
route1.append(bs3.get());
route1.append(bs2.get());
route1.append(bs1.get());
// add trips to schedule
original_schedule.append("ted", 7, 17, &route1);
original_schedule.append("ted", 9, 38, &route1);
original_schedule.append("alice", 11, 47, &route1);
}
// display the complete schedule
std::cout << "schedule" << original_schedule;
}
印刷:
schedule
6:24 bob
34º135'52.56" 134º22'78.3" 24th Street and 10th Avenue
35º137'23.456" 133º35'54.12" State street and Cathedral Vista Lane
35º136'15.456" 133º32'15.3" White House
9:57 bob
34º135'52.56" 134º22'78.3" 24th Street and 10th Avenue
35º137'23.456" 133º35'54.12" State street and Cathedral Vista Lane
35º136'15.456" 133º32'15.3" White House
11:2 alice
34º135'52.56" 134º22'78.3" 24th Street and 10th Avenue
35º137'23.456" 133º35'54.12" State street and Cathedral Vista Lane
35º136'15.456" 133º32'15.3" White House
7:17 ted
35º134'48.789" 133º32'16.23" Lincoln Memorial
35º136'15.456" 133º32'15.3" White House
35º137'23.456" 133º35'54.12" State street and Cathedral Vista Lane
9:38 ted
35º134'48.789" 133º32'16.23" Lincoln Memorial
35º136'15.456" 133º32'15.3" White House
35º137'23.456" 133º35'54.12" State street and Cathedral Vista Lane
11:47 alice
35º134'48.789" 133º32'16.23" Lincoln Memorial
35º136'15.456" 133º32'15.3" White House
35º137'23.456" 133º35'54.12" State street and Cathedral Vista Lane
结论
为了方便地使用该数据结构,您可以使用示例中map
的循环:
std::list<
std::pair<bus_schedule::trip_info, bus_route*>>::const_iterator it;
for (it = bs.schedule.begin(); it != bs.schedule.end(); it++) {
os << it->first << *(it->second);
}
但是,在 C++17 中,您的编写方式与以下内容完全相同:
for (auto const& [info,route] : bs.schedule) { os << info << *route; }
您可以看到它[k, v]
使用结构化绑定来提取值类型的“第一”和“第二”部分。如果您的编译器中没有 C++17 功能,您始终可以手动执行相同操作:
for (auto const& pair : bs.schedule) {
trip_info const& info = pair.first;
bus_route const& route = *pair.second;
os << info << route;
}
环游private
会员
我认为这个数据结构不是典型的或“好”的惯用 C++。使用原始指针会导致内存管理错误(例如,反序列化路由的每一站都会泄露)。
添加到这个“装置”getter/setter上可能会给猪涂口红²。
相反,我会选择公开您需要公开的内容。这是一个从 main 打印详细信息的示例,而不会使operator<<
运算符过载:
// display the complete schedule
std::cout << "schedule";
for (auto const& [info,route] : original_schedule.schedule) {
std::cout << '\n' << info.hour << ':' << info.minute << ' ' << info.driver << ' ';
for (auto& stop : route->stops)
std::cout << '\n' << stop->latitude << stop->longitude << ' ' << stop->description();
}
打印和以前一样。
完整列表
#include <iostream>
#include <list>
#include <memory>
#include <string>
struct gps_position {
int degrees;
int minutes;
float seconds;
friend std::ostream& operator<<(std::ostream& os, const gps_position& gp) {
return os << ' ' << gp.degrees << "º" << gp.minutes << "'" << gp.seconds << '"';
}
};
/////////////////////////////////////////////////////////////
// One bus stop
struct bus_stop {
gps_position latitude, longitude;
[[nodiscard]] virtual std::string description() const = 0;
virtual ~bus_stop() = default;
explicit bus_stop(gps_position _lat, gps_position _long)
: latitude(_lat), longitude(_long) {}
};
/////////////////////////////////////////////////////////////
// Several kinds of bus stops
struct bus_stop_corner : bus_stop {
std::string street1, street2;
[[nodiscard]] std::string description() const override {
return street1 + " and " + street2;
}
explicit bus_stop_corner(gps_position _lat, gps_position _long, std::string _s1, std::string _s2)
: bus_stop(_lat, _long), street1(std::move(_s1)), street2(std::move(_s2)) {}
};
struct bus_stop_destination : bus_stop {
std::string name;
[[nodiscard]] std::string description() const override { return name; }
bus_stop_destination(gps_position _lat, gps_position _long, std::string _name)
: bus_stop(_lat, _long), name(std::move(_name)) {}
};
struct bus_route {
std::list<bus_stop*> stops;
void append(bus_stop* _bs) { stops.push_back(_bs); }
};
/////////////////////////////////////////////////////////////
// a bus schedule is a collection of routes each with a starting time
struct bus_schedule {
struct trip_info { int hour, minute; std::string driver; };
void append(const std::string& _d, int _h, int _m, bus_route* _br) {
schedule.emplace(schedule.end(), trip_info{_h, _m, _d}, _br);
}
std::list<std::pair<trip_info, bus_route*>> schedule;
};
int main() {
// fill in the data
// make a few stops
auto bs0 = std::make_unique<bus_stop_corner>(
gps_position{ 34, 135, 52.560F }, gps_position{ 134, 22, 78.30F },
"24th Street", "10th Avenue");
auto bs1 = std::make_unique<bus_stop_corner>(
gps_position{ 35, 137, 23.456F }, gps_position{ 133, 35, 54.12F },
"State street", "Cathedral Vista Lane");
auto bs2 = std::make_unique<bus_stop_destination>(
gps_position{ 35, 136, 15.456F }, gps_position{ 133, 32, 15.300F },
"White House");
auto bs3 = std::make_unique<bus_stop_destination>(
gps_position{ 35, 134, 48.789F }, gps_position{ 133, 32, 16.230F },
"Lincoln Memorial");
// make the schedule
bus_schedule original_schedule;
bus_route route0;
bus_route route1;
{
// make a route
route0.append(bs0.get());
route0.append(bs1.get());
route0.append(bs2.get());
// add trips to schedule
original_schedule.append("bob", 6, 24, &route0);
original_schedule.append("bob", 9, 57, &route0);
original_schedule.append("alice", 11, 2, &route0);
}
{
// make aother routes
route1.append(bs3.get());
route1.append(bs2.get());
route1.append(bs1.get());
// add trips to schedule
original_schedule.append("ted", 7, 17, &route1);
original_schedule.append("ted", 9, 38, &route1);
original_schedule.append("alice", 11, 47, &route1);
}
// display the complete schedule
std::cout << "schedule";
for (auto const& [info,route] : original_schedule.schedule) {
std::cout << '\n' << info.hour << ':' << info.minute << ' ' << info.driver << ' ';
for (auto& stop : route->stops)
std::cout << '\n' << stop->latitude << stop->longitude << ' ' << stop->description();
}
}
请注意,即使删除所有空白行和注释并使用相同的格式,代码也比示例短 100 行。
¹ 请注意,代码显然根本不是客观上“高效”的,因为它执行各种动态分配和运行时多态性
² 这种反模式对于有传统 OOP 背景的人来说很常见,请参阅伪类/准类(PDF)
推荐阅读
- javascript - 在javascript中使用for循环内的switch case验证表单字段
- postgresql - 什么时候应该使用 PostgreSQL 索引包含?
- powershell - install-package:检测到包“Microsoft.Data.Sqlite”的依赖循环
- php - 如何使用 Codeigniter 数组使用 update_batch?
- javascript - 无需 JavaScript 且无需加载静态工具包即可加载单个 TypeKit 字体系列
- mysql - mysql从多个表中选择总和和平均值的数据
- java - 在任何线程上如何从对话框中获取值?
- javascript - 需要帮助创建动态导航菜单
- c# - 物体不动,如何让子弹动起来
- bash - AWS Lambda 随机触发 S3 上传