Namespaces
Variants

static members

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
explicit (C++11)
static

Special member functions
Templates
Miscellaneous

Dentro de una definición de clase, la palabra clave static declara miembros que no están vinculados a instancias de clase.

Fuera de la definición de una clase, tiene un significado diferente: consulta storage duration .

Contenidos

Sintaxis

Una declaración para un miembro estático es una declaración de miembro cuyos especificadores de declaración contienen la palabra clave static . La palabra clave static usualmente aparece antes de otros especificadores (por lo que la sintaxis se describe informalmente como static data-member o static member-function ), pero puede aparecer en cualquier lugar de la secuencia de especificadores.

El nombre de cualquier miembro de datos estático y función miembro estática debe ser diferente del nombre de la clase contenedora.

Explicación

Los miembros estáticos de una clase no están asociados con los objetos de la clase: son variables independientes con duración de almacenamiento o de hilo (desde C++11) storage duration o funciones regulares.

La static palabra clave solo se utiliza con la declaración de un miembro estático, dentro de la definición de la clase, pero no con la definición de ese miembro estático:

class X { static int 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 el miembro como de tipo incompleto (distinto de void ), incluyendo el tipo en el cual el miembro está declarado:

struct Foo;
struct S
{
    static int a[]; // declaración, tipo incompleto
    static Foo x;   // declaración, tipo incompleto
    static S s;     // declaración, tipo incompleto (dentro de su propia definición)
};
int S::a[10]; // definición, tipo completo
struct Foo {};
Foo S::x;     // definición, tipo completo
S S::s;       // definición, tipo completo

Sin embargo, si la declaración utiliza el especificador constexpr o inline (desde C++17) , el miembro debe declararse con tipo completo.

(desde C++11)

Para hacer referencia a un miembro estático m de la clase T , se pueden 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. Cuando se está en el mismo ámbito de la clase, la calificación no es necesaria:

struct X
{
    static void f(); // declaración
    static int n;    // declaración
};
X g() { return X(); } // alguna función que retorna X
void f()
{
    X::f();  // X::f es un nombre calificado de función miembro estática
    g().f(); // g().f es una expresión de acceso a miembro que referencia a una función miembro estática
}
int X::n = 7; // definición
void X::f() // definición
{
    n = 1; // X::n es accesible simplemente como n en este ámbito
}

Los miembros estáticos obedecen las reglas de acceso a miembros de clase (private, protected, public) .

Funciones miembro estáticas

Las funciones miembro estáticas no están asociadas con ningún objeto. Cuando se llaman, no tienen this pointer.

Las funciones miembro estáticas no pueden ser virtual , const , volatile , o ref-qualified .

La dirección de una función miembro estática puede almacenarse en un pointer to function normal, pero no en un pointer to member function .

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. Solo hay una instancia del miembro de datos estático en todo el programa con duración de almacenamiento estático , a menos que se use la palabra clave thread_local , en cuyo caso hay un objeto por hilo 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 el ámbito de un espacio de nombres tienen enlace externo si la clase misma tiene enlace externo (no es miembro de un espacio de nombres sin nombre ). Las clases locales (clases definidas dentro de funciones) y las clases sin nombre, incluyendo las clases miembro de clases sin nombre, no pueden tener miembros de datos estáticos.

Un miembro de datos estático puede declararse inline . Un miembro de datos estático inline puede definirse en la definición de la clase y puede especificar un inicializador. No requiere una definición fuera de la clase:

struct X
{
    inline static int fully_usable = 1; // No out-of-class definition required, ODR-usable
    inline static const std::string class_name{"X"}; // Likewise
    static const int non_addressable = 1; // C.f. non-inline constants, usable
                                          // for its value, but not ODR-usable
    // static const std::string class_name{"X"}; // Non-integral declaration of this
                                                 // form is disallowed entirely
};
(desde C++17)

Miembros estáticos constantes

Si un miembro de datos estático de tipo integral o de enumeración se declara const (y no volatile ), puede ser inicializado con un inicializador en el que cada expresión sea una expresión constante , directamente dentro de la definición de la clase:

struct X
{
    const static int n = 1;
    const static int m{2}; // desde C++11
    const static int k;
};
const int X::k = 3;

Si un miembro de datos estático de LiteralType se declara constexpr , debe ser inicializado con un inicializador en el que cada expresión sea una expresión constante, directamente dentro de la definición de la clase:

struct X
{
    constexpr static int arr[] = { 1, 2, 3 };        // OK
    constexpr static std::complex<double> n = {1,2}; // OK
    constexpr static int k; // Error: constexpr static requiere un inicializador
};
(desde C++11)

Si un dato miembro estático const no inline (desde C++17) o un constexpr dato miembro estático (desde C++11) (hasta C++17) es ODR-use , aún se requiere una definición en el ámbito del espacio de nombres, pero no puede tener un inicializador.

Un miembro de datos estático constexpr es implícitamente inline y no necesita ser redeclarado en el ámbito del espacio de nombres. Esta redeclaración sin un inicializador (anteriormente requerida) todavía está permitida, pero está obsoleta.

(since C++17)
struct X
{
    static const int n = 1;
    static constexpr int m = 4;
};
const int *p = &X::n, *q = &X::m; // X::n y X::m son utilizados en ODR
const int X::n;             // … por lo tanto una definición es necesaria
constexpr int X::m;         // … (excepto para X::m en C++17)

Palabras clave

static

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.

DR Aplicado a Comportamiento publicado Comportamiento correcto
CWG 194 C++98 los nombres de funciones miembro (estáticas) pueden ser iguales al nombre de la clase se añadió restricción de nomenclatura (incluyendo
funciones miembro no estáticas )

Referencias

  • Estándar C++23 (ISO/IEC 14882:2024):
  • 11.4.9 Miembros estáticos [class.static]
  • Estándar C++20 (ISO/IEC 14882:2020):
  • 11.4.8 Miembros estáticos [class.static]
  • Estándar C++17 (ISO/IEC 14882:2017):
  • 12.2.3 Miembros estáticos [class.static]
  • Estándar C++14 (ISO/IEC 14882:2014):
  • 9.4 Miembros estáticos [class.static]
  • Estándar C++11 (ISO/IEC 14882:2011):
  • 9.4 Miembros estáticos [class.static]
  • Estándar C++98 (ISO/IEC 14882:1998):
  • 9.4 Miembros estáticos [class.static]

Véase también