2011-03-26 16 views
16

Tengo una clase y una variable const.¿No puede C++ tipo POD tener cualquier constructor?

struct A 
{ 
    int b; 
}; 

A const a; 

La clase A es POD y se puede inicializar de esta manera.

A const a = { 3 }; 

En mi humilde opinión, parece que tiene un constructor como este.

struct A 
{ 
    int b; 

    A(int newB) : b(newB) 
    { 
    } 
}; 

Pero Clang supone A como tipo no agregado. ¿Por qué no puedo tener un constructor así? ¿O debería hacer algo más?


He modificado la pregunta para que presente mi significado original. Había escribió el struct como class por error, y lo siento por @Johannes acerca confuso :)

+0

Eonil : Creo que mi respuesta aclara todas sus dudas, especialmente la cita del Estándar. – Nawaz

+0

Debe decidir de qué se trata la pregunta: 1) tipos de POD o 2) simplemente la capacidad de usar el inicializador '{}' (es decir, agregados). En este momento no está claro cuál es específicamente el problema. – AnT

+0

@Nawaz Gracias por su atención. Tu respuesta es lo que quiero! – Eonil

Respuesta

17

POD significa Tipo de datos Plain Old que por definición no puede tener constructor definido por el usuario.

POD es en realidad un tipo agregado (consulte la próxima cita). Entonces, ¿qué es agregado? El estándar de C++ dice en la sección §8.5.1/1,

Un agregado es una matriz o una clase (cláusula 9) con no-declarado de usuario constructores (12.1), no privado o protegido miembros de datos no estáticos (cláusula 11), sin clases base (cláusula 10) y sin funciones virtuales (10.3).

Y la sección § 9/4 del estándar de C++ dice,

[....] Un POD-estructura es una clase agregada que no tiene datos no estáticos miembros de de tipo no-POD-struct, no POD-unión (o matriz de tales tipos) o de referencia, y tiene no copia operador de asignación definida por el usuario y no destructor definido por el usuario. Del mismo modo, un POD-unión es una unión agregado que no tiene miembros de datos no estáticos de tipo no POD-struct, no POD-unión (o variedad de tales tipos) o de referencia, y tiene no asignación de copia definida por el usuario operador y no definido por el usuario destructor. Una clase POD es una clase que es una POD-struct o una POD-union.

partir de esto, también es claro que la clase POD/struct/union aunque no puede tener operador de asignación definida por el usuario y destructor también definida por el usuario.


Sin embargo, hay otros tipos de POD. La sección §3.9/10 dice,

tipos aritméticas (3.9.1), tipos de enumeración, los tipos de puntero, y puntero a tipos miembros (3.9.2), y versiones CV-calificada de estos tipos (3,9 .3) se denominan colectivamente tipos escalares . tipos escalares, tipos de POD-struct, tipos POD-Unión (cláusula 9), matrices de tales tipos y versiones CV-calificado de estos tipos (3.9.3) son colectivamente llamados tipos POD.

Leer este FAQ: What is a "POD type"?

+0

¡Lo tengo! Gracias. – Eonil

5

La clase A es POD y se puede inicializar como esto

Lo sentimos, lo que está mal. Debido a que b es privado, la clase no es un POD.

Pero Clang asume A como tipo no agregado. ¿Por qué no puedo tener un constructor así? ¿O debería hacer algo más?

Esto es una limitación de C++ tal como existe actualmente. C++ 0x ya no tendrá esta limitación. Mientras que en C++ 0x tu tipo tampoco es un POD, tu inicialización funcionará (suponiendo que hagas ese constructor public).

(Además, creo que un término mejor para su uso aquí es "agregado". El requisito para usar { ... } es que su clase es un agregado. No tiene que ser un POD).

+1

Oh gracias. Fue mi error al usar 'clase' en lugar de' struct'. Lo siento. No me importa el acceso predeterminado. Actualicé mi pregunta Y el comentario para los tipos agregados pero no POD es útil en sí mismo :) – Eonil

2

Las otras respuestas describen las reglas POD bastante bien. Si usted desea conseguir un estilo de inicialización similar a un constructor para un POD se puede utilizar una función de estilo make_, por ejemplo:

struct A 
{ 
    int i_; 
}; 

A make_A(int i = 0) 
{ 
    A a = { i }; 
    return a; 
} 

casos POD ahora puede que éste se inicia como:

A a = make_A(); 
Cuestiones relacionadas