簡體   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