Klassenobjekt in Strukturobjekt C / C ++ umwandeln

Nov 27 2020

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 classObjals 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 classObjauf struObjdiese 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

3 BartekBanachewicz Nov 27 2020 at 13:22

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 memcpyzwischen solchen Strukturen AFAIR wechseln können.

1 Persixty Nov 27 2020 at 17:08

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 structund die classsind Layout-kompatible Typen in C ++. Es ist sehr klar, dass es kein Problem ist , eins a classund eins a zu deklarieren, structund 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 classund das ist in Ordnung, nicht virtualwahr!), Aber Sie kopieren ihn in einen structauf 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!