28 votos

¿Por qué C++11 del POD "diseño estándar" de la definición de la forma que es?

Estoy buscando en el nuevo, relajado POD definición en C++11 (sección 9.7)

Un estándar de diseño de la clase es una clase que:

  • no tiene no miembros de datos estáticos de tipo no-estándar-clase de diseño (o de la matriz de dichos tipos) o de referencia,
  • no tiene funciones virtuales (10.3) y no virtual de clases base (10.1),
  • tiene el mismo control de acceso (Cláusula 11) para todos los que no son miembros de datos estáticos,
  • no tiene no-estándar-diseño de clases base,
  • no tiene no miembros de datos estáticos en la mayoría de los derivados de la clase y en más de una clase base con los no-miembros de datos estáticos, o no tiene clases base con los no-miembros de datos estáticos, y
  • no tiene clases base del mismo tipo que el primer no-miembro de datos estáticos.

He resaltado los bits que me sorprendió.

¿Qué podría ir mal si hemos tolerado miembros de datos con diferentes controles de acceso?

¿Qué podría ir mal si el primer miembro de datos también fue una clase base? es decir,

struct Foo {};
struct Good : Foo {int x; Foo y;};
struct Bad  : Foo {Foo y; int x;};

Admito que es raro construcción, pero ¿por qué, Bad ser prohibida, pero no Good?

Por último, ¿qué podría ir mal si más de uno de los componentes de la clase había miembros de datos?

19voto

Steve Jessop Puntos 166970

Es básicamente acerca de la compatibilidad con C++03 y C:

  • mismo control de acceso - C++03 implementaciones están autorizados a utilizar especificadores de control de acceso como una oportunidad para re-ordenar el (grupos de) los miembros de una clase, por ejemplo, de los pack que mejor.
  • más de una clase en la jerarquía con los no-miembros de datos estáticos - C++03 no dice donde las clases base se encuentra, o si el relleno se elide en la base de la clase de subobjetos que estaría presente en un objeto del mismo tipo.
  • clase base y el primer miembro del mismo tipo - a causa de la segunda regla, si el tipo de clase base se utiliza para un miembro de datos, entonces debe ser una clase vacía. Muchos compiladores de hacer aplicar el vacío de la clase base de la optimización, así que lo Andreas dice acerca de los sub-objetos que tienen la misma dirección sería cierto. No estoy seguro de que a pesar de lo que se trata estándar de diseño de clases que significa que es malo para la clase base subobjeto tienen la misma dirección, como primer miembro de datos del mismo tipo, pero no importa cuando la clase base subobjeto tiene la misma dirección como primer miembro de datos de un tipo diferente. [Edit: es debido a que los diferentes objetos de un mismo tipo tienen diferentes direcciones, incluso si está vacío sub-objetos. Gracias a Johannes]

C++0x probablemente podría haber definido que esas cosas son estándar de diseño de tipos demasiado, en cuyo caso se podría definir también cómo están establecidos, en la misma medida que lo hace para el estándar de diseño de tipos. Johannes la respuesta va en este más, mira a su ejemplo de una agradable propiedad de la norma de diseño de clases que estas cosas pueden interferir con.

Pero si lo hizo, entonces algunas implementaciones se verían obligados a cambiar la forma de diseñar las clases para ajustarse a los nuevos requerimientos, lo cual es una molestia para la estructura de la compatibilidad entre las diferentes versiones de compilador de pre - y post - C++0x. Se rompe el C++ ABI, básicamente.

Mi comprensión de cómo un diseño estándar fue definido es que se veían a lo que POD requisitos podría estar relajado, sin romper las implementaciones existentes. Así que yo supongo que sin comprobar, que los anteriores son ejemplos en los que algunos de los actuales C++03 aplicación hace uso de la no-POD naturaleza de la clase para hacer algo que es incompatible con un diseño estándar.

18voto

Johannes Schaub - litb Puntos 256113

Se le permite lanzar un estándar de diseño del objeto de la clase de dirección de un puntero a su primer miembro y la espalda por uno de los últimos párrafos, que es también a menudo se hace en C:

struct A { int x; };
A a;

// "px" is guaranteed to point to a.x
int *px = (int*) &a;

// guaranteed to point to a
A *pa = (A*)px; 

Para que funcione, el primer miembro y el objeto completo tiene que tener la misma dirección (el compilador no puede ajustar el puntero int por cualquier bytes porque no puede saber si se trata de un miembro de una A o no).

Por último, ¿qué podría ir mal si más de uno de los componentes de la clase había miembros de datos?

Dentro de una clase, los miembros son asignados en el aumento de las direcciones de acuerdo a la orden de declaración. Sin embargo C++ no dicta la orden de asignación de los datos de los miembros a través de las clases. Si tanto la derivada de la clase base y la clase había miembros de datos, el Estándar no define a una orden de sus direcciones a propósito, a fin de dar una implementación completa flexibilidad en la publicación de la memoria. Pero por encima de yeso para el trabajo, usted necesita saber lo que es el "primero" de miembro de la orden de asignación!

¿Qué podría ir mal si el primer miembro de datos también fue una clase base?

Si la clase base tiene el mismo tipo que el primer miembro de datos, la implementación de ese lugar las clases de base antes de la clase derivada de los objetos en la memoria tendría que tener un relleno de bytes antes de que el objeto de clase derivada de los miembros de datos en la memoria (de la clase base tendría el tamaño de una), para evitar tener la misma dirección de la clase base y el primer miembro de datos (en C++, dos objetos distintos del mismo tipo siempre tienen diferentes direcciones). Pero que volvería a hacer imposible lanzar la dirección del objeto de clase derivada para el tipo de su primer miembro de datos.

6voto

Bo Persson Puntos 42821

¿Qué podría ir mal si hemos tolerado miembros de datos con diferentes controles de acceso?

El lenguaje actual dice que el compilador no puede reordenar los miembros bajo el mismo control de acceso. Como:

struct x
{
public:
    int x;
    int y;
private:
    int z;
};

Aquí x debe ser asignado antes de y, pero no hay ninguna restricción en z en relación a x y y.

struct y
{
public:
    int x;
public:
    int y;
};

El nuevo texto dice que y es todavía un POD a pesar de los dos publics. Esto es en realidad una relajación de las reglas.

4voto

Andreas Brinck Puntos 23806

En cuanto a porqué Bad no está permitido dejar que me quoute de un artículo que he encontrado:

Esto asegura que dos de los subobjetos que tienen el mismo tipo de clase y que pertenecen a la misma la mayoría de los derivados de objeto no se encuentran asignados a la misma dirección.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2172.html

2voto

Nicolas Grebille Puntos 872

De viñeta 5, parece que ambos son no pod ya que la mayoría de la clase derivada tiene un no miembro de datos estáticos (int), no puede tener una clase base con los no-miembro de datos estáticos.

Yo lo entiendo como: "sólo uno de la "base" de la clase (es decir, de la misma clase o de una de las clases que heredan de la) puede hacer que los no-miembros de datos estáticos"

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X