是否可以编写与C struct完全兼容的C ++类或结构。兼容性我指的是对象的大小和变量的内存位置。我知道使用*(point*)&pnt
甚至(float*)&pnt
(在变量是浮点数的不同情况下)是邪恶的,但考虑到性能需要它真的需要它。使用普通型铸造操作员每秒百万次是不合逻辑的。
以此为例
Class Point {
long x,y;
Point(long x, long y) {
this->x=x;
this->y=y;
}
float Distance(Point &point) {
return ....;
}
};
C版是POD结构
struct point {
long x,y;
};
答案 0 :(得分:19)
最干净的是要从C结构继承:
struct point
{
long x, y;
};
class Point : public struct point
{
public:
Point(long x, long y)
{ this->x=x; this->y=y; }
float Distance(Point &point)
{ return ....; }
}
C ++编译器保证C样式结构点具有与C编译器相同的布局。 C ++类Point为其基类部分继承了这种布局(因为它不添加数据或虚拟成员,所以它将具有相同的布局)。指向类Point的指针将转换为指向struct point的指针而不使用强制转换,因为始终支持转换为基类指针。因此,您可以使用类Point对象并自由地将指针传递给C函数,期望指向struct point的指针。
当然,如果已经有一个定义结构点的C头文件,那么你可以只包括它而不是重复定义。
答案 1 :(得分:8)
是
(适用编辑)强>
答案 2 :(得分:5)
您应该设计您的POD数据结构,使它们具有自然对齐,然后它们可以在不同体系结构上由不同编译器创建的程序之间传递。自然对齐是任何成员的记忆偏移可以被该成员的大小整除的地方。 IE:一个浮点数位于一个可被4整除的地址,一个双重位于一个可被8整除的地址上。如果你声明一个字符后跟一个浮点数,大多数架构将填充3个字节,但有些可以设想填充1个字节。如果你声明一个浮点数跟着一个字符串,那么所有的编译器(我应该为这个声明添加一个来源,抱歉)都不会填充。
答案 3 :(得分:1)
C和C ++是不同的语言,但一直是C ++的意图,你可以拥有一个以二进制兼容方式支持这两种语言的实现。因为它们是不同的语言,所以它始终是编译器实现细节,是否实际支持它。通常,提供C和C ++编译器(或具有两种模式的单个编译器)的供应商支持完全兼容传递 POD结构(以及指向 POD结构的指针)在C ++代码和C代码之间。
通常,仅仅使用用户定义的构造函数会破坏保证,尽管有时您可以将指向此类对象的指针传递给C函数,期望指向具有相同数据结构的struct
指针并且它将起作用。
简而言之:检查编译器文档。
答案 4 :(得分:1)
在C和C ++中使用相同的“struct”。如果要在C ++实现中添加方法,只要不添加数据成员或虚函数,就可以继承结构,大小应该相同。
请注意,如果您有一个空结构或数据成员是空结构,则它们在C和C ++中的大小不同。在C中,sizeof(empty-struct)== 0虽然在C99中,不允许使用空结构(但无论如何都可以支持作为“编译器扩展”)。在C ++中,sizeof(empty-struct)!= 0(典型值为1)。
答案 5 :(得分:0)
除了其他答案之外,我肯定不会将任何访问说明符(public:,private:etc)放入您的C ++类/结构中。 IIRC允许编译器根据可见性重新排序成员变量块,以便private: int a; pubic: int b;
可以获得a和b交换轮。请参阅此链接:http://www.embedded.com/design/218600150?printable=true
我承认对为什么POD的定义不包括禁止这种效果感到困惑。
答案 6 :(得分:-2)
只要你的类没有表现出某种类似的高级特征,比如增长虚拟的东西,它应该是几乎相同的结构。
此外,您可以将Class
(由于大写无效,无论如何)更改为struct
而不会造成任何伤害。除了会员将公开(他们现在是私人)。
但是现在我想到你在谈论类型转换......你无法通过转换指针类型将float
变成代表相同值的long
,反之亦然。我希望你只是为了移动东西而只想要这些指针。