Las constantes definidas con const liberan su espacio después de salir de su ámbito, mientras que las constantes estáticas definidas con static no liberan su espacio de almacenamiento después de la ejecución de la función.

static indica estático. Las funciones miembro estáticas y las variables miembro estáticas de una clase están relacionadas con la clase, no con objetos específicos de la clase. Incluso sin un objeto concreto, se pueden invocar las funciones miembro estáticas y las variables miembro de la clase. Generalmente, una función estática de una clase es casi una función global, solo que su ámbito se limita al archivo que la contiene.

En C++, las variables miembro estáticas (static) no se pueden inicializar dentro de la clase. Dentro de la clase solo se declaran; la definición debe estar fuera del cuerpo de la clase, normalmente se inicializan en el archivo de implementación de la clase, por ejemplo:double Account::Rate = 2.25;

La palabra clave static solo se puede usar en la declaración dentro del cuerpo de la definición de la clase; al definir no se puede marcar como static.

En C++, las variables miembro const tampoco se pueden inicializar en la definición de la clase; solo se pueden inicializar mediante la lista de inicialización del constructor, y debe existir un constructor.

Los miembros de datos const solo son constantes durante el ciclo de vida de un objeto, pero son variables para toda la clase. Debido a que una clase puede crear múltiples objetos, los valores de los miembros de datos const pueden ser diferentes en distintos objetos. Por lo tanto, no se pueden inicializar los miembros de datos const en la declaración de la clase, porque cuando no se ha creado ningún objeto de la clase, el compilador no sabe cuál es el valor del miembro de datos const.

La inicialización de los miembros de datos const solo se puede realizar en la lista de inicialización del constructor de la clase. Si se desea establecer una constante que sea constante en toda la clase, se debe usar una constante de enumeración dentro de la clase, o static const.

class Test{ public: Test():a(0){} enum {size1=100,size2=200}; private: const int a;//Solo se puede inicializar en la lista de inicialización del constructor static int b;//Definir e inicializar en el archivo de implementación de la clase conststatic int c;//Igual que static const int c; }; int Test::b=0;//Las variables miembro static no se pueden inicializar en la lista de inicialización del constructor porque no pertenecen a ningún objeto. cosnt intTest::c=0;//Nota: al asignar un valor a una variable miembro estática, no se necesita el modificador static, pero sí se debe añadir const.

El propósito principal de las funciones miembro const es evitar que la función miembro modifique el contenido del objeto. Es decir, una función miembro const no puede modificar el valor de las variables miembro, pero puede acceder a ellas. Cuando se trata de un método miembro, dicha función solo puede ser una función miembro const.

El propósito principal de las funciones miembro static es actuar como funciones globales dentro del ámbito de la clase. No pueden acceder a los miembros de datos no estáticos de la clase. Las funciones miembro estáticas de una clase no tienen puntero this, lo que conlleva:

  • 1. No pueden acceder directamente a las variables miembro no estáticas de la clase ni invocar funciones miembro no estáticas.
  • 2. No pueden declararse como virtual.

Sobre el problema de inicialización de los miembros static, const, static const y const static

1. Inicialización de miembros const en una clase:

Al crear un const en una clase, no se le puede dar un valor inicial.

class foo{ public: foo():i(100){} private: const int i=100;//error!!! }; //O inicializar de esta manera foo::foo():i(100){}

2. Inicialización de miembros static en una clase:

Las variables static en una clase pertenecen a la clase, no a un objeto. Tienen una única copia durante toda la ejecución del programa, por lo tanto no se pueden inicializar al definir objetos, es decir, no se pueden inicializar con un constructor. El método correcto de inicialización es:

Tipo de datos NombreClase::nombreMiembroDatoEstático = valor;
class foo{ public: foo(); private: staticint i; }; intfoo::i=20;

Esto indica:

