[英]Using C++ struct with virtual members (i.e. non-POD) in C
在的問題,如本 ,C ++類/結構和C的結構之間的兼容性,作為可能的,只要所有成員都是同一類型的說明的那樣,以相同的順序,並且沒有虛擬成員聲明。
那是我的問題。 我有虛擬方法,我非常希望在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結構。 無論實施如何,對齊問題仍然存在。
在這個例子中,如果編寫了一個將mystr
實例mystr
給C ++函數的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 ++互操作性的最佳方法是什么?
我不建議你用#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
使其混亂,這是我不建議的,因為如果您需要重構代碼會很不方便。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.