¿En qué escenarios es mejor usar un structvs a classen C ++?
¿En qué escenarios es mejor usar un structvs a classen C ++?
Respuestas:
Las diferencias entre a classy a structen C ++ son que las estructuras tienen publicmiembros y bases predeterminados y las clases tienen privatemiembros y bases predeterminados . Ambas clases y las estructuras pueden tener una mezcla de public, protectedyprivate los miembros, pueden utilizar la herencia y pueden tener funciones miembro.
Recomendaría usar estructuras como estructuras de datos antiguos sin ninguna clase de características, y usar clases como estructuras de datos agregados con privatedatos y funciones miembro.
Como todos los demás señalan, en realidad solo hay dos diferencias de idioma reales:
structvalores predeterminados de acceso público y classvalores predeterminados de acceso privado.structpredeterminado es publicherencia y el valor classpredeterminado es privateherencia. (Irónicamente, como con tantas cosas en C ++, el valor predeterminado es al revés: la publicherencia es, con mucho, la opción más común, pero la gente rara vez declara structs solo para ahorrar al escribir la publicpalabra clave " ".Pero la verdadera diferencia en la práctica es entre un class/ structque declara un constructor / destructor y uno que no. Hay ciertas garantías para un tipo de POD de "datos antiguos", que ya no se aplican una vez que se hace cargo de la construcción de la clase. Para mantener esta distinción clara, muchas personas deliberadamente solo usan structs para los tipos de POD y, si van a agregar algún método, usan classes. 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 "tipo POD": ¿Qué son los tipos POD en C ++? )
structo classno tiene relación con si su objeto es POD o si debe definir un constructor / destructor de copia. Las funciones de los miembros tampoco tienen relación con que algo sea POD. Cuando vuelvo a leer lo que escribiste, veo que no estás sugiriendo lo contrario, pero la redacción actual es confusa
Hay muchas ideas falsas en las respuestas existentes.
Ambos classy structdeclarar una clase.
Sí, es posible que deba reorganizar sus palabras clave de modificación de 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 seguir con la structpalabra clave para clases sin funciones de miembro, porque la definición resultante "parece" una estructura simple de C.
Del mismo modo, a algunas personas les gusta usar la classpalabra clave para las clases con funciones y privatedatos de miembros , porque dice "clase" y, por lo tanto, parece ejemplos de su libro favorito sobre programación orientada a objetos.
La realidad es que esto depende completamente de usted y su equipo, y literalmente no hará ninguna diferencia en su programa.
Las siguientes dos clases son absolutamente equivalentes en todos los sentidos, excepto su nombre:
struct Foo
{
int x;
};
class Bar
{
public:
int x;
};
Incluso puede cambiar las palabras clave al volver a declarar:
class Foo;
struct Bar;
(aunque esto rompe las compilaciones de Visual Studio debido a la no conformidad, por lo que el compilador emitirá una advertencia cuando haga esto).
y las siguientes expresiones se evalúan como verdaderas:
std::is_class<Foo>::value
std::is_class<Bar>::value
Sin embargo, tenga en cuenta que no puede cambiar las palabras clave al redefinir ; esto es solo porque (según la regla de una definición) las definiciones de clase duplicadas en las unidades de traducción deben "consistir en la misma secuencia de tokens" . Esto significa que incluso no pueden intercambiar const int member;con int const member;, y no tiene nada que ver con la semántica de classo struct.
class foo { public: ... };y otra pueda tener struct foo { ... };que ser cierta según la afirmación "absolutamente equivalente". Se trata de razonar que las declaraciones incompletas struct foo;y class foo;son intercambiables. Estos no especifican el cuerpo de la clase, por lo que no le dicen nada al diseño de acceso.
Fooy Barson todavía equivalente / tipos idénticos. Me aseguré de decir "al redeclar " y dar un ejemplo. Ahora que lo pienso, aclararé esto en la respuesta para asegurarme de que no estoy engañando a la gente a UB
La única vez que uso una estructura en lugar de una clase es cuando declaro un functor justo antes de usarlo en una llamada de 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 por defecto, mientras que en la clase, por defecto son privados. Nota: debe hacer que sus clases base sean explícitamente públicas, privadas o protegidas, en lugar de depender de los valores predeterminados.
struct y class son funcionalmente equivalentes.
OK, suficiente de esa charla techno chirriante y limpia. 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 poca encapsulación 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 tiene 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 me ha sido útil es cuando tengo un sistema que recibe mensajes de formato fijo (por ejemplo, un puerto serie) de otro sistema. Puede convertir la secuencia de bytes en una estructura que define 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, esto es lo mismo que haría en C, pero creo que la sobrecarga de tener que decodificar el mensaje en una clase generalmente no vale la pena.
operator >>en una clase en lugar de escribir la processMessagefunción, lo que haría que su C ++ se parezca más a C ++ y menos a C.
__packed__estructura y tener una implementación ifdef compatible con endian (debe cambiar el orden en una máquina donde la endianess es opuesta a la fuente de datos externa está proporcionando). No es bonito, pero solía empacar / desempaquetar registros para periféricos remotos en plataformas integradas de forma portátil.
chartipo, que está exento de alias. Sin embargo, todavía hay un problema, aunque diferente: enviar un char*a un tipo diferente, si realmente no había ningún objeto del último tipo ya inicializado en esa dirección, es UB ya que viola las reglas de por vida. Afaik, incluso si el tipo de destino es trivialmente construible, simplemente tener memoria asignada no es suficiente para que C ++ permita formalmente tratar esa memoria como ese tipo.
Puede usar "struct" en C ++ si está escribiendo una biblioteca cuyas partes internas son C ++ pero la API puede ser llamada por código C o C ++. Simplemente haga un encabezado único que contenga estructuras y funciones API globales que exponga a los códigos C y C ++ de la siguiente 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 función () en un archivo C ++ usando el código C ++ y hacer que se pueda llamar desde C y los dos mundos pueden compartir datos a través de la estructura declarada. Existen otras advertencias, por supuesto, 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 auxiliares. Por ejemplo, cuando necesito algo como esto:
struct myvec {
int x;
int y;
int z;
int length() {return x+y+z;}
};
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 solo para almacenamiento de datos. Le permitiré obtener algunas funciones auxiliares si facilita el trabajo con los datos. Sin embargo, tan pronto como los datos requieran control de flujo (es decir, captadores / establecedores que mantengan o protejan un estado interno) o comience a adquirir cualquier funcionalidad importante (básicamente más similar a un objeto), se 'actualizará' a una clase para comunicar mejor la intención.
Las estructuras ( POD , en general) son útiles cuando se proporciona una interfaz compatible con C con una implementación de C ++, ya que son portátiles a través de las fronteras del lenguaje y los formatos de enlace.
Si eso no le preocupa, entonces supongo que el uso de la "estructura" en lugar de la "clase" es un buen comunicador de intenciones (como dijo anteriormente @ZeroSignal). 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 diversas tareas de metaprogramación, como las plantillas de rasgos que solo exponen un montón de definiciones de tipos 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 estructuras y clases. La principal diferencia funcional es que los miembros de una estructura son públicos de forma predeterminada, mientras que son privados de forma predeterminada 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 ha dicho. 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 retenerlos.
Son más o menos lo mismo. Gracias a la magia de C ++, una estructura puede contener funciones, usar herencia, crearse usando "nuevo", etc., como una clase
La única diferencia funcional es que una clase comienza con derechos de acceso privado, mientras que una estructura comienza con público. Esta es la compatibilidad con versiones anteriores de C.
En la práctica, siempre he usado estructuras como titulares de datos y clases como objetos.
Como otros han señalado
Hay una recomendación clara sobre cuándo usar cuál de Stroustrup / Sutter:
Sin embargo, tenga en cuenta que no es aconsejable reenviar declaraciones. como una clase ( class X;) y definirlo como struct ( struct X { ... }). Puede funcionar en algunos enlazadores (por ejemplo, g ++) y puede fallar en otros (por ejemplo, MSVC), por lo que se encontrará en el infierno del desarrollador.
class Foo; struct Foo { void bar() {} }; int main() { Foo().bar(); }no solo compila y se ejecuta con MSVC 2017, incluso produce una advertencia clara que Foofue declarada como structpero definida como class. Pero también recuerdo claramente que le costó a nuestro equipo medio día encontrar ese estúpido error. No estoy seguro de qué versión de MSVC hemos usado en ese entonces.
classo structen una declaración de reenvío, y los dos son libremente intercambiables según el estándar (aunque se sabe que VS advierte; siempre supuse que era solo para evitar errores aparentes del programador). Algo no huele bien aquí. ¿Estás seguro de que no fue un error de violación de ODR?
structavance hacia classadelante, los problemas desaparecieron. A partir de hoy, también me parece extraño. Me alegraría si pudieras arrojar algo de luz sobre ello.
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();
Obtendremos un error: main_one is privateporque no es accesible. Podemos resolverlo inicializándolo especificando que es un público, es decir
class test_one {
public:
int main_one();
};
Una estructura es una clase donde los miembros son públicos de forma predeterminada.
struct test_one {
int main_one;
};
Medios main_onees privado es decir
class test_one {
public:
int main_one;
};
Utilizo estructuras para estructuras de datos donde los miembros pueden tomar cualquier valor, así es más fácil.
Una ventaja de structover classes que guarda una línea de código, si se adhiere a "primero miembros públicos, luego privados". En este sentido, encuentro la palabra claveclass inútil.
Aquí hay otra razón para usar solo structy nunca class. Algunas pautas de estilo de código para C ++ sugieren el uso de letras minúsculas para las macros de funciones, la razón es que cuando la macro se convierte en una función en línea, no es necesario cambiar el nombre. Igual que aquí. Tiene su estructura de estilo C agradable y un día, descubre que necesita agregar un constructor, o algún método conveniente. ¿Lo cambias a a class? ¿En todas partes?
Distinguir entre structsy classes es demasiado complicado, interponerse en la forma de hacer lo que deberíamos estar haciendo: programar. Como muchos de los problemas de C ++, surge del fuerte deseo de compatibilidad hacia atrás.
class? ¿Pensó que una clase definida con la structpalabra clave no puede tener funciones miembro o un constructor?
joe()debe definirse con una classpalabra clave? ¿Cada clase con al menos 4 intmiembros debe definirse con una structpalabra clave?
struct, los agregados con métodos se definen con class". Demasiada molestia.
son lo mismo con diferentes valores predeterminados (privado por defecto para classy público por defecto para struct), por lo que en teoría son totalmente intercambiables.
entonces, si solo quiero empaquetar información para moverme, uso una estructura, incluso si pongo algunos métodos allí (pero no muchos). Si es algo opaco en su mayoría, donde el uso principal sería a través de métodos, y no directamente a los miembros de datos, utilizo una clase completa.
Las estructuras por defecto tienen acceso público y las clases por defecto tienen acceso privado.
Personalmente, uso estructuras para objetos de transferencia de datos o como objetos de valor. Cuando se usa como tal, declaro que todos los miembros son constantes para evitar modificaciones por otro código.
Tanto structy classson los mismos bajo el capó, aunque con diferentes valores por defecto en cuanto a visibilidad, structpor defecto es público y classpor defecto es privado. Puede cambiar uno para que sea el otro con el uso apropiado de privateypublic . Ambos permiten la herencia, los métodos, los constructores, los destructores y todo lo demás de un lenguaje orientado a objetos.
Sin embargo, una gran diferencia entre los dos es que structuna palabra clave se admite en C, mientras classque no. Esto significa que uno puede usar un structarchivo de inclusión que puede estar #includeen C ++ o C siempre que structsea un estilo C simple structy todo lo demás en el archivo de inclusión sea compatible con C, es decir, sin palabras clave específicas de C ++ como private, por ejemplo ,public , sin métodos, sin herencia, etc. etc. etc.
El estilo AC structse puede usar con otras interfaces que admiten el uso del estilo C structpara transportar datos de un lado a otro a través de la interfaz.
El estilo de CA structes un tipo de plantilla (no una plantilla de C ++ sino un patrón o plantilla) que describe el diseño de un área de memoria. Con los años las interfaces utilizable a partir de C y C con los plug-ins (aquí le está mirando Java y Python y Visual Basic) se han creado algunas de las cuales trabaja con el estilo C struct.
Técnicamente, ambos son iguales en C ++; por ejemplo, es posible que una estructura tenga operadores sobrecargados, etc.
Sin embargo :
Utilizo estructuras cuando deseo pasar información de múltiples tipos simultáneamente. Uso clases cuando estoy tratando 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 estudiante de estructura en los métodos get ... () por aquí, disfruta.
¿Cuándo elegirías usar struct y cuándo usar class en C ++?
Yo uso structcuando defino functorsy POD. De lo contrario lo 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; }
};
std::binary_function<>no solo está en desuso, incluso c ++ 17 la elimina.
Todos los miembros de la clase son privados de forma predeterminada y todos los miembros de la estructura son públicos de forma predeterminada. La clase tiene bases privadas predeterminadas y Struct tiene bases públicas predeterminadas. Struct en el caso de C no puede tener funciones miembro donde, como en el caso de C ++, podemos agregar funciones miembro a la estructura. Aparte de estas diferencias, no encuentro nada sorprendente sobre ellas.
Utilizo struct solo cuando necesito mantener algunos datos sin ninguna función miembro asociada (para operar con los datos miembros) y acceder a las variables de datos directamente.
Por ejemplo: lectura / escritura de datos de archivos y secuencias de socket, etc. Pasar argumentos de función en una estructura donde los argumentos de función son demasiados y la sintaxis de función parece demasiado larga.
Técnicamente no hay una gran diferencia entre clase y estructura, excepto la accesibilidad predeterminada. Más sobre eso depende del estilo de programación como lo use.
Pensé que Structs tenía la intención de ser una Estructura de datos (como una matriz de información de tipos de datos múltiples) y que las clases estaban destinadas al Empaquetado de código (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 intencionalmente intentes ser confuso.
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 e intentar hacerlo explícito en el nombre de la clase, o mediante comentarios.
P.ej
class PublicInputData {
//data members
};
structsería ya bastante explícito que los miembros de la clase serán, por defecto, públicos?