【问题标题】:How to declare a pointer to a nested C++ class in C [duplicate]如何在C中声明指向嵌套C++类的指针[重复]
【发布时间】:2021-12-22 01:28:12
【问题描述】:

我在 C++ 中有一个嵌套类,我希望 C 代码能够使用它。因为它是嵌套的,所以我不能将它转发给 C,所以我们在共享头文件中有这样的代码:

#ifdef __cplusplus
class Mgr {
public:
    class Obj {
        public:
        int x;
    };
};

typedef Mgr::Obj * PObj;
#else

typedef void* PObj;

#endif

这导致 C 和 C++ 各自看到 PObj 的不同定义,我担心这违反了单一定义规则。但是它“只是”一个指针,所以我不确定这是否会出错。

除了将指针传递给作为方法包装器的 C++ 函数之外,C 对指针不做任何事情。例如,我们将在组合标题中包含它:

#ifdef __cplusplus
extern "C" {
#endif
int obj_GetX(PObj pObj);

#ifdef __cplusplus
}
#endif /* __cplusplus */

以此作为 C++ 文件中的实现:

int obj_GetX(PObj pObj) {
    return pObj->x;
}

所以:

  1. 这真的是个问题吗?
  2. 如果是这样,在 C 和 C++ 之间共享此指针的最佳方式是什么

【问题讨论】:

  • C++ 中的PObj 类型需要什么?对我来说,它看起来像是你在 C++ 中永远不需要的东西,而且只有在 C 中。如果你能做到这一点,你可以省略 C++ typedef,并且永远不会有冲突的类型。
  • 好吧,C 代码也不能直接创建嵌套类的实例,因为类定义是 C 中可诊断的错误。您可以做的最好的事情是让 Mgr::Obj 被视为C 中的不透明指针和void * 和任何一个一样好。要使用这样的指针做几乎任何事情(例如访问或修改对象的成员),而不是将其与其他此类指针进行比较,您的 C 代码需要将 void * 传递回 C++ 代码。任何 C 代码试图直接对实际对象的成员做的事情(没有用 C++ 编写的适当函数的帮助)都会导致未定义的行为。
  • @Peter 我添加了对 C 对这个问题的作用的解释。它只将它传递给 C++ 方法的包装函数。

标签: c++ c inner-classes conditional-compilation one-definition-rule


【解决方案1】:

这本身不是问题,但是当您在 C++ 代码中将 void * 转换回 Mgr::Obj * 时,您可能会违反 strict aliasing 规则。

对此没有好的解决方案 - (对我而言)这是标准中的明显遗漏。您能做的最好的事情是编译任何使用-fno-strict-aliasing 标志进行此类转换的代码。我经常这样做,并且以这种方式执行演员表从来没有遇到过问题。

【讨论】:

  • 我在问题中添加了用法示例,但我不明白严格的别名问题,你能解释一下吗?注意C++代码不强制转换,C和C++都在函数签名中看到自己理解的类型,所以不需要强制转换。
  • 啊,我明白了,这有点偷偷摸摸。可能没问题,但我不确定这样在编译器的眼睛上拉扯羊毛是否有问题。为了以防万一,我会编译您将 PObj 传递给 C 的任何 C++ 方法,并设置 -fno-strict-aliasing
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多