programas - programa c++
La palabra clave estática y sus diversos usos en C++ (9)
¿Qué significa con la variable local? ¿Es eso una función variable local?
Sí - No global, como una variable local de función.
Porque también existe eso cuando declara una función local como estática que solo se inicializa una vez, la primera vez que ingresa a esta función.
Derecha.
También solo habla de la duración del almacenamiento con respecto a los miembros de la clase, ¿qué pasa si no es específico de la instancia, eso también es una propiedad de no estática? ¿O es esa duración de almacenamiento?
class R { static int a; }; // << static lives for the duration of the program
that is to say, all instances of R
share int R::a
-- int R::a
is never copied.
Now what about the case with static and file scope?
Effectively a global which has constructor/destructor where appropriate -- initialization is not deferred until access.
How does static relate to the linkage of a variable?
For a function local, it is external. Access: It''s accessible to the function (unless of course, you return it).
For a class, it is external. Access: Standard access specifiers apply (public, protected, private).
static
can also specify internal linkage, depending on where it''s declared (file/namespace).
This whole static keyword is downright confusing
It has too many purposes in C++.
can someone clarify the different uses for it English and also tell me when to initialize a static class member?
It''s automatically initialized before main
if it''s loaded and has a constructor. That might sound like a good thing, but initialization order is largely beyond your control, so complex initialization becomes very difficult to maintain, and you want to minimize this -- if you must have a static, then function local scales much better across libraries and projects. As far as data with static storage duration, you should try to minimize this design, particularly if mutable (global variables). Initialization ''time'' also varies for a number of reasons -- the loader and kernel have some tricks to minimize memory footprints and defer initialization, depending on the data in question.
La palabra clave static
es una que tiene varios significados en C ++ que encuentro muy confuso y nunca puedo pensar cómo debería funcionar realmente.
Por lo que entiendo, hay una duración de almacenamiento static
, lo que significa que dura toda la vida del programa en el caso de un global, pero cuando se habla de un local, significa que no se inicializa por defecto.
El estándar C ++ dice esto para los miembros de datos de clase con la palabra clave static
:
3.7.1 Duración del almacenamiento estático [basic.stc.static]
3 La palabra clave static se puede usar para declarar una variable local con duración de almacenamiento estática.
4 La palabra clave static aplicada a un miembro de datos de clase en una definición de clase proporciona al miembro de datos una duración de almacenamiento estática.
¿Qué significa con la variable local ? ¿Es eso una función variable local? Porque también existe eso cuando declara una función local como static
que solo se inicializa una vez, la primera vez que ingresa a esta función.
También solo habla de la duración del almacenamiento con respecto a los miembros de la clase, ¿qué pasa si no es específico de la instancia, eso también es una propiedad de no static
? ¿O es esa duración de almacenamiento?
Ahora, ¿qué pasa con el caso con el alcance static
y de archivo? ¿Se considera que todas las variables globales tienen una duración de almacenamiento estática por defecto? Lo siguiente (de la sección 3.7.1) parece indicarlo:
1 Todas las variables que no tienen una duración de almacenamiento dinámica, no tienen duración de almacenamiento de subprocesos y no son locales tienen duración de almacenamiento estático. El almacenamiento para estas entidades durará por la duración del programa (3.6.2, 3.6.3)
¿Cómo se relaciona static
con el enlace de una variable?
Toda esta palabra clave static
es francamente confusa, ¿alguien puede aclarar los diferentes usos del inglés y también decirme cuándo inicializar un miembro static
clase?
Variables:
Existen variables static
para la "vida útil" de la unidad de traducción en la que está definida , y:
- Si está en un ámbito de espacio de nombres (es decir, fuera de las funciones y clases), no se puede acceder desde ninguna otra unidad de traducción. Esto se conoce como "vinculación interna". (No hagas esto en encabezados, es solo una idea terrible, terminas con una variable separada en cada unidad de traducción, lo cual es bastante confuso)
- Si es una variable en una función , no se puede acceder desde fuera de la función, al igual que cualquier otra variable local. (este es el local que mencionaron)
- los miembros de la clase no tienen un alcance restringido debido a la
static
, pero se pueden abordar desde la clase, así como una instancia (comostd::string::npos
). [Nota: puede declarar miembros estáticos en una clase, pero normalmente deberían definirse en una unidad de traducción (archivo cpp), y como tal, solo hay uno por clase]
Antes de que se ejecute cualquier función en una unidad de traducción (posiblemente después de que la ejecución main
comience), las variables con duración de almacenamiento estática en esa unidad de traducción serán "constante inicializadas" (para constexpr
donde sea posible, o cero de lo contrario), y luego los no locales son "Inicializado dinámicamente" correctamente en el orden en que se definen en la unidad de traducción (para cosas como std::string="HI";
que no son constexpr
). Finalmente, las estadísticas estáticas locales se inicializan la primera vez que la ejecución "alcanza" la línea donde están declaradas. Todos son destruidos en el orden inverso de inicialización.
La forma más sencilla de hacer todo esto bien es hacer que todas las variables estáticas que no se inicialicen en la función constexpr
estáticas, lo que asegura que todos sus statics / globales se inicialicen correctamente cuando intente usarlos sin importar qué, evitando así la estática fiasco de orden de inicialización .
T& get_global() {
static T global = initial_value();
return global;
}
Tenga cuidado, porque cuando la especificación dice que las variables de espacio de nombres de nombres tienen "duración de almacenamiento estático" de forma predeterminada, significan el bit de "duración de la unidad de traducción", pero eso no significa que no se pueda acceder fuera del archivo.
Funciones
Significativamente más sencillo, static
se usa a menudo como una función miembro de la clase, y muy raramente se utiliza para una función autónoma.
Una función miembro estática difiere de una función miembro regular en que se puede invocar sin una instancia de una clase, y como no tiene instancia, no puede acceder a los miembros no estáticos de la clase. Las variables estáticas son útiles cuando se quiere tener una función para una clase que definitivamente no se refiere a ningún miembro de instancia, o para administrar variables de miembros static
.
struct A {
A() {++A_count;}
A(const A&) {++A_count;}
A(A&&) {++A_count;}
~A() {--A_count;}
static int get_count() {return A_count;}
private:
static int A_count;
}
int main() {
A var;
int c0 = var.get_count(); //some compilers give a warning, but it''s ok.
int c1 = A::get_count(); //normal way
}
Una función libre static
significa que la función no será referida por ninguna otra unidad de traducción, y por lo tanto el enlazador puede ignorarla por completo. Esto tiene un pequeño número de propósitos:
- Se puede usar en un archivo cpp para garantizar que la función nunca se use desde ningún otro archivo.
- Se puede poner en un encabezado y cada archivo tendrá su propia copia de la función. No es útil, ya que en línea hace más o menos lo mismo.
- Acelera el tiempo de enlace al reducir el trabajo
- Puede poner una función con el mismo nombre en cada TU, y todos pueden hacer cosas diferentes. Por ejemplo, podría colocar un
static void log(const char*) {}
en cada archivo cpp, y cada uno podría iniciar sesión de una manera diferente.
Cuando declaras una variable static
en el alcance del archivo, esa variable solo está disponible en ese archivo en particular (técnicamente, la * unidad de traducción, pero no lo compliquemos demasiado). Por ejemplo:
a.cpp
static int x = 7;
void printax()
{
cout << "from a.cpp: x=" << x << endl;
}
b.cpp
static int x = 9;
void printbx()
{
cout << "from b.cpp: x=" << x << endl;
}
main.cpp:
int main(int, char **)
{
printax(); // Will print 7
printbx(); // Will print 9
return 0;
}
Para una variable local , static
significa que la variable se inicializará en cero y retendrá su valor entre las llamadas:
unsigned int powersoftwo()
{
static unsigned lastpow;
if(lastpow == 0)
lastpow = 1;
else
lastpow *= 2;
return lastpow;
}
int main(int, char **)
{
for(int i = 0; i != 10; i++)
cout << "2^" << i << " = " << powersoftwo() << endl;
}
Para las variables de clase , significa que solo hay una instancia única de esa variable que se comparte entre todos los miembros de esa clase. Según los permisos, se puede acceder a la variable desde fuera de la clase utilizando su nombre completo.
class Test
{
private:
static char *xxx;
public:
static int yyy;
public:
Test()
{
cout << this << "The static class variable xxx is at address "
<< static_cast<void *>(xxx) << endl;
cout << this << "The static class variable yyy is at address "
<< static_cast<void *>(&y) << endl;
}
};
// Necessary for static class variables.
char *Test::xxx = "I''m Triple X!";
int Test::yyy = 0;
int main(int, char **)
{
Test t1;
Test t2;
Test::yyy = 666;
Test t3;
};
Marcar una función que no es de clase como static
hace que la función solo sea accesible desde ese archivo y que no sea accesible desde otros archivos.
a.cpp
static void printfilename()
{ // this is the printfilename from a.cpp -
// it can''t be accessed from any other file
cout << "this is a.cpp" << endl;
}
b.cpp
static void printfilename()
{ // this is the printfilename from b.cpp -
// it can''t be accessed from any other file
cout << "this is b.cpp" << endl;
}
Para las funciones de miembro de clase, marcarlas como static
significa que la función no necesita ser llamada en una instancia particular de un objeto (es decir, no tiene un puntero).
class Test
{
private:
static int count;
public:
static int GetTestCount()
{
return count;
};
Test()
{
cout << this << "Created an instance of Test" << endl;
count++;
}
~Test()
{
cout << this << "Destroyed an instance of Test" << endl;
count--;
}
};
int Test::count = 0;
int main(int, char **)
{
Test *arr[10] = { NULL };
for(int i = 0; i != 10; i++)
arr[i] = new Test();
cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;
// now, delete them all except the first and last!
for(int i = 1; i != 9; i++)
delete arr[i];
cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;
delete arr[0];
cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;
delete arr[9];
cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;
return 0;
}
En realidad es bastante simple. Si declara una variable como estática en el alcance de una función, su valor se conservará entre llamadas sucesivas a esa función. Asi que:
int myFun()
{
static int i=5;
i++;
return i;
}
int main()
{
printf("%d", myFun());
printf("%d", myFun());
printf("%d", myFun());
}
mostrará 678
lugar de 666
, ya que recuerda el valor incrementado.
En cuanto a los miembros estáticos, conservan su valor en todas las instancias de la clase. Entonces el siguiente código:
struct A
{
static int a;
};
int main()
{
A first;
A second;
first.a = 3;
second.a = 4;
printf("%d", first.a);
}
imprimirá 4, porque first.a y second.a son esencialmente la misma variable. En cuanto a la inicialización, vea esta pregunta.
La duración del almacenamiento estático significa que la variable reside en el mismo lugar en la memoria a lo largo de la vida útil del programa.
El enlace es ortogonal a esto.
Creo que esta es la distinción más importante que puedes hacer. Comprender esto y el resto, así como recordarlo, debería ser fácil (no dirigirse directamente a @Tony, sino a quien pueda leer esto en el futuro).
La palabra clave static
se puede usar para designar enlaces internos y almacenamiento estático, pero en esencia, estos son diferentes.
¿Qué significa con la variable local? ¿Es eso una función variable local?
Sí. Independientemente de cuándo se inicializa la variable (en la primera llamada a la función y cuando la ruta de ejecución alcanza el punto de declaración), residirá en el mismo lugar en la memoria durante la vida del programa. En este caso, static
le da almacenamiento estático.
Ahora, ¿qué pasa con el caso con el alcance estático y de archivo? ¿Se considera que todas las variables globales tienen una duración de almacenamiento estática por defecto?
Sí, todos los globales tienen por definición duración de almacenamiento estático (ahora que hemos aclarado lo que eso significa). Pero las variables con ámbito de espacios de nombres no se declaran con static
, porque eso les daría un vínculo interno, por lo que una variable por unidad de traducción.
¿Cómo se relaciona estática con el enlace de una variable?
Proporciona una vinculación interna de variables con ámbito de espacio de nombres. Le da a los miembros y las variables locales una duración de almacenamiento estática.
Ampliemos todo esto:
//
static int x; //internal linkage
//non-static storage - each translation unit will have its own copy of x
//NOT A TRUE GLOBAL!
int y; //static storage duration (can be used with extern)
//actual global
//external linkage
struct X
{
static int x; //static storage duration - shared between classes
};
void foo()
{
static int x; //static storage duration - shared between calls
}
Esta palabra clave estática es francamente confusa
Definitivamente, a menos que estés familiarizado con esto. :) Tratando de evitar agregar nuevas palabras clave al idioma, el comité reutilizó este, IMO, en este sentido: confusión. Se usa para significar cosas diferentes (podría decir, probablemente oponer cosas).
Las variables estáticas se comparten entre cada instancia de una clase, en lugar de que cada clase tenga su propia variable.
class MyClass
{
public:
int myVar;
static int myStaticVar;
};
//Static member variables must be initialized. Unless you''re using C++11, or it''s an integer type,
//they have to be defined and initialized outside of the class like this:
MyClass::myStaticVar = 0;
MyClass classA;
MyClass classB;
Cada instancia de ''MyClass'' tiene su propia ''myVar'', pero comparte la misma ''myStaticVar''. De hecho, ni siquiera necesita una instancia de MyClass para acceder a ''myStaticVar'', y puede acceder a ella fuera de la clase de esta manera:
MyClass::myStaticVar //Assuming it''s publicly accessible.
Cuando se usa dentro de una función como una variable local (y no como una variable de miembro de clase), la palabra clave static hace algo diferente. Le permite crear una variable persistente, sin dar un alcance global.
int myFunc()
{
int myVar = 0; //Each time the code reaches here, a new variable called ''myVar'' is initialized.
myVar++;
//Given the above code, this will *always* print ''1''.
std::cout << myVar << std::endl;
//The first time the code reaches here, ''myStaticVar'' is initialized. But ONLY the first time.
static int myStaticVar = 0;
//Each time the code reaches here, myStaticVar is incremented.
myStaticVar++;
//This will print a continuously incrementing number,
//each time the function is called. ''1'', ''2'', ''3'', etc...
std::cout << myStaticVar << std::endl;
}
Es una variable global en términos de persistencia ... pero sin ser global en alcance / accesibilidad.
También puede tener funciones miembro estáticas. Las funciones estáticas son básicamente funciones que no son miembros, pero dentro del espacio de nombres del nombre de clase, y con acceso privado a los miembros de la clase.
class MyClass
{
public:
int Func()
{
//...do something...
}
static int StaticFunc()
{
//...do something...
}
};
int main()
{
MyClass myClassA;
myClassA.Func(); //Calls ''Func''.
myClassA.StaticFunc(); //Calls ''StaticFunc''.
MyClass::StaticFunc(); //Calls ''StaticFunc''.
MyClass::Func(); //Error: You can''t call a non-static member-function without a class instance!
return 0;
}
Cuando llama a una función de miembro, hay un parámetro oculto llamado ''this'', que es un puntero a la instancia de la clase que llama a la función. Las funciones de miembros estáticos no tienen ese parámetro oculto ... se pueden llamar sin una instancia de clase, pero tampoco pueden acceder a variables miembro no estáticas de una clase, porque no tienen un puntero ''this'' con el que trabajar. No están siendo llamados en ninguna instancia de clase específica.
No soy un programador de C, así que no puedo darle información sobre los usos de estática en un programa de C correctamente, pero cuando se trata de programación orientada a objetos, static básicamente declara una variable, o una función o una clase para ser el mismo durante toda la vida del programa. Toma por ejemplo.
class A
{
public:
A();
~A();
void somePublicMethod();
private:
void somePrivateMethod();
};
Cuando instancias esta clase en tu Main, haces algo como esto.
int main()
{
A a1;
//do something on a1
A a2;
//do something on a2
}
Estas dos instancias de clase son completamente diferentes entre sí y operan independientemente una de la otra. Pero si recrearas la clase A como esta.
class A
{
public:
A();
~A();
void somePublicMethod();
static int x;
private:
void somePrivateMethod();
};
Vamos a volver a la principal de nuevo.
int main()
{
A a1;
a1.x = 1;
//do something on a1
A a2;
a2.x++;
//do something on a2
}
Entonces a1 y a2 compartirían la misma copia de int x, por lo que cualquier operación en x en a1 influiría directamente en las operaciones de x en a2. Entonces, si tuviera que hacer esto
int main()
{
A a1;
a1.x = 1;
//do something on a1
cout << a1.x << endl; //this would be 1
A a2;
a2.x++;
cout << a2.x << endl; //this would be 2
//do something on a2
}
Ambas instancias de la clase A comparten variables y funciones estáticas. Espero que esto responda a su pregunta. Mi conocimiento limitado de C me permite decir que definir una función o variable como estática significa que solo es visible para el archivo que la función o variable se define como estática. Pero esto sería mejor para un tipo C y no para mí. C ++ permite las formas C y C ++ de declarar sus variables como estáticas porque es completamente compatible con C.
Para aclarar la pregunta, preferiría categorizar el uso de la palabra clave "estática" en tres formas diferentes:
(UN). variables
(SEGUNDO). funciones
(DO). variables miembro / funciones de las clases
la explicación sigue a continuación para cada uno de los subtítulos:
(A) palabra clave ''estática'' para las variables
Este puede ser un poco complicado, sin embargo, si se explica y se entiende correctamente, es bastante sencillo.
Para explicar esto, primero es realmente útil conocer el alcance, la duración y el vínculo de las variables, sin las cuales las cosas siempre son difíciles de ver a través del turbio concepto de palabra clave staic
1. Ámbito : determina en qué parte del archivo, la variable es accesible. Puede ser de dos tipos: (i) Alcance local o de bloque . (ii) Alcance global
2. Duración : determina cuándo se crea y se destruye una variable. De nuevo, es de dos tipos: (i) Duración automática (para variables que tienen alcance Local o Bloque). (ii) Duración estática (para variables con alcance global).
3. Enlace : determina si se puede acceder (o vincular) a una variable en otro archivo. Nuevamente (y afortunadamente) es de dos tipos: (i) Enlace interno (para variables que tienen Alcance de bloque y Alcance global) (ii) Enlace externo (para variables que tienen solo alcance global)
Vamos a referirnos a un ejemplo a continuación para una mejor comprensión:
//main file
#include <iostream>
int global_var1; //has global scope
const global_var2(1.618); //has global scope
int main()
{
//these variables are local to the block main.
//they have automatic duration, i.e, they are created when the main() is
// executed and destroyed, when main goes out of scope
int local_var1(23);
const double local_var2(3.14);
{
/* this is yet another block, all variables declared within this block are
have local scope limited within this block. */
// all variables declared within this block too have automatic duration, i.e,
/*they are created at the point of definition within this block,
and destroyed as soon as this block ends */
char block_char1;
int local_var1(32) //NOTE: this has been re-declared within the block,
//it shadows the local_var1 declared outside
std::cout << local_var1 <<"/n"; //prints 32
}//end of block
//local_var1 declared inside goes out of scope
std::cout << local_var1 << "/n"; //prints 23
global_var1 = 29; //global_var1 has been declared outside main (global scope)
std::cout << global_var1 << "/n"; //prints 29
std::cout << global_var2 << "/n"; //prints 1.618
return 0;
} //local_var1, local_var2 go out of scope as main ends
//global_var1, global_var2 go out of scope as the program terminates
//(in this case program ends with end of main, so both local and global
//variable go out of scope together
(Los lectores deben ser pacientes: esta es la base necesaria para comprender el uso de palabras clave "estáticas" para varios casos en variables)
Ahora viene el concepto de Linkage. Cuando una variable global definida en un archivo está destinada a ser utilizada en otro archivo, la vinculación de la variable juega un papel importante.
La vinculación de las variables globales está especificada por las palabras clave: (i) estático , y (ii) externo
(Ahora tienes la explicación ;-))
la palabra clave static se puede aplicar a variables con alcance local y global, y en ambos casos, significan cosas diferentes. Primero explicaré el uso de la palabra clave ''estática'' en variables con alcance global (donde también aclaro el uso de la palabra clave ''extern'') y luego en el caso de las que tienen alcance local.
1. Palabra clave estática para variables con alcance global
Las variables globales tienen una duración estática, lo que significa que no salen del alcance cuando un bloque de código en particular (por ejemplo main ()) en el que se usa finaliza. Dependiendo de la vinculación, se puede acceder solo dentro del mismo archivo donde se declaran (para la variable global estática) o fuera del archivo, incluso fuera del archivo en el que se declaran (variables globales de tipo extern)
En el caso de una variable global que tenga un especificador externo, y si se está accediendo a esta variable fuera del archivo en el que se ha inicializado, debe declararse en el archivo donde se está utilizando, al igual que una función debe ser reenviada declarado si su definición está en un archivo diferente de donde se está utilizando.
Por el contrario, si la variable global tiene una palabra clave estática, no se puede usar en un archivo fuera de la cual se ha declarado.
(ver ejemplo a continuación para aclaración)
p.ej:
//main2.cpp
static int global_var3 = 23; /*static global variable, cannot be
accessed in anyother file */
extern double global_var4 = 71; /*can be accessed outside this file linked to main2.cpp */
int main() { return 0; }
main3.cpp
//main3.cpp
#include <iostream>
int main()
{
extern int gloabl_var4; /*this variable refers to the gloabal_var4
defined in the main2.cpp file */
std::cout << global_var4 << "/n"; //prints 71;
return 0;
}
ahora cualquier variable en c ++ puede ser const o no const y para cada ''const-ness'' obtenemos dos casos de vinculación c ++ por defecto, en caso de que no se especifique ninguno:
(i) Si una variable global no es const, su vinculación es externa por defecto , es decir, se puede acceder a la variable global non-const en otro archivo .cpp mediante declaración forward usando la palabra clave extern (en otras palabras, no const global las variables tienen un enlace externo (con duración estática del curso)). También el uso de la palabra clave extern en el archivo original donde se ha definido es redundante. En este caso, para hacer que una variable global no const sea inaccesible a un archivo externo, utilice el especificador ''static'' antes del tipo de la variable .
(ii) Si una variable global es const, su enlace es estático por defecto , es decir, no se puede acceder a una variable const global en un archivo distinto de donde está definido (en otras palabras, las variables globales const tienen un enlace interno (con duración estática) por supuesto)). También es redundante el uso de la palabra clave static para evitar que una variable global const sea accedida en otro archivo. Aquí, para hacer que una variable global const tenga un enlace externo, use el especificador ''extern'' antes del tipo de la variable
Aquí hay un resumen de las variables de alcance global con varios enlaces
//globalVariables1.cpp
// defining uninitialized vairbles
int globalVar1; // uninitialized global variable with external linkage
static int globalVar2; // uninitialized global variable with internal linkage
const int globalVar3; // error, since const variables must be initialized upon declaration
const int globalVar4 = 23; //correct, but with static linkage (cannot be accessed outside the file where it has been declared*/
extern const double globalVar5 = 1.57; //this const variable ca be accessed outside the file where it has been declared
A continuación, investigamos cómo se comportan las variables globales anteriores cuando se accede a ellas en un archivo diferente.
//using_globalVariables1.cpp (eg for the usage of global variables above)
// Forward declaration via extern keyword:
extern int globalVar1; // correct since globalVar1 is not a const or static
extern int globalVar2; //incorrect since globalVar2 has internal linkage
extern const int globalVar4; /* incorrect since globalVar4 has no extern
specifier, limited to internal linkage by
default (static specifier for const variables) */
extern const double globalVar5; /*correct since in the previous file, it
has extern specifier, no need to initialize the
const variable here, since it has already been
legitimately defined perviously */
2. Palabra clave estática para variables con alcance local
Anteriormente, mencioné que las variables con alcance local tienen una duración automática, es decir, que llegan a existir cuando se ingresa el bloque (ya sea un bloque normal, ya sea un bloque de funciones) y dejan de existir cuando el bloque termina, para abreviar, las variables con alcance local tienen duración automática
Si el especificador estático se aplica a una variable local dentro de un bloque, cambia la duración de la variable de automática a estática
Echemos un vistazo a un ejemplo.
//localVarDemo.cpp
#include <iostream>
int localNextID()
{
int tempID = 1; //tempID created here
return tempID++; //copy of tempID returned and tempID incremented to 2
} //tempID destroyed here, hence value of tempID lost
int newNextID()
{
static int newID = 0;//newID has static duration, with internal linkage
return newID++; //copy of newID returned and newID incremented by 1
} //newID doesn''t get destroyed here :-)
int main()
{
int employeeID1 = nextID(); //employeeID1 = 1
int employeeID2 = nextID(); // employeeID2 = 1 again (not desired)
int employeeID3 = newNextID(); //employeeID3 = 0;
int employeeID4 = newNextID(); //employeeID4 = 1;
int employeeID5 = newNextID(); //employeeID5 = 2;
return 0;
}
esto concluye mi explicación para la palabra clave estática aplicada a las variables. pheww !!!
B. Palabra clave "estática" utilizada para funciones
en términos de funciones, la palabra clave estática tiene un significado directo. Aquí, se refiere a la vinculación de la función. Normalmente, todas las funciones declaradas dentro de un archivo cpp tienen una vinculación externa por defecto, es decir, una función definida en un archivo puede usarse en otro archivo cpp mediante la declaración directa.
utilizar una palabra clave estática antes de que la declaración de función limite su vinculación a interna , es decir, una función estática no se puede usar dentro de un archivo fuera de su definición.
C. Palabra clave Staitc utilizada para las variables miembro y las funciones de las clases
1. palabra clave ''estática'' para las variables miembro de las clases
Comienzo directamente con un ejemplo aquí
#include <iostream>
class DesignNumber
{
private:
static int m_designNum; //design number
int m_iteration; // number of iterations performed for the design
public:
DesignNumber() { } //default constructor
int getItrNum() //get the iteration number of design
{
m_iteration = m_designNum++;
return m_iteration;
}
static int m_anyVariable; //public static variable
};
int DesignNumber::m_designNum = 0; // starting with design id = 0
// note : no need of static keyword here
//causes compiler error if static keyword used
int DesignNumber::m_anyNumber = 99; /* initialization of inclass public
static member */
enter code here
int main()
{
DesignNumber firstDesign, secondDesign, thirdDesign;
std::cout << firstDesign.getItrNum() << "/n"; //prints 0
std::cout << secondDesign.getItrNum() << "/n"; //prints 1
std::cout << thirdDesign.getItrNum() << "/n"; //prints 2
std::cout << DesignNumber::m_anyNumber++ << "/n"; /* no object
associated with m_anyNumber */
std::cout << DesignNumber::m_anyNumber++ << "/n"; //prints 100
std::cout << DesignNumber::m_anyNumber++ << "/n"; //prints 101
return 0;
}
En este ejemplo, la variable estática m_designNum conserva su valor y esta única variable de miembro privada (porque es estática) se comparte b / w con todas las variables del tipo de objeto DesignNumber
Al igual que otras variables miembro, las variables miembro estáticas de una clase no están asociadas a ningún objeto de clase, lo que se demuestra mediante la impresión de cualquier número en la función principal.
variables de miembros estáticos const vs non-const en clase
(i) variables de miembro estático de clase non-const En el ejemplo anterior, los miembros estáticos (tanto públicos como privados) no eran constantes. La norma ISO prohíbe que los miembros estáticos no const sean inicializados en la clase. Por lo tanto, como en el ejemplo anterior, deben ser iniciados después de la definición de la clase, con la advertencia de que la palabra clave estática debe ser omitida.
(ii) las variables de miembro const-static de clase esto es sencillo y va con la convención de otra inicialización de variable de miembro const, es decir, las variables de miembro estáticas const de una clase se pueden inicializar en el punto de declaración y se pueden inicializar al final de la declaración de clase con una advertencia de que la palabra clave const debe agregarse al miembro estático cuando se inicializa después de la definición de la clase.
Sin embargo, recomiendo inicializar las variables de miembro estáticas const en el punto de declaración. Esto va con la convención estándar de C ++ y hace que el código se vea más limpio
para obtener más ejemplos sobre variables miembro estáticas en una clase, busque el siguiente enlace en learncpp.com http://www.learncpp.com/cpp-tutorial/811-static-member-variables/
2. palabra clave "estática" para la función miembro de las clases
Al igual que las variables miembro de las clases pueden ser estáticas, también pueden las funciones miembro de las clases. Las funciones de miembro normales de las clases siempre están asociadas a un objeto del tipo de clase. Por el contrario, las funciones miembro estáticas de una clase no están asociadas a ningún objeto de la clase, es decir, no tienen * este puntero.
En segundo lugar, dado que las funciones miembro estáticas de la clase no tienen * este puntero, pueden llamarse utilizando el nombre de clase y el operador de resolución de alcance en la función principal (ClassName :: functionName ();)
En tercer lugar, las funciones miembro estáticas de una clase solo pueden acceder a variables miembro estáticas de una clase, ya que las variables miembro no estáticas de una clase deben pertenecer a un objeto de clase.
para obtener más ejemplos sobre funciones miembro estáticas en una clase, busque el siguiente enlace desde learncpp.com
http://www.learncpp.com/cpp-tutorial/812-static-member-functions/
Static Object: We can define class members static using static keyword. When we declare a member of a class as static it means no matter how many objects of the class are created, there is only one copy of the static member.
A static member is shared by all objects of the class. All static data is initialized to zero when the first object is created, if no other initialization is present. We can''t put it in the class definition but it can be initialized outside the class as done in the following example by redeclaring the static variable, using the scope resolution operator :: to identify which class it belongs to.
Let us try the following example to understand the concept of static data members:
#include <iostream>
using namespace std;
class Box
{
public:
static int objectCount;
// Constructor definition
Box(double l=2.0, double b=2.0, double h=2.0)
{
cout <<"Constructor called." << endl;
length = l;
breadth = b;
height = h;
// Increase every time object is created
objectCount++;
}
double Volume()
{
return length * breadth * height;
}
private:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};
// Initialize static member of class Box
int Box::objectCount = 0;
int main(void)
{
Box Box1(3.3, 1.2, 1.5); // Declare box1
Box Box2(8.5, 6.0, 2.0); // Declare box2
// Print total number of objects.
cout << "Total objects: " << Box::objectCount << endl;
return 0;
}
When the above code is compiled and executed, it produces the following result:
Constructor called.
Constructor called.
Total objects: 2
Static Function Members: By declaring a function member as static, you make it independent of any particular object of the class. A static member function can be called even if no objects of the class exist and the static functions are accessed using only the class name and the scope resolution operator ::.
A static member function can only access static data member, other static member functions and any other functions from outside the class.
Static member functions have a class scope and they do not have access to the this pointer of the class. You could use a static member function to determine whether some objects of the class have been created or not.
Let us try the following example to understand the concept of static function members:
#include <iostream>
using namespace std;
class Box
{
public:
static int objectCount;
// Constructor definition
Box(double l=2.0, double b=2.0, double h=2.0)
{
cout <<"Constructor called." << endl;
length = l;
breadth = b;
height = h;
// Increase every time object is created
objectCount++;
}
double Volume()
{
return length * breadth * height;
}
static int getCount()
{
return objectCount;
}
private:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};
// Initialize static member of class Box
int Box::objectCount = 0;
int main(void)
{
// Print total number of objects before creating object.
cout << "Inital Stage Count: " << Box::getCount() << endl;
Box Box1(3.3, 1.2, 1.5); // Declare box1
Box Box2(8.5, 6.0, 2.0); // Declare box2
// Print total number of objects after creating object.
cout << "Final Stage Count: " << Box::getCount() << endl;
return 0;
}
When the above code is compiled and executed, it produces the following result:
Inital Stage Count: 0
Constructor called.
Constructor called.
Final Stage Count: 2