Estructura C / C ++ frente a clase

108

Después de terminar mi clase de C ++, me pareció que las estructuras / clases son prácticamente idénticas, excepto con algunas diferencias menores.

Nunca antes había programado en C; pero sé que tiene estructuras. En C, ¿es posible heredar otras estructuras y establecer un modificador de público / privado?

Si puede hacer esto en C normal, ¿por qué en el mundo necesitamos C ++? ¿Qué hace que las clases sean diferentes de una estructura?


fuente

Respuestas:

146

En C ++ , las estructuras y las clases son prácticamente iguales; la única diferencia es que cuando los modificadores de acceso (para variables miembro, métodos y clases base) en las clases son privados, los modificadores de acceso en estructuras son públicos.

Sin embargo, en C , una estructura es solo una colección agregada de datos (públicos) y no tiene otras características de clase: sin métodos, sin constructor, sin clases base, etc. Aunque C ++ heredó la palabra clave, extendió la semántica. (Sin embargo, esta es la razón por la que las cosas están predeterminadas en público en las estructuras: una estructura escrita como una estructura C se comporta como una).

Si bien es posible falsificar algunas OOP en C, por ejemplo, definir funciones que toman un puntero a una estructura como primer parámetro, u ocasionalmente coaccionar estructuras con los mismos primeros campos para que sean "sub / superclases", siempre es una especie de atornillado, y no es realmente parte del lenguaje.

Antal Spector-Zabusky
fuente
Desde OOP, los posibles chicos de .Net lo han definido de esta manera ✓ CONSIDERE definir una estructura en lugar de una clase si las instancias del tipo son pequeñas y comúnmente de corta duración o están comúnmente incrustadas en otros objetos. X EVITE definir una estructura a menos que el tipo tenga todas las características siguientes: 1. Representa lógicamente un valor único, similar a los tipos primitivos (int, double, etc.). 2. Tiene un tamaño de instancia inferior a 16 bytes. 3. Es inmutable.
Abhijeet
5
@Abhijeet Esa es la distinción entre estructuras y clases en C #, pero eso es simplemente irrelevante para C ++, y más aún para C. En C #, las clases y estructuras son en realidad diferentes; no es así en C ++, y C solo tiene estructuras sin OO.
Antal Spector-Zabusky
¿No sería mejor haber mantenido la misma semántica C en la estructura C ++? y cuando se requiera usar una "estructura en una forma de C ++", simplemente use una clase Nunca he tenido el beneficio de tener una estructura "aumentada" en C ++ en comparación con C. Me gusta seguir usando la estructura como se diseñó en C; de lo contrario, uso una clase, con alguna excepción permitida.
Raffaello
15

Aparte de las diferencias en el acceso predeterminado (público / privado), no hay diferencia.

Sin embargo, algunas tiendas que codifican en C y C ++ usarán "class / struct" para indicar qué se puede usar en C y C ++ (struct) y cuáles son solo C ++ (class). En otras palabras, en este estilo todas las estructuras deben funcionar con C y C ++. Esta es la razón por la que había una diferencia en primer lugar hace mucho tiempo, cuando C ++ todavía se conocía como "C con clases".

Tenga en cuenta que las uniones de C funcionan con C ++, pero no al revés. Por ejemplo

union WorksWithCppOnly{
    WorksWithCppOnly():a(0){}
    friend class FloatAccessor;
    int a;
private:
    float b;
};

Y de la misma manera

typedef union friend{
    int a;
    float b;
} class;

solo funciona en C

Lance Diduck
fuente
9
Usar palabras clave cpp en su código c y luego afirmar que no es compatible con cpp es bastante estúpido
Dani
7

Voy a agregar a las respuestas existentes porque el C ++ moderno ahora es una cosa y se han creado Pautas básicas oficiales para ayudar con preguntas como estas.

Aquí hay una sección relevante de las pautas:

C.2: Use class si la clase tiene una invariante; use struct si los miembros de datos pueden variar de forma independiente

