C++ 和序列化:有啥方法可以进行某种内省吗?

Posted

技术标签:

【中文标题】C++ 和序列化:有啥方法可以进行某种内省吗?【英文标题】:C++ and serialization: is there any way to do some kind of introspection?C++ 和序列化:有什么方法可以进行某种内省吗? 【发布时间】:2011-11-15 11:12:01 【问题描述】:

我在Wikipedia 阅读了一些示例,但我正在寻找一些现实生活中的示例:如何使用自省、为什么(它有助于编写干净的代码)以及代码本身。

例如,有没有办法创建一个“通用”函数来序列化任何种类的对象?我的意思是:父级中只有一个函数,所有后代都可以将自己“保存”+“恢复”到文件中/从文件中“恢复”。

【问题讨论】:

“一切都在问题中”不是提出问题的好方法。除非您只使用完全标准的术语,否则您应该稍微解释一下您的问题并说明动机,并说明您试图从中得到什么。 【参考方案1】:

没有使用(因为它不存在),没有代码示例(因为它不存在),也没有理由尝试使用它(因为它不存在)。

您可以获得的最接近的是 RTTI/dynamic_cast。但这并不是真正的内省。

【讨论】:

【参考方案2】:

C++ 中有 RTTI,您也可以使用条件语句和dynamic_cast<>() 来达到此效果,但在 C++ 中,我们通常会在编译时尽可能多地努力。如果您觉得需要自省,是否有更好的方法可以通过静态方法实现您的目标。

【讨论】:

如果这听起来对你没有说服力,那一定是因为我含糊其辞。 能否具体一点,告诉我们你想要达到的目标是什么?【参考方案3】:

不是真的。您最接近的是RTTI。但是看看Qt metaobjects 看看他们是怎么做到的(也使用他们的moc 生成器)。

【讨论】:

【参考方案4】:

我建议你看看 boost::any

http://www.boost.org/doc/libs/1_47_0/doc/html/any.html

【讨论】:

boost::any 是一种 one-size-fits-all 类型,但我不明白它与内省有何关系... @AdrienPlisson 我不知道谁投了反对票,但boost::any 是 RTTI introspection(如链接的***文章中所述)如何的完美示例 用过。特别是,您可以查看any_cast 模板。 @Sga:如果您以@和名称开头评论,则会通知用户,这会提高他阅读您评论的机会。无论如何,+1 @DavidRodríguez-dribeas :我投了反对票。 boost::any 没有在 C++ 中提供任何内置的自省功能,它只是一个实现自省的“hack”。就像说C是一种动态编程语言一样,因为您可以使用python C库来执行一些python代码...【参考方案5】:

对于 C++,如果你必须“去那里”,则有 RTTI

More detailed example here on wikipedia

Extensive discussion on this topic already for reference

【讨论】:

【参考方案6】:

从链接的文章可以看出你指的是typeiddynamic_cast<>。您应该在问题中明确说明这一点,因为您很快就会发现很多人会直接跳转而不浏览链接。

现在,它们是如何/何时使用的?最简单的答案是通常不应该使用它。在大多数情况下,一个设计良好的程序不需要执行运行时类型检查,如果您发现自己这样做了,那么您的设计很可能有问题。

当然,所有事情都有例外,特别是@Sga 给出的例子是一个非常好的例子。在boost::any 中,库执行 type-erasure 以便能够在类型内保存 any 对象,然后在提取值时在any_cast 中手动使用 RTTI验证实际对象的类型是否正确。现在,这也不常见,大多数程序不使用 type-erasure,而且当它们使用时,很少需要在运行时分析类型。

【讨论】:

“在大多数情况下,一个设计良好的程序不需要执行运行时类型检查,如果你发现自己这样做了,那么你的设计很可能有问题。” => 怎么可能序列化一个类(创建一个“通用”序列化函数)?我认为序列化与“糟糕的设计”无关。 @OlivierPons 我并没有说它永远没有意义,只是在大多数情况下它没有意义。在您的特定示例中,我已经实现了几次序列化并且不需要手动 RTTI 检查,提供一个序列化虚拟函数并在对象上调用它,然后动态调度将发挥它的魔力。请注意,您首先需要可序列化的接口才能调用该函数... 是的,但是您所说的意味着您仍然必须在 每个 希望能够序列化自身的子节点上实现“序列化功能”。在 Java 或 php 中,由于自省,您只需编写此函数 once (序列化/反序列化实际上是 php 核心函数的一部分 => 参见 php.net/manual/fr/function.serialize.php) @olivierPons:是的,同意,但你现在谈论的是完全不同的事情:语言必须支持反射,并且比 c++ 中的手动 RTTI 访问强大得多。 C++ 不支持反射。在所有语言的上下文中,上面的句子是:在 C++ 中,运行时类型检查通常是代码异味。同样,通常情况下,有几个例子是有意义的(boost::any,for one)【参考方案7】:

正如其他人之前所说,内省不是 C++ 的一个特性,最接近它的是 typeid() 和 dynamic_cast,但你并不想那么接近。;)

所有权系统的精心设计、引用的传递和包含、policy-based design 的使用可用于摆脱这种自省需求:在严格的 OOP 世界中,不需要(应该)需要对象知道他们自己的类型(除了提供virtual 行为,如果这样定义)。

【讨论】:

以上是关于C++ 和序列化:有啥方法可以进行某种内省吗?的主要内容,如果未能解决你的问题,请参考以下文章

java中的serialVersionUID。 如果在本地的两个类中声明了两个值相同的这个变量,会有啥问题吗?

是否可以在 C++ 中序列化和反序列化一个类?

Serializable是接口吗?public class DeleteBean implements Serializable这个类去实现它有啥作用?

当通过覆盖 writeObject() 和 readObject() 可以进行自定义序列化时,java Externalization 有啥用? [复制]

有啥方法可以防止杰克逊中的字段反序列化?

Haskell 函数可以序列化吗?