  • 1. La inicialización se realiza fuera del cuerpo de la clase, sin anteponer static, para evitar confundirla con variables u objetos estáticos comunes.
  • 2. Al inicializar no se agregan los calificadores de acceso del miembro, como private, public, etc.
3. Al inicializar se utiliza el operador de ámbito para indicar a qué clase pertenece. Por lo tanto, los miembros de datos estáticos son miembros de la clase, no miembros del objeto.

3. Inicialización de miembros static const y const static en una clase

Estas dos formas tienen el mismo efecto. Para facilitar la memorización, aquí solo se explica un método de inicialización general:

class Test{ public: static const int mask1; conststatic int mask2; }; constTest::mask1=0xffff; constTest::mask2=0xffff; //Su inicialización no tiene diferencia, aunque uno es constante estática y el otro es estática constante. Los estáticos se almacenarán en el área de variables globales; en realidad el resultado final es el mismo. Puede que en diferentes compiladores se manejen de forma distinta, pero el resultado final es el mismo.

Ejemplo completo

Ejemplo

#ifdef A_H_ #define A_H_ #include <iostream> usingnamespace std; class A{ public: A(int a); staticvoid print();//Función miembro estática private: static int aa;//Declaración de miembro de datos estático staticconst int count;//Miembro de datos estático constante (se puede inicializar en el constructor) const int bb;//Miembro de datos constante }; int A::aa=0;//Definición e inicialización de miembro estático const int A::count=25;//Definición e inicialización de miembro estático constante A::A(int a):bb(a){//Inicialización de miembro constante aa+=1; } void A::print(){ cout<<"count="<<count<<endl; cout<<"aa="<<aa<<endl; } #endif void main(){ A a(10); A::print();//Acceder a la función miembro estática a través de la clase a.print();//Acceder a la función miembro estática a través de un objeto }

Ubicación de la inicialización

Los miembros estáticos no se pueden inicializar en la definición de la clase (excepto int). No se pueden inicializar en el archivo de cabecera.

Por ejemplo, si se define myclass.h, normalmente se inicializa en myclass.cpp.


Miembros estáticos de clases en C++ (static)

Los miembros estáticos se proponen para resolver el problema de compartir datos. Hay muchas formas de lograr el intercambio; por ejemplo, establecer variables u objetos globales es una forma. Sin embargo, las variables u objetos globales tienen limitaciones. En este capítulo, nos centramos en los miembros estáticos de la clase para implementar el intercambio de datos.

Miembros de datos estáticos

En una clase, los miembros estáticos pueden lograr el intercambio de datos entre múltiples objetos, y el uso de miembros de datos estáticos no viola el principio de ocultamiento, lo que garantiza la seguridad. Por lo tanto, los miembros estáticos son miembros compartidos por todos los objetos de la clase, no miembros de un objeto particular.

El uso de miembros de datos estáticos puede ahorrar memoria, porque son comunes a todos los objetos. Por lo tanto, para múltiples objetos, el miembro de datos estático se almacena en un solo lugar y es compartido por todos los objetos. El valor del miembro de datos estático es el mismo para cada objeto, pero su valor se puede actualizar. Basta con actualizar el valor del miembro de datos estático una vez para garantizar que todos los objetos accedan al mismo valor actualizado, lo que puede mejorar la eficiencia temporal.

Los métodos de uso y las precauciones de los miembros de datos estáticos son los siguientes:

1. Al definir o declarar un miembro de datos estático, se antepone la palabra clave static.

2. La inicialización de los miembros estáticos es diferente de la inicialización de los miembros de datos generales. El formato de inicialización de un miembro de datos estático es el siguiente:

 
<Tipo de datos><NombreClase>::<nombreMiembroDatoEstático> = <valor>

Esto indica:

