在诸如this之类的问题中,只要所有成员具有相同的类型,顺序相同,并且没有声明虚拟成员,就可以解释C ++类/结构和C结构之间的兼容性。 / p>
那是我的问题。我有虚方法,我非常想在C ++中操作结构时保留它们。
让我们来看看这个玩具示例。它意味着在单个头文件中定义的C和C ++兼容结构。
mystr.h:
#ifdef __cplusplus
#include <string>
struct mystr_base {
virtual ~mystr_base() {}
virtual std::string toString() = 0;
};
#endif
#ifdef __cplusplus
extern "C" {
#endif
struct mystr
#ifdef __cplusplus
: public mystr_base
#endif
{
const char* data;
#ifdef __cplusplus
std::string toString() {
return std::string(data);
}
#endif
};
#ifdef __cplusplus
}
#endif
这可能不是很漂亮,但是会为这个例子做。在实际场景中,C和C ++变体可能位于不同的头文件中,C ++结构扩展了POD结构。无论实施如何,对齐问题仍然存在。
使用此示例,如果编写的C程序将mystr
的实例传递给C ++函数,则vtable将干扰对齐:
test.h:
#include "mystr.h"
#ifdef __cplusplus
extern "C"
#endif
void mycxxfunc(struct mystr str);
TEST.CPP:
#include <stdio.h>
#include "test.h"
void mycxxfunc(mystr str) {
printf("mystr: %s\n", str.data);
}
main.c中:
#include "test.h"
int main(int argc, char** argv) {
const char* testString = "abc123";
struct mystr str;
str.data = testString;
mycxxfunc(str);
}
$ g++ -c test.cpp && gcc main.c test.o
$ ./a.out
Segmentation fault (core dumped)
(假设这是因为C ++函数试图从结构的已分配内存的末尾读取data
)
在保留在C ++中使用虚拟功能的能力的同时,启用此C-C ++互操作性的最佳方法是什么?
答案 0 :(得分:2)
我不建议您使用#ifdefs
混乱头文件。
如果您想同时保留某种虚拟化和C兼容性,那么在这种情况下您应该做的第一件事是:
一个想法如下。
标题文件:
struct MyStrImpl;
struct MyStr {
MyStrImpl * impl;
};
extern "C" MyReturnType myFunction(MyStr myStr);
.cpp
文件中的实施:
struct MyCppString {
virtual ...
};
#ifdef __cplusplus
struct MyStrImpl : public MyCppString {
};
#else
struct MyStrImpl {
};
#endif
MyStr::MyStr() : impl{new MyStrImpl{}} {
}
这样你就有了一个可以在C和C ++中使用的类型。
优点:
#ifdef
。缺点:
您不能同时在头文件中同时使用C兼容类型和虚函数,而不会使用#ifdef
使其混乱,这是我不建议的,因为如果您需要重构代码会很不方便