Klassenobjekt in Strukturobjekt C / C ++ umwandeln
Ich habe zwei Projekte, eines in C und das andere in C ++, und ich versuche, ein Klassenobjekt in C ++ in ein Strukturobjekt in C umzuwandeln. Ich habe beispielsweise ein Objekt aus myClass, das ich wie folgt in myStru umwandeln möchte:
In meinem C ++ - Projekt habe ich diese Klasse:
class myClass{
myClass();
~myClass();
char *data;
int var;
}
In meinem C-Projekt habe ich folgende Struktur:
struct myStru {
char *data;
int var;
};
typedef struct myStru myStru;
Jetzt erstelle ich in meinem C ++ - Projekt ein Objekt aus myClass
:
myClass *classObj = new myClass();
classObj->data = new char[10];
classObj->var = 99;
In meinem C-Projekt erhalte ich classObj
als ungültigen Zeiger und versuche, ihn wie folgt umzuwandeln:
myStru *struObj = (myStru*)malloc(sizeof(struct myStru));
struObj = (myStru*) classObj;
printf(" struObj->var %d \n", struObj->var); // this print 99
Ich mache das später in meinem C ++ - Projekt
delete []classObj->data; // I know smart pointers can be used here but this is not my point in this question now
delete classObj;
Ist das, was ich hier mache, richtig? dh classObj
auf struObj
diese Weise gießen?
Das vollständige Beispiel finden Sie hier (danke @Borgleader) http://coliru.stacked-crooked.com/a/05543b944ee23f2f
BEARBEITEN: Ich habe in diesem Artikel eine gute Antwort auf meine Frage gefunden (siehe Zugreifen auf C ++ - Klassen von C aus): https://www.oracle.com/technical-resources/articles/it-infrastructure/mixing-c-and-cplusplus.html
Antworten
Ich bin nicht 100% sicher, weil es C ++ ist und Sie es niemals sein können, aber ich denke, dies ist ein undefiniertes Verhalten.
Sie können nicht über einen Zeiger auf ein Mitglied auf eine andere Struktur auf die Mitglieder einer Struktur zugreifen. Eine bemerkenswerte Ausnahme von dieser Regel besteht darin, auf die gemeinsame Anfangssequenz von zwei Strukturen zuzugreifen, die Mitglieder einer Gewerkschaft sind.
Dies könnte funktionieren, wenn Sie stattdessen Ihre Klasse von der Struktur geerbt haben.
Alternativ besteht die andere Ausnahme darin, dass Sie sicher memcpy
zwischen solchen Strukturen AFAIR wechseln können.
Bei dieser Frage geht es um Interoperabilität, und Sie erhalten nie eine endgültige Antwort, da sie auf implementierungsdefinierten Aspekten des C- und C ++ - Compilers beruht. Die struct
und die class
sind Layout-kompatible Typen in C ++. Es ist sehr klar, dass es kein Problem ist , eins a class
und eins a zu deklarieren, struct
und weil beide den gleichen Mitgliederzugriff für alle ihre Mitglieder haben (obwohl sie sich voneinander unterscheiden), sind sie kompatibel (zumindest ab C ++ 14, glaube ich). .
Das Beste, was der Standard bieten wird, ist:
Hinweis: Standardlayoutklassen sind nützlich für die Kommunikation mit Code, der in anderen Programmiersprachen geschrieben wurde. Ihr Layout ist in 12.2 angegeben. - Endnote
Es ist beabsichtigt, dass solche Klassen (die sowohl Standardlayout als auch Layoutkompatibel sind) interoperabel sind. Wenn Sie denselben Compiler in zwei Modi verwenden, wäre es "enttäuschend", wenn dies nicht funktionieren würde. Aber das ist das Beste, was Sie "enttäuschen" werden - überprüfen Sie die Dokumentation.
Ich wundere mich ein wenig über das Ressourcenmanagement in der Gesamtstrategie. Sie haben einen Destruktor in C ++ deklariert class
und das ist in Ordnung, nicht virtual
wahr!), Aber Sie kopieren ihn in einen struct
auf der C-Seite, wenn der C-Code eine 'destruktorähnliche' Funktion hat, um seine Objekte zu zerstören, die aufgrund von Ihnen zu Problemen führen können habe das C ++ - Objekt bitweise geklont (hoffentlich!).
Wenn C free(s->data)
seine Kopie eines in C ++ erstellten Objekts aufruft, das verwendet wurde new
, provozieren Sie undefiniertes Verhalten. Dies könnte der Ausnahmefall sein, malloc()
der aus Kompatibilitätsgründen die Verwendung auf der C ++ - Seite rechtfertigt .
Es ist wahrscheinlich in Ordnung, aber Sie verlassen sich auf Interoperabilitätsfunktionen zwischen C und C ++, und die beiden Standards bringen Sie so weit wie möglich, aber per Definition verwenden Sie implementierungsdefinierte Funktionen.
Durch diesen Hinweis wissen wir, dass der Standard bereit ist, zu funktionieren, und er wird es wahrscheinlich tun. Viel Glück!