  • (1) La inicialización se realiza fuera del cuerpo de la clase, sin anteponer static, para evitar confundirla con variables u objetos estáticos comunes.
  • (2) Al inicializar no se agregan los calificadores de acceso del miembro, como private, public, etc.
  • (3) Al inicializar se utiliza el operador de ámbito para indicar la clase a la que pertenece. Por lo tanto, los miembros de datos estáticos son miembros de la clase, no miembros del objeto.

3. Los miembros de datos estáticos se almacenan estáticamente; tienen una vida útil estática y deben inicializarse.

4. Al hacer referencia a un miembro de datos estático, se utiliza el siguiente formato:

<NombreClase>::<nombreMiembroEstático>

Si los permisos de acceso del miembro de datos estático lo permiten (es decir, si es un miembro public), se puede hacer referencia al miembro de datos estático en el programa según el formato anterior.

A continuación se da un ejemplo para ilustrar la aplicación de los miembros de datos estáticos:

Ejemplo

#include … class Myclass{ public: Myclass(int a, int b, int c); void GetNumber(); void GetSum(); private: int A, B, C; static int Sum; }; int Myclass::Sum = 0; Myclass::Myclass(int a, int b, int c){ A = a; B = b; C = c; Sum += A+B+C; } void Myclass::GetNumber(){ cout<<"Number="<<a<<","<<b<<","<<c<<endl; } void Myclass::GetSum(){ cout<<"Sum="<<sum<<endl; } void main(){ Myclass M(3, 7, 10),N(14, 9, 11); M.GetNumber(); N.GetNumber(); M.GetSum(); N.GetSum(); }

A partir del resultado de salida se puede ver que el valor de Sum es igual tanto para el objeto M como para el objeto N. Esto se debe a que al inicializar el objeto M, la suma de los tres miembros de datos de tipo int del objeto M se asigna a Sum, por lo que Sum guarda ese valor. Al inicializar el objeto N, la suma de los tres miembros de datos de tipo int del objeto N se añade al valor existente de Sum, por lo que Sum guardará el nuevo valor. Por lo tanto, el valor referenciado ya sea a través del objeto M o del objeto N es el mismo, es decir, 54.

Funciones miembro estáticas

Las funciones miembro estáticas, al igual que los miembros de datos estáticos, pertenecen a los miembros estáticos de la clase y no son miembros de objeto. Por lo tanto, no se necesita el nombre del objeto para hacer referencia a los miembros estáticos.

En la implementación de una función miembro estática no se pueden referenciar directamente los miembros no estáticos declarados en la clase, pero sí se pueden referenciar los miembros estáticos declarados en la clase. Si en una función miembro estática se desea hacer referencia a un miembro no estático, se puede hacer a través de un objeto. A continuación se explica esto con un ejemplo.

Ejemplo

#include … class M{ public: M(int a){ A=a; B+=a; } static void f1(M m); private: int A; static int B; }; void M::f1(M m) { cout<<"A="<<m.a<<endl; cout<<"B="<<b<<endl; } int M::B=0; void main() { M P(5),Q(10); M::f1(P); //Al invocar no se usa el nombre del objeto M::f1(Q); }

El lector puede analizar el resultado por sí mismo. De ello se puede ver que para invocar una función miembro estática se utiliza el siguiente formato:

  
<NombreClase>::<nombreFunciónMiembroEstático>(<lista de parámetros>);

Métodos de inicialización de variables miembro de varios tipos en C++

En C++, los diferentes tipos de miembros tienen métodos de inicialización distintos según sean static o const. La sintaxis de Java no es tan complicada; no es de extrañar que tanta gente se haya ido a aprender Java. Antes, en una entrevista me preguntaron esto y no supe responder; al escribir código también solía confundirme. Aquí he revisado los libros y hago un resumen.

//-----------------Test.h---------------------------- #pragma once class Test { private : int var1; // int var11= 4; Método de inicialización incorrecto const int var2 ; // const int var22 =22222; Método de inicialización incorrecto static int var3; // static int var3333=33333; Error, solo los miembros int constantes estáticos pueden inicializarse mediante asignación directa static const int var4=4444; // Correcto, los miembros constantes estáticos pueden inicializarse directamente static const int var44; public: Test(void); ~Test(void); }; //--------------------Test.cpp----------------------------------- #include ".\test.h" int Test::var3 = 3333333; // Método correcto de inicialización de miembros estáticos // int Test::var1 = 11111;; Error, solo los miembros estáticos pueden inicializarse así // int Test::var2 = 22222; Error // int Test::var44 = 44444; // Método incorrecto, indica redefinición Test::Test(void):var1(11111),var2(22222)Método de inicialización correcto// var3(33333) no puede inicializarse aquí { var1 =11111; // Correcto, las variables normales también pueden inicializarse aquí // var2 = 222222; Error, porque una constante no puede ser asignada, solo puede inicializarse en el "constructor initializer (lista de inicialización del constructor)" var3 =44444; // Esta asignación es correcta, pero como todos los objetos comparten un miembro estático, afectará a los demás; esto ya no puede llamarse inicialización } Test::~Test(void){} //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Algunos tipos de datos de variables miembro son especiales, y su forma de inicialización también difiere de la de las variables miembro de tipos de datos normales. Estos tipos especiales de variables miembro incluyen:

