lanzar objeto de clase a objeto de estructura C / C ++

Nov 27 2020

Tengo dos proyectos, uno en C y el otro en C ++ y trato de convertir un objeto de clase en C ++ a un objeto de estructura en C. Por ejemplo, tengo un objeto de myClass que estoy tratando de convertir en myStru de la siguiente manera:

En mi proyecto C ++ tengo esta clase:

class myClass{
    myClass();
    ~myClass();
    char    *data;
    int     var;
}

En mi proyecto C tengo esta estructura:

struct myStru {
    char  *data;
    int    var;
};
typedef struct myStru myStru;

Ahora en mi proyecto de C ++ creo un objeto de myClass:

myClass *classObj = new myClass();
classObj->data = new char[10];
classObj->var  = 99;

En mi proyecto C recibo classObjcomo un puntero vacío e intento convertirlo de la siguiente manera:

myStru *struObj = (myStru*)malloc(sizeof(struct myStru));
struObj = (myStru*) classObj;
printf(" struObj->var %d \n", struObj->var); // this print 99

Hago esto más tarde en mi proyecto C ++

   delete []classObj->data; // I know smart pointers can be used here but this is not my point in this question now
    delete  classObj;

¿Lo que estoy haciendo aquí es correcto? es decir, lanzando classObjde struObjesa manera?

El ejemplo completo se puede encontrar aquí (gracias @Borgleader) http://coliru.stacked-crooked.com/a/05543b944ee23f2f

EDITAR: Encontré una buena respuesta a mi pregunta en este artículo (consulte Acceso a clases de C ++ desde C): https://www.oracle.com/technical-resources/articles/it-infrastructure/mixing-c-and-cplusplus.html

Respuestas

3 BartekBanachewicz Nov 27 2020 at 13:22

No estoy 100% seguro, porque es C ++ y nunca podrás estarlo, pero creo que este es un comportamiento indefinido.

No puede acceder a los miembros de una estructura a través de un puntero a un miembro de otra estructura. Una excepción notable de esa regla implica acceder a la secuencia inicial común de dos estructuras que son miembros de una unión.

Esto podría funcionar si realmente heredara su clase de la estructura en su lugar.

Alternativamente, la otra excepción es que puede memcpyentre tales estructuras, AFAIR.

1 Persixty Nov 27 2020 at 17:08

Esta pregunta es sobre interoperabilidad y nunca obtendrá una respuesta definitiva porque se basa en aspectos definidos por la implementación del compilador de C y C ++. The structy the classson tipos compatibles con el diseño en términos de C ++. Está muy claro que declarar uno a classy uno a structno es un problema y porque ambos tienen el mismo acceso de miembro para todos sus miembros (aunque diferentes entre sí) son compatibles (al menos en C ++ 14 en adelante, creo) .

Lo mejor que ofrecerá el estándar es:

Nota: Las clases de diseño estándar son útiles para comunicarse con código escrito en otros lenguajes de programación. Su diseño se especifica en 12.2. - nota final

La intención es que tales clases (que son tanto de diseño estándar como compatibles con el diseño) sean interoperables. Si está utilizando el mismo compilador en dos modos, sería 'decepcionante' si esto no funcionara. Pero eso es lo mejor que obtendrá "decepcionante": consulte la documentación.

Me pregunto un poco sobre la gestión de recursos en la estrategia general. Ha declarado un destructor en C ++ classy está bien, virtual¡ no lo está !), Pero lo copia en un structen el lado C, si el código C tiene una función 'similar a un destructor' para destruir sus objetos que pueden causar problemas porque He clonado bit a bit el objeto C ++ (¡con suerte!).

Si C llamó free(s->data)a su copia de un objeto construido en C ++ que había usado new, está provocando un comportamiento indefinido. Ese podría ser el caso excepto que justifica el uso malloc()en el lado de C ++ por compatibilidad.

Entonces, probablemente esté bien, pero confía en las capacidades de interoperabilidad entre C y C ++ y los dos estándares lo llevan tan lejos como pueden, pero por definición está utilizando características definidas por la implementación.

Por esa nota, sabemos que el estándar está dispuesto a funcionar y probablemente lo hará. ¡Buena suerte!