sindicatos sindical principales oit mexico los libertad frente estado ejemplos convenio clasificacion clases c++ inheritance unions language-lawyer

c++ - sindical - Sindicatos como clase base



principales sindicatos en mexico 2017 (7)

El estándar define que las Uniones no se pueden usar como clase Base, pero ¿hay algún razonamiento específico para esto? Por lo que yo sé, las Uniones pueden tener constructores, destructores, también variables de miembros y métodos para operar en esos varibales. En resumen, una Unión puede encapsular un tipo de datos y un estado al que se puede acceder a través de funciones de miembros. Por lo tanto, en la mayoría de los términos comunes califica para ser una clase y si puede actuar como una clase, ¿por qué está restringido de actuar como una clase base?

Editar: Aunque las respuestas intentan explicar el razonamiento, todavía no entiendo cómo la Unión como una clase Derivada es peor que cuando la Unión es solo una clase. Entonces, con la esperanza de obtener una respuesta y un razonamiento más concretos, impulsaré este para obtener una recompensa. Sin ofender a las respuestas ya publicadas, ¡gracias por eso!


Aquí está mi conjetura para C ++ 03.

Según $ 9.5 / 1, en C ++ 03, las Uniones no pueden tener funciones virtuales. El objetivo de una derivación significativa es poder anular comportamientos en la clase derivada. Si una unión no puede tener funciones virtuales, eso significa que no tiene sentido derivar de una unión.

De ahí la regla.


Bjarne Stroustrup dijo "parece haber pocas razones para ello" en el Manual de referencia anotado de C ++.


Creo que usted obtuvo la respuesta usted mismo en sus comentarios sobre la respuesta de EJP.

Creo que los sindicatos solo están incluidos en C ++ para ser compatibles con C. Creo que los sindicatos parecían una buena idea en 1970, en sistemas con espacios de memoria pequeños. Para cuando apareció C ++, imagino que los sindicatos ya parecían menos útiles.

Teniendo en cuenta que los sindicatos son bastante peligrosos de todos modos, y no terriblemente útiles, las grandes nuevas oportunidades para crear errores que heredan de los sindicatos crearían probablemente no parecían una buena idea :-)


El título pregunta por qué los sindicatos no pueden ser una clase base, pero la pregunta parece ser sobre los sindicatos como una clase derivada. Entonces, ¿cuál es?

No hay una razón técnica por la cual los sindicatos no puedan ser una clase base; simplemente no está permitido. Una interpretación razonable sería pensar en la unión como una estructura cuyos miembros coinciden potencialmente en la memoria, y considerar la clase derivada como una clase que hereda de esta estructura (bastante extraña). Si necesita esa funcionalidad, generalmente puede persuadir a la mayoría de los compiladores para que acepten una unión anónima como miembros de una estructura. Aquí hay un ejemplo, que es adecuado para usar como una clase base. (Y hay una estructura anónima en la unión por si acaso).

struct V3 { union { struct { float x,y,z; }; float f[3]; }; };

La razón de ser de los sindicatos como una clase derivada es probablemente más simple: el resultado no sería una unión. Los sindicatos deberían ser la unión de todos sus miembros y todas sus bases. Eso es justo, y podría abrir algunas posibilidades de plantillas interesantes, pero tendría una serie de limitaciones (todas las bases y miembros tendrían que ser POD, y podría heredar dos veces, porque un tipo derivado es intrínsecamente no -POD?), Este tipo de herencia sería diferente del otro tipo, el lenguaje deportivo (OK, no es que esto haya detenido a C ++ anteriormente) y, de todos modos, es algo redundante: la funcionalidad de unión existente funcionaría igual de bien.

Stroustrup dice esto en el libro de D & E:

Al igual que con el void * , los programadores deben saber que los sindicatos ... son intrínsecamente peligrosos, deben evitarse siempre que sea posible y deben manejarse con especial cuidado cuando realmente se necesiten.

(La elisión no cambia el significado).

Así que me imagino que la decisión es arbitraria, y él simplemente no vio ninguna razón para cambiar la funcionalidad de la unión (funciona bien tal como está con el subconjunto C de C ++), y por eso no diseñó ninguna integración con las nuevas características de C ++. Y cuando cambió el viento, se atascó de esa manera.


Puede heredar el diseño de datos de una unión utilizando la función de unión anónima de C ++ 11.

#include <cstddef> template <size_t N,typename T> struct VecData { union { struct { float x; float y; float z; }; float a[N]; }; }; template <size_t N, typename T> class Vec : public VecData<N,T> { //methods.. };

En general, casi siempre es mejor no trabajar con los sindicatos directamente, sino incluirlos dentro de una estructura o clase. Luego puede basar su herencia en la capa exterior de la estructura y usar uniones dentro si lo necesita.


Tony Park dio una respuesta que es bastante cercana a la verdad. El comité de C ++ básicamente no pensó que valiera la pena esforzarse para hacer que los sindicatos fueran una parte importante de C ++, de manera similar al tratamiento de arreglos como material heredado que tuvimos que heredar de C pero que realmente no queríamos.

Los sindicatos tienen problemas: si permitimos que los tipos distintos de POD entren en uniones, ¿cómo se construyen? Ciertamente se puede hacer, pero no necesariamente de forma segura, y cualquier consideración requeriría recursos del comité. Y el resultado final sería menos que satisfactorio, porque lo que realmente se requiere en un lenguaje sensato son los sindicatos discriminados, y los sindicatos desnudos nunca podrían ser elevados a sindicatos discriminados de manera compatible con C (que de todos modos puedo imaginar).

