将 C 识别的指针类型定义为内部 C++ 类

gil*_*_bz 2 c c++ conditional-compilation inner-classes one-definition-rule

我有一个类想要在 C 和 C++ 之间共享,其中 C 只能将其作为指针获取。然而,因为它是一个内部类,所以不能向前声明。相反,这就是我们当前的代码在公共头文件中所做的事情:

#ifdef __cplusplus
class Container {
public:
    class Object {
        public:
        int x;
    };
};

typedef Container::Object * PObject;
#else

typedef void* PObject;

#endif
Run Code Online (Sandbox Code Playgroud)

这看起来违反了单一定义规则 (ODR),因为 C 和 C++ 使用#ifdef. 但因为这是一个指针,所以我不确定这是否会产生真正的问题。C 仅使用指针将其传递给 C++ 函数,它不会直接用它执行任何操作。例如公共头文件中的这段代码:

#ifdef __cplusplus
extern "C" {
#endif
int object_GetX(PObject pObject);

#ifdef __cplusplus
}
#endif /* __cplusplus */
Run Code Online (Sandbox Code Playgroud)

这就是我们在 C++ 文件中实现它的方式:

int object_GetX(PObject pObject) {
    return pObject->x;
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  1. 像这样违反 ODR 会造成任何实际问题吗?
  2. 如果是这样,是否有另一种方便的方法将类共享给C?

mol*_*ilo 5

首先,类型别名指针通常会带来麻烦。
不要这样做。

其次,“内部”类是一个被过度使用的概念,所以我的第一反应是考虑它是否真的有必要。

如果有必要,您可以定义一个不透明的空类型并从中派生以实现某种类型安全:

在共享标头中:

struct OpaqueObject;

#ifdef __cplusplus
extern "C" {
#endif

int object_GetX(OpaqueObject* pObject);

#ifdef __cplusplus
}
#endif /* __cplusplus */
Run Code Online (Sandbox Code Playgroud)

在 C++ 头文件中:


struct OpaqueObject {};

class Container {
public:
    class Object : public OpaqueObject {
        public:
        int x;
    };
};


Run Code Online (Sandbox Code Playgroud)

执行:

int object_GetX(OpaqueObject* pObject) {
    return static_cast<Container::Object*>(pObject)->x;
}
Run Code Online (Sandbox Code Playgroud)