我有一个C结构,可用于各种 C和C++ 代码(通过extern "C"
)。
#ifdef __cplusplus
extern "C" {
#endif
typedef struct A A;
struct A {
/*some members*/
};
#ifdef __cplusplus
}
#endif
分配,初始化和释放是由我控制下的独立成员函数完成的,但是我不控制对成员的访问,因为可以在各处访问它们。
麻烦的是,我无法在整个系统中大量使用的 header 中更改
struct
的定义,但是我仍然想扩展类型并添加一些成员。由于必须同时编译为C++和C,因此我不能简单地创建派生类型struct B : public A
。所以我的想法是将此类型添加到cpp文件中:#ifdef __cplusplus
extern "C" {
#endif
typedef struct B B;
struct B {
A parent; // <---- public inheritance
/*some members*/
};
#ifdef __cplusplus
}
#endif
现在,我可以修改cpp文件中的所有函数,但是我仍然必须在编译单元之外分发并接受
A*
,因为没人知道B
是什么。因此,我想知道是否存在一种理智且定义明确的方法。我可以简单地将
B*
转换为A*s
并返回,还是必须将它们显式转换:A* static_cast_A(B* b) {
return &(b->parent);
}
B* static_cast_B(A* a) {
B* const b = 0;
unsigned const ptrdiff = (unsigned)((void*)(&(b->parent)));
return (B*)(((void*)a)-ptrdiff);
}
还有其他问题吗?还是应该完全不同地做?
最佳答案
对齐要求不会引起任何问题,这确实是C中伪造继承的默认方式。
但是,您的static_cast_B()
不可移植(特别是void *
算术,如果是unsigned
,则转换为sizeof (void *) > sizeof (unsigned)
-后者仍然可以工作,但是有点代码味道)。
我建议改用以下代码:
#include <stddef.h>
B* static_cast_B(A* a) {
return (B*)((char*)a - offsetof(B, parent));
}