Un invariante es una condición lógica para los miembros de un objeto que un constructor debe establecer para que asuman las funciones miembro públicas. Después de que se establece el invariante (normalmente por un constructor), se puede llamar a cada función miembro para el objeto. Un invariante puede expresarse de manera informal (por ejemplo, en un comentario) o más formalmente usando Expects.

Si todos los miembros de datos pueden variar independientemente unos de otros, no es posible una invariante.

Si una clase tiene datos privados, un usuario no puede inicializar completamente un objeto sin el uso de un constructor. Por lo tanto, el definidor de clase proporcionará un constructor y debe especificar su significado. Esto significa efectivamente que el definidor necesita definir un invariante.

Aplicación

Busque estructuras con todos los datos privados y clases con miembros públicos.

Los ejemplos de código dados:

struct Pair {  // the members can vary independently
    string name;
    int volume;
};

// but

class Date {
public:
    // validate that {yy, mm, dd} is a valid date and initialize
    Date(int yy, Month mm, char dd);
    // ...
private:
    int y;
    Month m;
    char d;    // day
};

ClassFuncionan bien para miembros que, por ejemplo, se derivan entre sí o están interrelacionados. También pueden ayudar con la comprobación de la cordura al crear una instancia. StructLos s funcionan bien para tener "bolsas de datos", donde en realidad no ocurre nada especial, pero los miembros lógicamente tienen sentido estar agrupados.

A partir de esto, tiene sentido que classexistan s para admitir la encapsulación y otros conceptos de codificación relacionados, para los que structsimplemente no son muy útiles.

Dave
fuente
Otra consideración es la portabilidad. structs son los más portátiles. Pueden ser utilizados por C o C ++ o de ida y vuelta. También se pueden descomprimir en Python usando el structmódulo, por ejemplo. Si sus prioriza los proyectos que sean compatibles con otros idiomas, interfaces o sistemas, prefieren structmás class. Para asuntos estrictamente internos del programa, prefiera class.
Dave
6

No es posible definir funciones miembro o derivar estructuras entre sí en C.

Además, C ++ no es solo C + "derivar estructuras". Las plantillas, las referencias, los espacios de nombres definidos por el usuario y la sobrecarga de operadores no existen en C.

Johannes Schaub - litb
fuente
Sé que las plantillas, etc.no existen en C, pero no conocía las powerestructuras en C. ¿Entonces C ++ solo usa estructuras para ser compatibles con C?
4
¿Solo por compatibilidad con versiones anteriores? Desde un punto de vista práctico, probablemente hay algo en eso, pero la distinción puede ser una señal de intención: cuando uso un, structme refiero a un tipo de cosa POD en gran medida pasiva.
dmckee --- ex-moderador gatito
@dmckee: Por lo que vale, la mayoría de los functores STL (es decir std::less) se definen como estructuras, no como clases.
Billy ONeal
1
C ++ no es totalmente compatible con C. Se podría decir que la palabra clave struct es un alojamiento para los desarrolladores de C. Me gusta la palabra clave struct para las clases que simplemente contienen datos de forma ordenada pero que no proporcionan (mucha) lógica por sí mismos.
ypnos
@ypnos: Vea mi último comentario. La única diferencia entre los dos es que los miembros de uno son públicos predeterminados y los otros son privados predeterminados.
Billy ONeal
3

Una diferencia más en C ++, cuando hereda una clase de la estructura sin ningún especificador de acceso, se convierte en herencia pública, mientras que en el caso de la clase es herencia privada.

Mars Rover
fuente
1

C ++ utiliza estructuras principalmente para 1) compatibilidad con versiones anteriores de C y 2) tipos de POD. Las estructuras C no tienen métodos, herencia o visibilidad.

Chris Hafey
fuente
2
Por lo que vale, la mayoría de los functores STL (es decir std::less) se definen como estructuras, no como clases.
Billy ONeal
3
Tenga en cuenta que las estructuras de C ++ tienen métodos, herencia y visibilidad.
robertwb
c struct puede incluir un puntero de función como type (* addr) (params);
Error