题
如果我有一个类如下
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_struct
我该在 Example_Class
例如,如果我这样做
struct example_struct foo_struct;
Example_Class foo_class = Example_Class();
memcpy(&foo_struct, &foo_class, sizeof(foo_struct));
将 foo_struct.x = 8
和 foo_struct.y = 9
(即:相同的价值观作为x、y值的foo_class)?
我想问的原因是我一个C++库(不想改变它的)就是分享的对象C码和我想用一个结构,以表示对象来自C++图书馆。我唯一感兴趣的对象的属性。
我知道这个理想的情况是有Example_class包裹以防万一共同结构之间的C和C++代码,但它不是一件容易改变C++图书馆在使用。
解决方案
C++标准 保证 忆布局的一个C struct
和一个C++ class
(或 struct
-同事)将是相同的,前提是用C++ class
/struct
符合条件的被 荚 ("普通的老数据")。所以,这是什么POD的意思吗?
一类或结构是POD,如果:
- 所有数据成员公众和自己荚或基本类型(但不参考或针对部件的类型),或列这样的
- 它没有用户定义的构造、分配运营商或析构
- 它没有虚拟的功能
- 它没有基类
关于只有"C++主义"允许非虚拟件的功能,静态成员和成员的职能。
因为你流的既有的构造和一析构,它是从形式上来说不的POD类型,所以担保不住脚的。(虽然,正如其他人已经提到的,在实践中的两个布局可能等同于任何编译器,你的尝试,因此,只要没有虚拟的功能)。
见第[26.7]的 C++常见问题的精简 更多的细节。
其他提示
example_struct的内存结构是否与Example_Class
中的结构相似
行为无法保证,并且与编译器有关。
话虽如此,答案是“是的,在我的机器上”,只要Example_Class不包含虚方法(并且不从基类继承)。
在您描述的情况下,答案是“可能是的”。但是,如果该类具有任何虚函数(包括可以从基类继承的虚析构函数),或者使用多重继承,那么类布局可能会有所不同。
添加其他人所说的内容(例如:编译器特定的,只要你没有虚函数就可能会有效):
如果您这样做,我强烈建议使用sizeof(Example_class)== sizeof(example_struct)的静态断言(编译时检查)。请参见BOOST_STATIC_ASSERT,或等效的编译器特定或自定义构造。如果某人(或某些东西,例如编译器更改)修改了类以使匹配无效,那么这是一个很好的第一道防线。如果你想要额外的检查,你也可以运行时检查成员的偏移量是否相同,哪些(与静态大小断言一起)将保证正确性。
在C ++编译器的早期,有一些例子,编译器首先用类更改struct关键字然后编译。关于相似之处。
差异来自类继承,尤其是虚函数。如果类包含虚函数,那么它必须在其布局的开头有一个指向描述符类型的指针。另外,如果B类继承自A类,则首先是A类的布局,然后是B类自己的布局。
因此,关于将类实例转换为结构实例的问题的准确答案是:取决于类的内容。对于具有方法(构造函数和非虚拟析构函数)的特定类,布局可能会相同。如果析构函数被声明为虚拟,那么布局在结构和类之间肯定会有所不同。
这篇文章显示从C结构到C ++类没有太多需要做的事情:第1课 - 从结构到班级
以下是解释如何将虚函数表引入具有虚函数的类的文章:第4课 - 多态性
课程& C ++中的结构是等价的,除了结构的所有成员默认都是公共的(默认情况下类成员是私有的)。这确保了在C ++编译器中编译遗留C代码将按预期工作。
没有什么能阻止你在结构中使用所有奇特的C ++特性:
struct ReallyAClass
{
ReallyAClass();
virtual !ReallAClass();
/// etc etc etc
};
当您想要将数据传递给C时,为什么不明确地将类的成员分配给结构?这样你就知道你的代码可以在任何地方使用。
您可能只是公开或私下从结构派生类。然后转换它将在C ++代码中正确解析。