56

如果我有如下课程

   class Example_Class 
   {
       private:
         int x; 
         int y; 
       public: 
         Example_Class() 
         { 
             x = 8;
             y = 9;
         }
       ~Example_Class() 
       { } 
   };

结构如下

struct
{
   int x;
   int y;
} example_struct;

记忆中的结构 example_structExample_Class

例如,如果我执行以下操作

struct example_struct foo_struct;
Example_Class foo_class = Example_Class();

memcpy(&foo_struct, &foo_class, sizeof(foo_struct));

foo_struct.x = 8foo_struct.y = 9(即:与 foo_class 中的 x,y 值相同的值)?

我问的原因是我有一个 C++ 库(不想更改它),它与 C 代码共享一个对象,我想使用一个结构来表示来自 C++ 库的对象。我只对对象的属性感兴趣。

我知道理想的情况是让 Example_class 围绕 C 和 C++ 代码之间的公共结构进行包装,但要更改正在使用的 C++ 库并不容易。

4

8 回答 8

75

C++ 标准保证structC和 C++ class(或-- 相同的东西)的内存布局struct将是相同的,只要 C++ class/struct符合POD(“普通旧数据”)的标准。那么 POD 是什么意思呢?

如果满足以下条件,则类或结构是 POD:

  • 所有数据成员都是公共的,它们本身是 POD 或基本类型(但不是引用或指向成员的类型),或此类的数组
  • 它没有用户定义的构造函数、赋值运算符或析构函数
  • 它没有虚函数
  • 它没有基类

关于唯一允许的“C++ 主义”是非虚拟成员函数、静态成员和成员函数。

由于您的类同时具有构造函数和析构函数,因此正式地说不是 POD 类型,因此保证不成立。(尽管正如其他人所提到的,实际上这两种布局在您尝试的任何编译器上都可能是相同的,只要没有虚函数)。

有关更多详细信息,请参阅C++ FAQ Lite的第 [26.7] 节。

于 2009-01-08T05:30:13.643 回答
10

example_struct 的内存结构是否与 Example_Class 中的结构相似

该行为无法保证,并且取决于编译器。

话虽如此,答案是“是的,在我的机器上”,前提是 Example_Class 不包含虚拟方法(并且不从基类继承)。

于 2009-01-08T01:02:35.180 回答
7

在您描述的情况下,答案是“可能是”。但是,如果该类有任何虚函数(包括可以从基类继承的虚析构函数),或者使用多重继承,那么类布局可能会有所不同。

于 2009-01-08T01:02:45.990 回答
3

添加到其他人所说的内容(例如:特定于编译器,只要您没有虚函数就可能会起作用):

如果你这样做,我强烈建议 sizeof(Example_class) == sizeof(example_struct) 的静态断言(编译时检查)。请参阅 BOOST_STATIC_ASSERT,或等效的编译器特定或自定义构造。如果有人(或某事,例如编译器更改)修改类以使匹配无效,这是一个很好的第一道防线。如果您需要额外检查,您还可以在运行时检查成员的偏移量是否相同,这(与静态大小断言一起)将保证正确性。

于 2009-01-08T01:49:25.350 回答
2

在 C++ 编译器的早期,有编译器首先用 class 更改 struct 关键字然后编译的例子。关于相似之处太多了。

差异来自类继承,尤其是虚函数。如果类包含虚函数,那么它必须在其布局的开头有一个指向类型描述符的指针。另外,如果 B 类继承自 A 类,那么 A 类的布局首先出现,然后是 B 类自己的布局。

因此,关于将类实例转换为结构实例的问题的确切答案是:取决于类内容。对于具有方法(构造函数和非虚拟析构函数)的特定类,布局可能是相同的。如果析构函数被声明为虚拟的,那么结构和类之间的布局肯定会变得不同。

这是一篇文章,它表明从 C 结构到 C++ 类不需要做太多工作:第 1 课 - 从结构到类

这里是解释如何将虚函数表引入具有虚函数的类的文章:第 4 课 - 多态性

于 2013-12-22T09:06:30.367 回答
0

C++ 中的类和结构是等价的,除了结构的所有成员默认情况下都是公共的(类成员默认情况下是私有的)。这可确保在 C++ 编译器中编译遗留 C 代码将按预期工作。

没有什么能阻止您在结构中使用所有花哨的 C++ 功能:

struct ReallyAClass
{
    ReallyAClass();
    virtual !ReallAClass();

    /// etc etc etc
};
于 2009-01-08T01:52:40.507 回答
0

当您想将数据传递给 C 时,为什么不将类的成员显式分配给结构?这样你就知道你的代码可以在任何地方工作。

于 2009-01-08T05:43:58.590 回答
-2

您可能只是公开或私下从结构派生类。然后强制转换它会在 C++ 代码中正确解析。

于 2009-01-08T06:39:00.587 回答