Para profundizar en los problemas técnicos: ya que puede envolver una unión de solo POD-component en una estructura sin perder nada, no hay ninguna ventaja que permita a los sindicatos como bases. Con los componentes de unión POD-only, no hay problema con los constructores explícitos que simplemente asignan uno de los componentes, ni con el uso de un bitblit (memcpy) para el constructor (o asignación) de copia generado por el compilador.

Tales uniones, sin embargo, no son lo suficientemente útiles para preocuparse excepto para retenerlos, por lo que el código C existente puede considerarse válido C ++. Estas uniones POD-only se rompen en C ++ porque no pueden retener un invariante vital que poseen en C: cualquier tipo de datos se puede usar como un tipo de componente.

Para hacer que los sindicatos sean útiles, debemos permitir tipos constructables como miembros. Esto es significativo porque no es aceptable simplemente asignar un componente en un cuerpo constructor, ya sea de la unión misma, o de cualquier estructura envolvente: no puede, por ejemplo, asignar una cadena a un componente de cadena no inicializada.

De esto se sigue que se deben inventar algunas reglas para inicializar el componente de unión con iniciadores de memoria, por ejemplo:

union X { string a; string b; X(string q) : a(q) {} };

Pero ahora la pregunta es: ¿cuál es la regla? Normalmente la regla es que debe inicializar cada miembro y base de una clase, si no lo hace explícitamente, el constructor predeterminado se usa para el resto, y si un tipo que no se inicializó explícitamente no tiene un constructor predeterminado, es un error [Excepción: copian los constructores, el valor predeterminado es el constructor de copia miembro].

Claramente, esta regla no puede funcionar para los sindicatos: la regla tiene que ser en su lugar: si la unión tiene al menos un miembro que no es POD, debe inicializar explícitamente exactamente un miembro en un constructor. En este caso, no se generarán ningún constructor, constructor de copia, operador de asignación o destructor por defecto, y si alguno de estos miembros se usa realmente, debe proporcionarse explícitamente.

Entonces, ahora la pregunta es: ¿cómo escribirías, digamos, un constructor de copias? Por supuesto, es muy posible hacerlo y hacerlo bien si diseña su sindicato de la manera en que, por ejemplo, las uniones de eventos X-Windows están diseñadas: con la etiqueta discriminante en cada componente, pero deberá usar el operador de ubicación nuevo para hacerlo , y tendrá que romper la regla que escribí arriba, que a primera vista parecía correcta.

¿Qué pasa con el constructor predeterminado? Si no tiene uno de esos, no puede declarar una variable no inicializada.

Existen otros casos en los que puede determinar el componente externamente y usar la colocación nueva para administrar una unión externamente, pero eso no es un constructor de copia. El hecho es que si tiene N componentes necesitaría N constructores, y C ++ tiene una idea equivocada de que los constructores usan el nombre de clase, lo que le deja bastante corto de nombres y le obliga a usar tipos fantasma para permitir que la sobrecarga elija la correcta constructor ... y no puede hacer eso para el constructor de copia ya que su firma está arreglada.

Ok, entonces ¿hay alternativas? Probablemente, sí, pero no son tan fáciles de soñar, y es más difícil convencer a más de 100 personas de que vale la pena pensar en una reunión de tres días repleta de otros problemas.

Es una lástima que el comité no haya implementado la regla anterior: los sindicatos son obligatorios para alinear datos arbitrarios y la administración externa de los componentes no es realmente tan difícil de hacer de forma manual, y trivial y completamente segura cuando el código es generado por un algoritmo adecuado, en otras palabras, la regla es obligatoria si desea utilizar C ++ como lenguaje de destino del compilador y aún así generar código legible y portátil. Tales uniones con miembros constructables tienen muchos usos, pero el más importante es representar el marco de pila de una función que contiene bloques anidados: cada bloque tiene datos locales en una estructura, y cada estructura es un componente de unión, no hay necesidad de ningún constructor o tal, el compilador usará la colocación nueva. La unión proporciona alineación y tamaño, y libera el acceso a componentes. [¡Y no hay otra forma de cumplir la alineación correcta!]

Por lo tanto, la respuesta a su pregunta es: usted está haciendo la pregunta incorrecta. No hay ninguna ventaja para las uniones POD-only como bases, y ciertamente no se pueden derivar clases porque entonces no serían POD. Para que sean útiles, se necesita tiempo para comprender por qué uno debe seguir el principio utilizado en todas partes en C ++: los bits que faltan no son un error a menos que intente usarlos.


Union es un tipo que se puede usar como cualquiera de sus miembros, según el miembro que se haya configurado; solo ese miembro se puede leer más adelante.

Cuando se deriva de un tipo, el tipo derivado hereda el tipo base; el tipo derivado se puede usar donde quiera que esté el tipo base. Si pudiera derivarse de un sindicato, la clase derivada podría utilizarse (no de forma implícita, sino explícita mediante el nombramiento del miembro) donde sea que se pueda usar cualquiera de los miembros del sindicato, pero entre esos miembros solo se podría acceder legalmente a un miembro. El problema es que los datos sobre qué miembro se ha establecido no se almacenan en la unión.

Para evitar esta contradicción sutil pero peligrosa que de hecho subvierte un sistema de tipo derivado de una unión no está permitido.