繁体   English   中英

在C中使用C ++ struct和虚拟成员(即非POD)

[英]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兼容性,那么在这种情况下您应该做的第一件事是:

  1. 使您的C ++和C类型成为表示的不透明指针。
  2. 将实现细节放在.cpp文件中。

一个想法如下。

头文件:

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 / C ++和两种语言的消耗品。

缺点:

  • 由于外部“C”而失去超载。
  • 必须使用C风格的接口(但可以使用C ++实现 - 就像.cpp文件中的虚函数接口一样。

您不能同时在头文件中同时使用C兼容类型和虚函数,而不会使用#ifdef使其混乱,这是我不建议的,因为如果您需要重构代码会很不方便。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM