c++ - ¿Cuándo debería usar una clase frente a una estructura en C ++?


¿En qué escenarios es mejor usar una struct frente a una class en C ++?



Answers


Las diferencias entre una class y una struct en C ++ son que las estructuras tienen miembros public predeterminados y las bases y las clases tienen bases y miembros private predeterminados. Tanto las clases como las estructuras pueden tener una combinación de miembros public y private , pueden usar herencia y pueden tener funciones de miembro.

Recomendaría el uso de estructuras como estructuras simples de datos antiguos sin características de clase, y el uso de clases como estructuras de datos agregados con datos private y funciones de miembros.




Como todos los demás observan, en realidad solo hay dos diferencias de lenguaje reales:

  • struct predeterminada en el acceso público y class valores predeterminados de class en acceso privado.
  • Al heredar, struct predeterminada en herencia public y class valores predeterminados de class en herencia private . (Irónicamente, como ocurre con tantas cosas en C ++, el valor predeterminado es al revés: public herencia public es, con mucho, la opción más común, pero las personas rara vez declaran struct s solo para ahorrar al escribir la palabra clave " public ".

Pero la diferencia real en la práctica es entre una class / struct que declara un constructor / destructor y otra que no. Existen ciertas garantías para un tipo de POD "de datos antiguos", que ya no se aplica una vez que se hace cargo de la construcción de la clase. Para mantener esta distinción clara, muchas personas deliberadamente solo usan struct s para los tipos de POD y, si van a agregar algún método, usan class es. La diferencia entre los dos fragmentos a continuación no tiene sentido:

class X
{
  public:

  // ...
};

struct X
{
  // ...
};

(Por cierto, aquí hay un hilo con algunas buenas explicaciones sobre lo que realmente significa el "tipo de POD": ¿Qué son los tipos de POD en C ++? )




Hay muchas ideas erróneas en las respuestas existentes.

Tanto la class como la struct declaran una clase.

Sí, es posible que deba reorganizar las palabras clave que modifican el acceso dentro de la definición de clase, según la palabra clave que utilizó para declarar la clase.

Pero, más allá de la sintaxis, la única razón para elegir una sobre la otra es la convención / estilo / preferencia.

A algunas personas les gusta quedarse con la palabra clave struct para las clases sin funciones miembro, porque la definición resultante "parece" una estructura simple de C.

Del mismo modo, a algunas personas les gusta utilizar la palabra clave class para las clases con funciones de miembros y datos private , porque dice "clase" y por lo tanto se ve como ejemplos de su libro favorito sobre programación orientada a objetos.

La realidad es que esto depende completamente de usted y de su equipo, y literalmente no tendrá ninguna importancia para su programa.

Las siguientes dos clases son absolutamente equivalentes en todos los sentidos excepto en su nombre:

struct Foo
{
   int x;
};

class Bar
{
public:
   int x;
};

Incluso puede cambiar las palabras clave al redeclar:

class Foo;
struct Bar;

(aunque algunos compiladores emitirán una advertencia cuando hagas esto, en el supuesto de que probablemente no tenías la intención de hacer algo tan confuso y que, por lo tanto, deberías pedirte que verifiques tu código).

y las siguientes expresiones se evalúan como verdaderas:

std::is_class<Foo>::value
std::is_class<Bar>::value



La única vez que uso una estructura en lugar de una clase es cuando declaro un funtor justo antes de usarlo en una llamada a función y quiero minimizar la sintaxis en aras de la claridad. p.ej:

struct Compare { bool operator() { ... } };
std::sort(collection.begin(), collection.end(), Compare()); 



Desde C ++ FAQ Lite :

Los miembros y las clases base de una estructura son públicos de forma predeterminada, mientras que en clase, tienen el valor predeterminado en privado. Nota: debe hacer que sus clases base sean explícitamente públicas, privadas o protegidas, en lugar de confiar en los valores predeterminados.

struct y clase son funcionalmente equivalentes.

OK, suficiente de esa charla techno limpia y chillona. Emocionalmente, la mayoría de los desarrolladores hacen una fuerte distinción entre una clase y una estructura. Una estructura simplemente se siente como una pila abierta de bits con muy poco encapsulamiento o funcionalidad. Una clase se siente como un miembro vivo y responsable de la sociedad con servicios inteligentes, una fuerte barrera de encapsulación y una interfaz bien definida. Dado que esa es la connotación que la mayoría de la gente ya tiene, probablemente debería usar la palabra clave struct si tiene una clase que tiene muy pocos métodos y datos públicos (¡tales cosas existen en sistemas bien diseñados!), Pero de lo contrario probablemente debería usar la clase palabra clave.




Un lugar donde una estructura ha sido útil para mí es cuando tengo un sistema que está recibiendo mensajes de formato fijo (por ejemplo, un puerto serie) de otro sistema. Puede convertir la secuencia de bytes en una estructura que defina sus campos y luego acceder fácilmente a los campos.

typedef struct
{
    int messageId;
    int messageCounter;
    int messageData;
} tMessageType;

void processMessage(unsigned char *rawMessage)
{
    tMessageType *messageFields = (tMessageType *)rawMessage;
    printf("MessageId is %d\n", messageFields->messageId);
}

Obviamente, esta es la misma cosa que harías en C, pero creo que la sobrecarga de tener que decodificar el mensaje en una clase generalmente no vale la pena.




Puede usar "struct" en C ++ si está escribiendo una biblioteca cuyas partes internas son C ++, pero la API puede llamarse mediante el código C o C ++. Simplemente crea un único encabezado que contiene estructuras y funciones API globales que expone a los códigos C y C ++ de esta manera:

// C access Header to a C++ library
#ifdef __cpp
extern "C" {
#endif

// Put your C struct's here
struct foo
{
    ...
};
// NOTE: the typedef is used because C does not automatically generate
// a typedef with the same name as a struct like C++.
typedef struct foo foo;

// Put your C API functions here
void bar(foo *fun);

#ifdef __cpp
}
#endif

Luego puede escribir una barra de funciones () en un archivo C ++ utilizando código C ++ y hacer que se pueda llamar desde C y los dos mundos pueden compartir datos a través de las estructuras declaradas. Por supuesto, hay otras advertencias cuando se mezclan C y C ++, pero este es un ejemplo simplificado.




Como todos dicen, la única diferencia real es el acceso predeterminado. Pero particularmente uso struct cuando no quiero ningún tipo de encapsulación con una clase de datos simple, incluso si implemento algunos métodos de ayuda. Por ejemplo, cuando necesito algo como esto:

struct myvec {
    int x;
    int y;
    int z;

    int length() {return x+y+z;}
};



Las estructuras ( POD , en general) son prácticas cuando se proporciona una interfaz compatible con C con una implementación de C ++, ya que son portátiles a través de los bordes del idioma y los formatos de enlazador.

Si eso no te concierne, entonces supongo que el uso de la "estructura" en lugar de "clase" es un buen comunicador de intención (como dijo @ZeroSignal arriba). Las estructuras también tienen una semántica de copia más predecible, por lo que son útiles para los datos que tiene la intención de escribir en medios externos o enviar a través del cable.

Las estructuras también son útiles para varias tareas de metaprogramación, como plantillas de rasgos que solo exponen un montón de typedefs dependientes:

template <typename T> struct type_traits {
  typedef T type;
  typedef T::iterator_type iterator_type;
  ...
};

... Pero eso es solo aprovechar el nivel de protección predeterminado de struct que es público ...




Para C ++, realmente no hay mucha diferencia entre las estructuras y las clases. La principal diferencia funcional es que los miembros de una estructura son públicos por defecto, mientras que son privados por defecto en las clases. De lo contrario, en lo que respecta al idioma, son equivalentes.

Dicho esto, tiendo a usar estructuras en C ++ como lo hago en C #, similar a lo que Brian dijo. Las estructuras son contenedores de datos simples, mientras que las clases se usan para objetos que necesitan actuar sobre los datos además de simplemente aferrarse a ellos.




Para responder a mi propia pregunta (descaradamente), como ya se mencionó, los privilegios de acceso son la única diferencia entre ellos en C ++.

Tiendo a usar una estructura para el almacenamiento de datos solamente. Permitiré que obtenga algunas funciones de ayuda si facilita el trabajo con los datos. Sin embargo, tan pronto como los datos requieran control de flujo (es decir, getters / setters que mantienen o protegen un estado interno) o comiencen a adquirir cualquier funcionalidad principal (básicamente más similar a un objeto), se "actualizará" a una clase para comunicar mejor el intento.




Son más o menos lo mismo. Gracias a la magia de C ++, una estructura puede contener funciones, usar herencia, crearse con "nuevo" y así sucesivamente, al igual que una clase

La única diferencia funcional es que una clase comienza con derechos de acceso privados, mientras que una estructura comienza con pública. Esta es la compatibilidad retroactiva con C.

En la práctica, siempre he usado estructuras como titulares de datos y clases como objetos.




son lo mismo con diferentes valores predeterminados (privado por defecto para la class , y público por defecto para struct ), por lo que en teoría son totalmente intercambiables.

entonces, si solo quiero empaquetar algo de información para moverme, uso una estructura, incluso si pongo algunos métodos allí (pero no muchos). Si es una cosa principalmente opaca, donde el uso principal sería a través de métodos, y no directamente a los miembros de los datos, uso una clase completa.




Las estructuras de forma predeterminada tienen acceso público y las clases de forma predeterminada tienen acceso privado.

Personalmente utilizo estructuras para objetos de transferencia de datos o como objetos de valor. Cuando se usa como tal, declaro que todos los miembros son const para evitar modificaciones por otro código.




¿Cuándo elegirías usar struct y cuándo usar la clase en C ++?

Uso struct cuando defino functors y POD . De lo contrario, uso class .

// '()' is public by default!
struct mycompare : public std::binary_function<int, int, bool>
{
    bool operator()(int first, int second)
    { return first < second; }
};

class mycompare : public std::binary_function<int, int, bool>
{
public:
    bool operator()(int first, int second)
    { return first < second; }
};



Clase.

Los miembros de la clase son privados por defecto.

class test_one {
    int main_one();
};

Es equivalente a

class test_one {
  private:
    int main_one();
};

Entonces, si lo intentas

int two = one.main_one();

main_one is private un error: main_one is private porque no es accesible. Podemos resolverlo inicializándolo especificando que es un público

class test_one {
  public:
    int main_one();
};

Struct.

Una estructura es una clase donde los miembros son públicos por defecto.

struct test_one {
    int main_one;
};

Significa main_one es privado ie

class test_one {
  public:
    int main_one;
};

Utilizo estructuras para estructuras de datos donde los miembros pueden tomar cualquier valor, es más fácil de esa manera.




Utilizo struct solo cuando necesito contener algunos datos sin ninguna función miembro asociada (para operar en los datos del miembro) y para acceder directamente a las variables de datos.

Ejemplo: leer / escribir datos de archivos y secuencias de socket, etc. Pasar argumentos de función en una estructura donde los argumentos de la función son demasiados y la sintaxis de la función parece demasiado larga.

Técnicamente, no hay una gran diferencia entre clase y estructura, excepto la accesibilidad predeterminada. Más sobre esto depende del estilo de programación como lo usas.




Técnicamente, ambos son iguales en C ++, por ejemplo, es posible que una estructura tenga operadores sobrecargados, etc.

Sin embargo :

Uso estructuras cuando deseo pasar información de varios tipos simultáneamente. Utilizo clases cuando trato con un objeto "funcional".

Espero eso ayude.

#include <string>
#include <map>
using namespace std;

struct student
{
    int age;
    string name;
    map<string, int> grades
};

class ClassRoom
{
    typedef map<string, student> student_map;
  public :
    student getStudentByName(string name) const 
    { student_map::const_iterator m_it = students.find(name); return m_it->second; }
  private :
    student_map students;
};

Por ejemplo, estoy devolviendo un alumno struct en los métodos get ... () aquí - enjoy.




Uso structs cuando necesito crear POD tipo o functor.




Una ventaja de struct over class es que guarda una línea de código, si se adhiere a "primeros miembros públicos, luego privados". En este sentido, creo que la class palabra clave es inútil.




Pensé que Structs tenía la intención de ser una estructura de datos (como una matriz de información de tipo de datos múltiples) y las clases se destinaron para Code Packaging (como colecciones de subrutinas y funciones).

:(




Nunca uso "struct" en C ++.

No puedo imaginar un escenario en el que usarías una estructura cuando quieres miembros privados, a menos que intentes confundir intencionalmente.

Parece que el uso de estructuras es más una indicación sintáctica de cómo se usarán los datos, pero prefiero simplemente hacer una clase y tratar de hacerlo explícito en el nombre de la clase, o mediante comentarios.

P.ej

class PublicInputData {
    //data members
 };



Las funciones de acceso no son la única diferencia entre estructuras y clases. Una estructura es mejor para los tipos POD (Plain Old Data), ya que es más fácil de administrar para el compilador y el programador. Para principiantes que no usan programación orientada a objetos, usar una estructura está bien.