В таких вопросах, как это, совместимость между классами/структурами C++ и C-структуры объясняются настолько, насколько это возможно, если все элементы имеют один и тот же тип, в одном и том же порядке и не объявлены виртуальные члены.
Это моя проблема. У меня есть виртуальные методы, и я бы очень хотел сохранить их при работе со структурой в C++.
Давайте рассмотрим этот игрушечный пример. Это должна быть совместимая с C и C++ структура, определенная в одном заголовочном файле.
моястр.ч:
#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++, виртуальная таблица будет мешать выравниванию:
тест.ч:
#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);
}
основной.с:
#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)
(предполагая, что это связано с тем, что функция С++ пытается прочитать data
из-за конца выделенной памяти структуры)
Каков наилучший способ включить эту совместимость C-C++, сохраняя при этом возможность использования виртуальных функций в C++?