在随机访问文件中存储 class 数据的最佳实践
Best practice in storing class data in random access files
在 C 中,数据通常以 struct
数据类型组织。这非常方便保存在随机访问文件中,因为您可以在结构上使用 sizeof
跳转到您想要的记录。
我不清楚在 C++ 中执行此操作的最佳方法是什么,其中你有一个 class 数据(连同一些当然不需要保留的成员函数) .直接存储 class 似乎是错误的,因为这当然会包括指向函数的指针和那种一旦保存到文件就变成垃圾的东西。
我能想到的另一种方法是将 class 中需要持久化的成员数据更改为 struct
,并更改访问函数以查看内部数据结构.它似乎有点太纠结了,但似乎是避免将每个字段复制两次(一次在单独的 struct
中,一次在 class 中)的唯一合乎逻辑的方法。
这当然会在您拥有继承的那一刻分解,并且派生 class 添加新字段。虽然这几乎不是 C++ 和随机访问文件特有的问题,并且它在许多其他对象持久性方法(包括其他编程语言中流行的 ORM 包)中面临 different possible strategies even when saving to a database table for instance.
人们通常在 C++ 中使用什么 'defacto standard' 方法来将 class 数据保存在文件中?无需到处复制东西?
假设所有成员函数都是无状态的(成员函数内没有定义静态局部变量),C++ classes 和 C 风格的结构没有区别:您只序列化每个 class实例。
进一步说明,当您编写序列化程序(或更常见的使用序列化库)时,您永远不会存储 vtable,因为没有意义:只有成员数据特定于对象实例,而 vtable由 class 定义。
因此,拥有虚函数的唯一真正影响是您不再处理 POD 对象:您不能简单地将整个结构内存转储到磁盘上,并且必须一个接一个地序列化 class 实例
在 C++ 中,struct
和 class
之间的唯一区别是它们的默认可见性; struct
默认为 public,而 class
默认为私有。用 struct
可以做的任何事情都可以用 class
来完成。两者都可以有构造函数、析构函数、成员函数、基类型、虚成员等
只要类型是平凡可复制的(即该类型具有平凡析构函数、复制构造函数、移动构造函数、复制赋值运算符和移动赋值运算符),或者 POD 类型(如果您使用的是 C++98) , 然后它可以像在 C 中一样序列化到一个文件。请注意,任何具有虚拟成员的类型,或者从具有虚拟成员的类型继承(虚拟或其他方式)的类型都不是简单可复制的。
编辑:非虚拟成员函数不影响类型的布局。没有指向此类函数的指针存储在对象本身中。
简答:视情况而定
中等答案:这取决于 C 结构是否可以直接序列化。
长答案:如果 class A
只是普通旧数据,它将像使用 C 结构一样可序列化,即二进制复制和加载 sizeof(A)
字节。如果 class 仅包含原始类型成员或它们的数组,and/or 子对象本身就是 POD,则它是 POD 对象。它可以有方法或静态方法,但没有虚拟方法(甚至没有虚拟析构函数)。
例如 char 数组是可以接受的,但没有指针、没有字符串、没有引用,并且(一般来说)没有来自标准库的对象(特别是没有 std::string)。
当然,由于它直接存储和加载二进制数据表示,因此肯定不能跨不同架构移植,但可用于本地保存状态。
在 C 中,数据通常以 struct
数据类型组织。这非常方便保存在随机访问文件中,因为您可以在结构上使用 sizeof
跳转到您想要的记录。
我不清楚在 C++ 中执行此操作的最佳方法是什么,其中你有一个 class 数据(连同一些当然不需要保留的成员函数) .直接存储 class 似乎是错误的,因为这当然会包括指向函数的指针和那种一旦保存到文件就变成垃圾的东西。
我能想到的另一种方法是将 class 中需要持久化的成员数据更改为 struct
,并更改访问函数以查看内部数据结构.它似乎有点太纠结了,但似乎是避免将每个字段复制两次(一次在单独的 struct
中,一次在 class 中)的唯一合乎逻辑的方法。
这当然会在您拥有继承的那一刻分解,并且派生 class 添加新字段。虽然这几乎不是 C++ 和随机访问文件特有的问题,并且它在许多其他对象持久性方法(包括其他编程语言中流行的 ORM 包)中面临 different possible strategies even when saving to a database table for instance.
人们通常在 C++ 中使用什么 'defacto standard' 方法来将 class 数据保存在文件中?无需到处复制东西?
假设所有成员函数都是无状态的(成员函数内没有定义静态局部变量),C++ classes 和 C 风格的结构没有区别:您只序列化每个 class实例。
进一步说明,当您编写序列化程序(或更常见的使用序列化库)时,您永远不会存储 vtable,因为没有意义:只有成员数据特定于对象实例,而 vtable由 class 定义。 因此,拥有虚函数的唯一真正影响是您不再处理 POD 对象:您不能简单地将整个结构内存转储到磁盘上,并且必须一个接一个地序列化 class 实例
在 C++ 中,struct
和 class
之间的唯一区别是它们的默认可见性; struct
默认为 public,而 class
默认为私有。用 struct
可以做的任何事情都可以用 class
来完成。两者都可以有构造函数、析构函数、成员函数、基类型、虚成员等
只要类型是平凡可复制的(即该类型具有平凡析构函数、复制构造函数、移动构造函数、复制赋值运算符和移动赋值运算符),或者 POD 类型(如果您使用的是 C++98) , 然后它可以像在 C 中一样序列化到一个文件。请注意,任何具有虚拟成员的类型,或者从具有虚拟成员的类型继承(虚拟或其他方式)的类型都不是简单可复制的。
编辑:非虚拟成员函数不影响类型的布局。没有指向此类函数的指针存储在对象本身中。
简答:视情况而定
中等答案:这取决于 C 结构是否可以直接序列化。
长答案:如果 class A
只是普通旧数据,它将像使用 C 结构一样可序列化,即二进制复制和加载 sizeof(A)
字节。如果 class 仅包含原始类型成员或它们的数组,and/or 子对象本身就是 POD,则它是 POD 对象。它可以有方法或静态方法,但没有虚拟方法(甚至没有虚拟析构函数)。
例如 char 数组是可以接受的,但没有指针、没有字符串、没有引用,并且(一般来说)没有来自标准库的对象(特别是没有 std::string)。
当然,由于它直接存储和加载二进制数据表示,因此肯定不能跨不同架构移植,但可用于本地保存状态。