【发布时间】:2022-01-11 17:01:22
【问题描述】:
我想在 C 和 C++ 之间共享一个类,其中 C 只能将它作为指针获取。然而,因为它是一个内部类,它不能被前向声明。相反,这是我们当前代码在一个通用头文件中所做的:
#ifdef __cplusplus
class Container {
public:
class Object {
public:
int x;
};
};
typedef Container::Object * PObject;
#else
typedef void* PObject;
#endif
这看起来违反了单一定义规则 (ODR),因为 C 和 C++ 使用 #ifdef 看到不同的定义。但是因为这是一个指针,我不确定这是否会造成真正的问题。
C 仅使用指针将其传递给 C++ 函数,它不直接对它做任何事情。比如通用头文件中的这段代码:
#ifdef __cplusplus
extern "C" {
#endif
int object_GetX(PObject pObject);
#ifdef __cplusplus
}
#endif /* __cplusplus */
这就像我们在 C++ 文件中实现它的方式:
int object_GetX(PObject pObject) {
return pObject->x;
}
我的问题是:
- 像这样违反 ODR 会导致任何实际问题吗?
- 如果是这样,是否有其他方便的方法可以将课程共享给 C?
【问题讨论】:
-
我个人不会有
typedef Container::Object * PObject;别名,只有不透明指针别名typedef void* PObject;。然后在需要时使用reinterpret_cast<Container::Object*>(...)。 -
不要将指针隐藏在 typedef 后面。
-
@Someprogrammerdude 我同意这可行,但它需要为每个添加的功能重复,所以我看看我们是否可以跳过这一步。这种方式也可能使 C++ 编译器有能力保护我不传递错误类型的指针,如果它也认为它是 void* 那么我们就失去了它。
-
我会(仍然是个人)将每个
extern "C"函数与实际成员 function 匹配,唯一的例外是“create”和“destroy”函数.我也永远不会使用 C++ 程序中的 C API。而且我几乎从不使用简单的“setter”和“getter”函数,而是尝试创建实现行为的函数。最后,我将废弃我的void*指针,转而使用molbdnilo's answer 中使用的不透明结构。 :)
标签: c++ c inner-classes conditional-compilation one-definition-rule