Miembros estáticos
Dentro de una definición de clase, la palabra clave static declara miembros que no están enlazados a instancias de clase.
Fuera de la definición de clase, tiene otro significado: véase duración de almacenamiento.
Contenido |
[editar]Sintaxis
Una declaración de miembro estático es una declaración de miembro cuyos especificadores de declaración contienen la palabra clave static. Normalmente la palabra clave static aparece antes que otros especificadores (razón por la cual la sintaxis a menudo se describe informalmente como staticmiembro-de-datos o staticfunción-miembro), pero puede aparecer en cualquier lugar en la secuencia de especificacores.
El nombre de cualquier miembro de datos estático o función miembro estática debe ser diferente del nombre de la clase que lo contiene.
[editar]Explicación
Los miembros estáticos de una clase no están asociados con objetos de la clase: son variables independientes con duración de almacenamiento estático o de hilo(desde C++11) o funciones regulares.
La palabra clave static solamente se usa en la declaración de un miembro estático, dentro de la definición de clase, no en la definición de estos miembros estáticos:
class X {staticint n;};// declaración (usa 'static')int X::n=1;// definición (no usa 'static')
La declaración dentro del cuerpo de la clase no es una definición y puede declarar que el miembro es de tipo incompleto (que no sea void), incluido el tipo en el que se declara el miembro:
struct Foo; struct S {staticint a[];// declaración, tipo incompletostatic Foo x;// declaración, tipo incompletostatic S s;// declaración, tipo incompleto (dentro de su propia definición)}; int S::a[10];// definición, tipo completostruct Foo {}; Foo S::x;// definición, tipo completo S S::s;// definición, tipo completo
Sin embargo, si la declaración usa el especificador constexpr o inline(desde C++17), el miembro tiene que ser declarado de tipo completo. | (desde C++11) |
Para referirse a un miembro estático m
de la clase T
, se puede usar dos formas: nombre calificado T::m
o expresión de acceso a miembro E.m
o E->m
, donde E
es una expresión que se evalúa a T
o T*
respectivamente. En el mismo ámbito de la clase, no es necesaria la calificación:
struct X {staticvoid f();// declaraciónstaticint n;// declaración}; X g(){return X();}// una función que devuelve X void f(){ X::f();// X::f es un nombre calificado de una función miembro estática g().f();// g().f es una expresión de acceso a miembro que se refiere a una // función miembro estática} int X::n=7;// definición void X::f()// definición { n =1;// X::n es accesible porque n está en el ámbito}
Los miembros estáticos siguen las reglas de acceso a miembros de clase (private, protected, public).
[editar]Funciones miembro estáticas
Las funciones miembro estáticas no están asociadas a ningún objeto. Cuando se llaman, no tienen puntero this.
Las funciones miembro estáticas no pueden ser virtual, const, volatile, o calificadas por referencia.
La dirección de una función miembro estática se puede almacenar en un puntero a función normal, pero no es un puntero a función miembro.
[editar]Miembros de datos estáticos
Los miembros de datos estáticos no están asociados con ningún objeto. Existen incluso si no se han definido objetos de la clase. Solamente hay una instancia del miembro de datos estático en todo el programa con duración de almacenamiento estática , a no ser que se use la palabra clave thread_local, en cuyo caso hay un objeto de este tipo por hilo de ejecución con duración de almacenamiento de hilo(desde C++11).
Los miembros de datos estáticos no pueden ser mutable.
Los miembros de datos estáticos de una clase en un ámbito de espacio de nombres tienen enlace externo si la clase misma tiene enlace externo (no es miembro de un espacio de nombres anónimo). Las clases locales (definidas dentro de funciones) y clases anónimas, incluyendo clases miembro de clases anónimas, no pueden tener miembros de datos estáticos.
Un miembro de datos estático se puede declarar inline. Un miembro de datos estático en línea se puede definir dentro de la definición de clase y se puede especificar un inicializador. No necesita una definición fuera de la clase: struct X {inlinestaticint n =1;}; | (desde C++17) |
[editar]Miembros estáticos constantes
Si se declara const (y no volatile) un miembro de datos estático, se puede inicializar con un inicializador en el que cada expresión es una expresión constante, dentro de la definición de clase:
struct X {conststaticint n =1;conststaticint m{2};// desde C++11conststaticint k;};constint X::k=3;
Si un miembro de datos estático de LiteralType se declara constexpr, se debe inicializar con un inicializador en el que cada expresión sea una expresión constante, dentro de la definición de clase: struct X {constexprstaticint arr[]={1, 2, 3};// correctoconstexprstaticstd::complex<double> n ={1,2};// correctoconstexprstaticint k;// Error: constexpr static requiere un inicializador}; | (desde C++11) |
Si un miembro de datos estático constante no en línea(desde C++17)o un miembro de datos estático constexpr(desde C++11)(hasta C++17) es de uso odr, todavía se requiere una definición en el ámbito del espacio de nombres, pero no puede tener un inicializador. Se puede proporcionar una definición aunque sea redundante(desde C++17).
struct X {staticconstint n =1;staticconstexprint m =4;}; constint*p =&X::n, *q =&X::m;// X::n y X::m son de uso odrconstint X::n;// … por lo que se necesita una definiciónconstexprint X::m;// … (excepto para X::m en C++17)
Si se declara constexpr un miembro de datos estático , es implícitamente inline y no es necesario redeclararlo en el ámbito de espacios de nombres. Todavía se permite esta redeclaración sin un inicializador (anteriormente requerida como se muestra arriba), pero está en desuso. | (desde C++17) |
[editar]Informe de defectos
Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.
ID | Aplicado a | Comportamiento según lo publicado | Comportamiento correcto |
---|---|---|---|
CWG 194 | C++98 | los nombres de funciones miembro (estáticas) pueden tener el mismo nombre que la clase | se añade restricción de nombre (incluyendo funciones miembro no estáticas) |
[editar]Referencias
- El estándar C++20 (ISO/IEC 14882:2020):
- 11.4.8 Static members [class.static]
- El estándar C++17 (ISO/IEC 14882:2017):
- 12.2.3 Static members [class.static]
- El estándar C++14 (ISO/IEC 14882:2014):
- 9.4 Static members [class.static]
- El estándar C++11 (ISO/IEC 14882:2011):
- 9.4 Static members [class.static]
- El estándar C++98 (ISO/IEC 14882:1998):
- 9.4 Static members [class.static]