Pregunta

Si tengo una clase de la siguiente manera

   class Example_Class 
   {
       private:
         int x; 
         int y; 
       public: 
         Example_Class() 
         { 
             x = 8;
             y = 9;
         }
       ~Example_Class() 
       { } 
   };

Y una estructura como sigue

struct
{
   int x;
   int y;
} example_struct;

Es la estructura en la memoria de example_struct similar a la de Example_Class

por ejemplo, si hago lo siguiente

struct example_struct foo_struct;
Example_Class foo_class = Example_Class();

memcpy(&foo_struct, &foo_class, sizeof(foo_struct));

¿ foo_struct.x = 8 y foo_struct.y = 9 (es decir, los mismos valores que los valores x, y en foo_class)?

La razón por la que pregunto es que tengo una biblioteca C ++ (no quiero cambiarla) que comparte un objeto con código C y quiero usar una estructura para representar el objeto que proviene de la biblioteca C ++. Solo me interesan los atributos del objeto.

Sé que la situación ideal sería tener a Example_class alrededor de una estructura común entre los códigos C y C ++, pero no será fácil cambiar la biblioteca de C ++ en uso.

¿Fue útil?

Solución

El estándar de C ++ garantiza que los diseños de memoria de C struct y C ++ class (o struct - - lo mismo) será idéntico, siempre que el class / struct de C ++ se ajuste al criterio de ser POD (" Plain Old Data ") . Entonces, ¿qué significa POD?

Una clase o estructura es POD si:

  • Todos los miembros de datos son públicos y ellos mismos POD o tipos fundamentales (pero no tipos de referencia o de puntero a miembro), o matrices de tales
  • No tiene constructores, operadores de asignación ni destructores definidos por el usuario
  • No tiene funciones virtuales
  • No tiene clases base

Acerca del único " C ++ - isms " se permiten funciones miembro no virtuales, miembros estáticos y funciones miembro.

Dado que su clase tiene un constructor y un destructor, formalmente no es del tipo POD, por lo que la garantía no se cumple. (Aunque, como han mencionado otros, en la práctica es probable que los dos diseños sean idénticos en cualquier compilador que intente, siempre que no haya funciones virtuales).

Consulte la sección [26.7] de C ++ FAQ Lite para más detalles.

Otros consejos

  

Es la estructura en memoria de example_struct similar a la de Example_Class

El comportamiento no está garantizado y depende del compilador.

Habiendo dicho eso, la respuesta es " sí, en mi máquina " ;, siempre que la Clase de Ejemplo no contenga ningún método virtual (y no herede de una clase base).

En el caso que describe, la respuesta es " probablemente sí " ;. Sin embargo, si la clase tiene alguna función virtual (incluido el destructor virtual, que podría heredarse de una clase base), o utiliza una herencia múltiple, el diseño de la clase puede ser diferente.

Para agregar a lo que otras personas han dicho (p. ej., específico del compilador, es probable que funcione siempre y cuando no tenga funciones virtuales):

Recomendaría encarecidamente una aserción estática (verificación en tiempo de compilación) de que sizeof (Example_class) == sizeof (example_struct) si está haciendo esto. Consulte BOOST_STATIC_ASSERT, o la construcción específica o específica del compilador equivalente. Esta es una buena primera línea de defensa si alguien (o algo, como un cambio de compilador) modifica la clase para invalidar la coincidencia. Si desea una verificación adicional, también puede verificar en tiempo de ejecución que las compensaciones de los miembros son las mismas, lo que (junto con la afirmación de tamaño estático) garantizará la corrección.

En los primeros días de los compiladores de C ++, había ejemplos cuando el compilador primero cambia las palabras clave de estructura con la clase y luego las compila. Mucho sobre las similitudes.

Las diferencias provienen de la herencia de clases y, especialmente, de las funciones virtuales. Si la clase contiene funciones virtuales, debe tener un puntero para escribir el descriptor al principio de su diseño. Además, si la clase B se hereda de la clase A, el diseño de la clase A es lo primero, seguido del propio diseño de la clase B.

Por lo tanto, la respuesta precisa a su pregunta acerca de simplemente enviar una instancia de clase a una instancia de estructura es: depende del contenido de la clase. Para la clase particular que tiene métodos (constructor y destructor no virtual), el diseño probablemente será el mismo. Si el destructor fuera declarado virtual, el diseño definitivamente sería diferente entre la estructura y la clase.

Aquí hay un artículo que muestra que no hay mucho que hacer para pasar de las estructuras C a las clases de C ++: Lección 1 - De la estructura a la clase

Y aquí está el artículo que explica cómo la tabla de funciones virtuales se introduce en las clases que tienen funciones virtuales: Lección 4 - Polimorfismo

Clases & amp; las estructuras en C ++ son equivalentes, excepto que todos los miembros de una estructura son públicos por defecto (los miembros de la clase son privados por defecto). Esto garantiza que la compilación del código C heredado en un compilador de C ++ funcionará como se esperaba.

No hay nada que le impida utilizar todas las funciones de C ++ en una estructura:

struct ReallyAClass
{
    ReallyAClass();
    virtual !ReallAClass();

    /// etc etc etc
};

¿Por qué no asignar explícitamente los miembros de la clase a la estructura cuando desea pasar los datos a C? De esa forma, sabrás que tu código funcionará en cualquier lugar.

Probablemente solo derivas la clase de la estructura, ya sea pública o en privado. Luego, convertirlo se resolvería correctamente en el código C ++.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top