lanzar objeto de clase a objeto de estructura C / C ++
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 classObj
como 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 classObj
de struObj
esa 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
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 memcpy
entre tales estructuras, AFAIR.
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 struct
y the class
son tipos compatibles con el diseño en términos de C ++. Está muy claro que declarar uno a class
y uno a struct
no 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 ++ class
y está bien, virtual
¡ no lo está !), Pero lo copia en un struct
en 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!