C ++ Class或Struct与C struct的兼容性

时间:2009-09-15 20:29:01

标签: c++ class data-structures

是否可以编写与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;
};

7 个答案:

答案 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)

  • 在两种语言中使用相同类型的相同类型
  • 确保该课程中没有任何虚拟内容(因此您不会将vtable指针卡在前面)
  • 根据所使用的编译器,您可能需要调整结构包装(通常使用编译指示)以确保兼容性。

(适用编辑)

  • 此外,您必须注意使用编译器检查sizeof()类型。例如,我遇到了一个将短路存储为32位值的编译器(当大多数将使用16位时)。更常见的情况是,32位架构上的int通常为32位,64位架构上为64位。

答案 2 :(得分:5)

POD适用于C ++。你可以拥有会员功能。 "A POD type in C++ is an aggregate class that contains only POD types as members, has no user-defined destructor, no user-defined copy assignment operator, and no nonstatic members of pointer-to-member type"

您应该设计您的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,反之亦然。我希望你只是为了移动东西而只想要这些指针。