【问题标题】:Possible compatibility issues inheriting from a C struct从 C 结构继承的可能的兼容性问题
【发布时间】:2012-10-29 01:05:33
【问题描述】:

背景:我们正在用 C++ 实现一个动态库,它扩展了 C 程序的功能。对于 C 程序中使用的主要结构之一,我们想添加我们自己的库特定字段。目前,当我们需要一个新字段时,我们会很好地要求 C 程序的开发人员为我们添加一个字段,最终我们会遇到大量的铸造混乱。我想知道我们是否可以改为执行以下操作:

主程序头文件:

#ifdef __cplusplus
extern "C" {
#endif
/* ... */
typedef struct ImportantStruct {
/* Definitions */
} ImportantStruct
/* ... */
#ifdef __cplusplus
}
#endif

我们的头文件:

//...
class ObjectType : public ImportantStruct {
// Our extra fields
}
//...

我想我有两个问题:

1) 这合法吗?

2) 当 C 程序尝试使用对象的 struct 部分时,这会产生什么问题?

【问题讨论】:

  • 如果你只使用组合而不是继承,听起来生活会容易得多......
  • 你将如何处理你的 C 结构?您只是导入 C 结构吗?通常,从 C 结构继承是可以的 - 请记住 extern "C" 中的 C 代码由 C++ 编译器解析...
  • 我在理论上同意组合将是一个非常非常好的解决方案。如果我从头开始做这件事,我会立即使用合成。问题是我们目前有一个typedef ImportantStruct ObjectType 和许多直接访问字段的地方。如果我将 typedef 更改为继承,这些访问仍然是合法的,并且我可以更好地控制对象的生命周期。但是,由于组合可能有其他直接优势,我肯定会重新考虑它作为一种选择。

标签: c++ c language-interoperability


【解决方案1】:

由于ImportantStruct 是一个POD 结构(它自动具有标准布局),并且由于ObjectType 没有其他基本类型并且如果它没有虚拟方法,它也具有标准布局。因此它可以用作 C 中的结构体。

1) 这合法吗?

是的。

2) 当 C 程序尝试使用对象的 struct 部分时,这会产生什么问题?

如果您的 c 函数不尝试覆盖它,那么您是安全的。你可以像这样覆盖它:

void foo( struct ImportantStruct *s )
{
 memset( s,0, sizeof(*s) );
}

如果有,则取决于重要结构中的内容,以及是否有填充字节。

这样的结构:

typedef struct {
  int a;
  char b;
} ImportantStruct;

在创建基类时可能会删除填充字节。

无论如何,我会使用组合,并避免任何类型的问题。但是您必须确保它是第一个成员,并且 ObjectType 具有标准布局。

【讨论】:

    【解决方案2】:

    派生方法应该有效,只需注意结果对齐。 我不会对“扩展”POD 中的结果大小/偏移量做出假设。一些编译器可能会删除基类的填充。因此派生的 C++ POD 可能与 resp 的大小不同。扩展平面 C 结构。

    更多关于派生对象布局的细节:c-data-alignment-member-order-inheritance

    此外,为了扩展 POD,您可以在 class 上使用 struct 关键字。差别不大,只是结构成员默认是公共的。 它也表达了你的 POD 意图(尽管它没有被强制执行)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-24
      • 1970-01-01
      • 1970-01-01
      • 2011-04-04
      • 1970-01-01
      • 1970-01-01
      • 2020-07-31
      • 1970-01-01
      相关资源
      最近更新 更多