  • a. Variables miembro de tipo constante
  • b. Variables miembro de tipo referencia
  • c. Variables miembro estáticas
  • d. Variables miembro constantes estáticas de tipo entero
  • e. Variables miembro constantes estáticas de tipo no entero

Para la inicialización de las variables miembro de tipo constante y las variables miembro de tipo referencia, debe realizarse mediante la lista de inicialización del constructor. La forma de asignar valores a las variables miembro de tipo constante y de tipo referencia dentro del cuerpo del constructor no es viable.

La inicialización de las variables miembro estáticas también es bastante especial.

Consulte el siguiente código y sus comentarios:

// Initialization of Special Data Member #include <iostream> using namespace std; class BClass { public: BClass() : i(1),ci(2), ri(i) // Para las variables miembro de tipo constante y las variables miembro de tipo referencia, debe realizarse mediante { // la lista parametrizada para la inicialización. La asignación dentro del cuerpo del constructor no es viable. } voidprint_values() { cout<< "i =\t" << i << endl; cout<< "ci =\t" << ci << endl; cout<< "ri =\t" << ri << endl; cout<< "si =\t" << si << endl; cout<< "csi =\t" << csi << endl; cout<< "csi2 =\t" << csi2 << endl; cout<< "csd =\t" << csd << endl; } private: inti; // Variable miembro normal constint ci; // Variable miembro constante int&ri; // Variable miembro de referencia staticint si; // Variable miembro estática //staticint si2 = 100; // error: solo las variables miembro constantes estáticas pueden inicializarse de esta manera staticconst int csi; // Variable miembro constante estática staticconst int csi2 = 100; // Inicialización de variables miembro constantes estáticas (Integral type) (1) staticconst double csd; // Variable miembro constante estática (non-Integral type) //staticconst double csd2 = 99.9; // error: solo los miembros de datos enteros estáticos constantes pueden inicializarse dentro de la clase }; // Inicialización de variables miembro estáticas (Integral type) int BClass::si = 0; // Inicialización de variables miembro constantes estáticas (Integral type) const int BClass::csi = 1; // Inicialización de variables miembro constantes estáticas (non-Integral type) const double BClass::csd = 99.9; // Al inicializar csi2 en (1), según Stanley B. Lippman, la siguiente línea es necesaria. // Pero en VC2003, si existe la siguiente línea, se producirá un error; mientras que en VC2005, esta línea es opcional. Esto depende del compilador. const int BClass::csi2; int main(void) { BClassb_class; b_class.print_values(); return0; }

Resumen de miembros estáticos en C++, C++, static

Los miembros estáticos en una clase son realmente una característica que despierta sentimientos encontrados. Una vez, en una entrevista, el examinador me acosó con este tema sin tregua, hasta que me puse rojo de vergüenza y fui derrotado. Así que cuando volví

, reflexioné detenidamente y decidí resumir bien los puntos de conocimiento sobre los miembros estáticos de clase, para no volver a estar en una posición pasiva en este tipo de preguntas en futuras entrevistas.

Los miembros estáticos de clase incluyen dos partes: miembros de datos estáticos y miembros de funciones estáticas.

Miembros de datos estáticos

Si se agrega la palabra clave static antes de la declaración de un miembro de datos en el cuerpo de la clase, ese miembro de datos se convierte en un miembro de datos estático de la clase. Al igual que otros miembros de datos, los miembros de datos estáticos también cumplen las reglas de acceso public/protected/private. Además, los miembros de datos estáticos tienen las siguientes características:

1. Definición de los miembros de datos estáticos.

Los miembros de datos estáticos son en realidad variables globales en el ámbito de la clase. Por lo tanto, la definición (inicialización) de los miembros de datos estáticos no debe colocarse en archivos de cabecera. (Declaración vs. definición (inicialización)) Su forma de definición es la misma que la de las variables globales. Por ejemplo:

xxx.hArchivoclass base{ private: static const int _i;// Declaración. El C++ estándar admite la inicialización de tipos integrales en el cuerpo de la clase, pero VC6 no lo admite. }; xxx.cppArchivoconst int base::_i=10;// La definición (inicialización) no está sujeta a las restricciones de acceso private y protected.

Nota:No intente definir (inicializar) miembros de datos estáticos en archivos de cabecera. En la mayoría de los casos, esto provocará errores como la redefinición. Incluso si se agrega#ifndef #define #endifo#pragma oncetampoco funciona.

2. Los miembros de datos estáticos son compartidos por todos los objetos de la clase, incluidos los objetos de las clases derivadas. Es decir, los objetos de la clase derivada comparten los miembros de datos estáticos de la clase base con los objetos de la clase base. Por ejemplo:

class base{ public : static int _num;// Declaración }; int base::_num=0;// Definición real del miembro de datos estático class derived:public base{ }; main() { base a; derived b; a._num++; cout<<"base class static data number_num is"<<a._num<<endl; b._num++; cout<<"derived class static datanumber _num is"<<b._num<<endl; } // El resultado es 1,2; se puede ver que la clase derivada y la clase base comparten el mismo miembro de datos estático.

3. Los miembros de datos estáticos pueden ser parámetros opcionales de las funciones miembro, mientras que los miembros de datos normales no pueden. Por ejemplo:

class base{ public : static int _staticVar; int _var; void foo1(int i=_staticVar);// Correcto, _staticVar es un miembro de datos estático void foo2(int i=_var);// Error, _var es un miembro de datos normal };

4. El tipo de un miembro de datos estático puede ser el tipo de la clase a la que pertenece, mientras que un miembro de datos normal no puede. Un miembro de datos normal solo puede declararse como puntero o referencia al tipo de la clase a la que pertenece. Por ejemplo:

class base{ public : static base_object1;// Correcto, miembro de datos estático base _object2;// Error base *pObject;// Correcto, puntero base &mObject;// Correcto, referencia };

5. Esta característica, no sé si pertenece al C++ estándar o si es una característica propia de VC6.

El valor de un miembro de datos estático puede modificarse legalmente dentro de una función miembro const. Por ejemplo:

class base{ public: base(){ _i=0; _val=0; } mutable int _i; static int _staticVal; int _val; void test() const{// Función miembro const _i++;// Correcto, miembro de datos mutable _staticVal++;// Correcto, miembro de datos static _val++;// Error } }; int base::_staticVal=0;

Funciones miembro estáticas

No hay mucho que decir sobre las funciones miembro estáticas.

1. La dirección de una función miembro estática puede almacenarse con un puntero a función normal, mientras que la dirección de una función miembro normal necesita almacenarse con un puntero a función miembro de clase. Por ejemplo:

class base{ static int func1(); int func2(); }; int (*pf1)()=&base::func1;// Puntero a función normal int (base::*pf2)()=&base::func2;// Puntero a función miembro

2. Las funciones miembro estáticas no pueden llamar a miembros no estáticos de la clase, porque las funciones miembro estáticas no contienen el puntero this.

3. Las funciones miembro estáticas no pueden declararse como funciones virtual, const o volatile. Por ejemplo:

class base{ virtual static void func1();// Error static void func2() const;// Error static void func3() volatile;// Error };

Por último, hay que decir que los miembros estáticos pueden accederse de forma independiente, es decir, se pueden acceder sin necesidad de crear ninguna instancia de objeto.

Autor: SDMrFeng

Original: https://blog.csdn.net/tobefxz/article/details/14109697