【问题标题】:cast class object to struct object C/C++将类对象转换为结构对象 C/C++
【发布时间】:2021-03-10 06:18:01
【问题描述】:

我有两个项目,一个在 C 中,另一个在 C++ 中,我尝试将 C++ 中的类对象转换为 C 中的结构对象。例如,我有一个来自 myClass 的对象,我试图将其转换为 myStru如下:

在我的 C++ 项目中,我有这个类:

class myClass{
    myClass();
    ~myClass();
    char    *data;
    int     var;
}

在我的 C 项目中,我有这样的结构:

struct myStru {
    char  *data;
    int    var;
};
typedef struct myStru myStru;

现在在我的 C++ 项目中,我从 myClass 创建一个对象:

myClass *classObj = new myClass();
classObj->data = new char[10];
classObj->var  = 99;

在我的 C 项目中,我收到 classObj 作为 void 指针,我尝试将其转换如下:

myStru *struObj = (myStru*)malloc(sizeof(struct myStru));
struObj = (myStru*) classObj;
printf(" struObj->var %d \n", struObj->var); // this print 99

我稍后会在我的 C++ 项目中这样做

   delete []classObj->data; // I know smart pointers can be used here but this is not my point in this question now
    delete  classObj;

我在这里做的对吗?即,以这种方式将classObj 转换为struObj

完整的例子可以在这里找到(感谢@Borgleader) http://coliru.stacked-crooked.com/a/05543b944ee23f2f

编辑: 我在这篇文章中找到了我的问题的一个很好的答案(请参阅从 C 中访问 C++ 类): https://www.oracle.com/technical-resources/articles/it-infrastructure/mixing-c-and-cplusplus.html

【问题讨论】:

  • 我相信这是未定义的行为,因为类型不同。
  • 如果您实际上同时使用 C 和 C++,请在问题中澄清。大多数情况下,当只有一个合适时,这两者被错误地标记在一起
  • 我很确定它是 UB,因为这些类型不兼容,但我正在努力证明这一点。
  • Structs 可以作为基类,所以使用 myStru 作为 myClass 的基类。
  • AFAICT,没有明确定义的方法可以在它们之间进行转换(然后访问它们)。正确的做法是定义myStru 结构并从中派生myClass。 (此外,您的“C”示例使用 C++ 并存在内存泄漏。)

标签: c++ c struct


【解决方案1】:

我不是 100% 确定,因为它是 C++,你永远不可能,但我认为这是未定义的行为。

您不能通过指向另一个结构的成员的指针来访问结构的成员。该规则的一个显着例外涉及访问作为联合成员的两个结构的公共初始序列。

如果你实际上是从结构继承你的类,这可能会起作用。

另外,另一个例外是您可以在此类结构之间安全地memcpy,AFAIR。

【讨论】:

【解决方案2】:

这个问题是关于互操作性的,您永远不会得到明确的答案,因为它依赖于 C 和 C++ 编译器的实现定义方面。 structclass 是 C++ 术语中的布局兼容类型。 很明显,声明一个 class 和一个 struct 不是问题,因为它们对所有成员都具有相同的成员访问权限(尽管彼此不同)是兼容的(至少在 C+ 中) +14 起我相信)。

该标准将提供的最佳效果是:

注意:标准布局类对于与代码进行通信很有用 用其他编程语言编写。它们的布局在 12.2. ——尾注

意图是这样的类(标准布局和布局兼容)是可互操作的。如果您在两种模式下使用相同的编译器,那么如果这不起作用,它会“令人失望”。 但这是你会得到“令人失望”的最好结果——查看文档。

我确实有点想知道整体战略中的资源管理。您已经在 C++ class 中声明了一个析构函数,这很好,它不是 virtual!),但是如果 C 代码有一个“类似析构函数”的函数来销毁,那么您将它复制到 C 端的 struct 中它的对象可能会导致麻烦,因为您已经按位克隆了 C++ 对象(希望如此!)。

如果 C 在其使用 C++ 构造的对象的副本上调用 free(s->data),该对象使用了 new,则您将引发未定义行为。 这可能是保证在 C++ 端使用malloc() 以实现兼容性的例外情况。

所以这可能没问题,但您依赖于 C 和 C++ 之间的互操作性功能,这两个标准尽可能地带您走得更远,但根据定义,您使用的是实现定义的功能。

通过该注释,我们知道该标准愿意并且很可能会起作用。 祝你好运!

【讨论】:

    猜你喜欢
    • 2020-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-23
    相关资源
    最近更新 更多