elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Guía rápida para descarga de herramientas gratuitas de seguridad y desinfección


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Variables estaticas...
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] 2 Ir Abajo Respuesta Imprimir
Autor Tema: Variables estaticas...  (Leído 1,946 veces)
digimikeh

Desconectado Desconectado

Mensajes: 184


Ver Perfil
Variables estaticas...
« en: 29 Agosto 2019, 05:16 am »

Muy buenas..

Tengo un mal concepto quizá de lo que son las variables estáticas, yo las imagino algo asi como un contenedor que se crea automáticamente al iniciarse un programa, vive durante todo el programa y luego se cierra una vez que el programa termina... como un bolso de viaje que tomas al iniciar el viaje y te deshaces de él cuando regresas a casa... asi es como yo las veo.. (por favor, indicarme si estoy mal).

El siguiente código no esta reflejando esto:

main.cpp
Código
  1. #include <iostream>
  2. #include "Archivo2.h"
  3. #include "Archivo1.h"
  4.  
  5. int main() {
  6. x::num = 10;
  7. std::cout << "Desde main -> " << x::num << "Memoria : " << &x::num;
  8. std::cout << std::endl;
  9. Archivo1 a;
  10. a.printVal();
  11. return 0;
  12. }
  13.  


Archivo1.h
Código
  1. #pragma once
  2. struct Archivo1{
  3. void printVal() const;
  4. };
  5.  

Archivo1.cpp
Código
  1. #include "Archivo2.h"
  2. #include "Archivo1.h"
  3. #include <iostream>
  4.  
  5. void Archivo1::printVal() const {
  6. std::cout << "Desde Archivo1 -> " << x::num << "Memoria : " << &x::num;
  7.  
  8. }
  9.  

Archivo2.h
Código
  1. namespace x{
  2.     static int num;
  3. }
  4.  


La salida de consola "Desde Main ->" imprime 10
La salida de consola "Desde Archivo1 ->" imprime 0...

Creí que estaba imprimiendo el mismo elemento, pero no, cuando le agregue que imprimiera la dirección de memoria, me encontré con la sorpresa de que ambas estan imprimiendo direcciones diferentes....

En qué momento se creó una nueva instancia de la variable estática y como puedo solucionar este dilema?.. mi intención es escribir e imprimir en una sola variable x::num

Saludos_!



« Última modificación: 29 Agosto 2019, 05:24 am por digimikeh » En línea

Dungeons & dragons;
dragons.Attack();
@XSStringManolo
<svg/onload=alert()>
Colaborador
***
Desconectado Desconectado

Mensajes: 2.280


Turn off the red ligth


Ver Perfil WWW
Re: Variables estaticas...
« Respuesta #1 en: 29 Agosto 2019, 10:15 am »

Prueba añadiendo external antes de static int num; en el archivo2.h

Parece un problema de linkado, que te crea otra static nueva en el .cpp.


En línea

Loretz

Desconectado Desconectado

Mensajes: 112


Ver Perfil
Re: Variables estaticas...
« Respuesta #2 en: 29 Agosto 2019, 15:04 pm »

El contenido de los archivos header (*.h) se copia y pega en cada lugar donde el compilador encuentra su #include. En tu caso se está escribiendo
Código:
namespace x {
    inline static int num;
}
en cada lugar donde se encuentre
Código:
#include "Archivo2.h"

Así, tendrás una x::num en cada cpp, una inicializada a 10 y la otra a 0 ("zero initialized", como exige el estándar).

Pero, además, las variables static tiene un alcance ("scope") a nivel de unidad de traducción (básicamente cada cosa que vaya a compilarse como *.obj), así que es natural que tengas una nueva x::num en cada cpp, esa es su naturaleza. Si quieres que sea la misma, no debería ser static.
En línea

digimikeh

Desconectado Desconectado

Mensajes: 184


Ver Perfil
Re: Variables estaticas...
« Respuesta #3 en: 29 Agosto 2019, 17:11 pm »

Gracias por las respuestas...


Manolo, te refieres a extern ?

Loretz, entonces las variables estáticas se instancian mediante la inclusión de archivos y no de tipos ... es asi?... por ejemplo, lo que has dicho: estoy incluyendo el mismo archivo en dos archivos independientes, serian dos instancias separadas de la variable estatica... sin embargo, si instancio dos tipos Archivo2 en un mismo archivo, ahi si estaria utilizando la misma variable estatica para ambos casos.... ?

Suponiendo que tengo una clase llamada Alpha, que tiene un campo publico estático llamado myName, si yo instancio esta clase mas de una vez dentro del mismo archivo fuente, todas las instancias de la clase estarían accediendo a la misma dirección de memoria de myName...

Es al menos lo que veo aqui en este ejemplo:
https://www.tutorialspoint.com/cplusplus/cpp_static_members.htm

Saludos..
En línea

Dungeons & dragons;
dragons.Attack();
Loretz

Desconectado Desconectado

Mensajes: 112


Ver Perfil
Re: Variables estaticas...
« Respuesta #4 en: 29 Agosto 2019, 21:08 pm »

Citar
Loretz, entonces las variables estáticas se instancian mediante la inclusión de archivos y no de tipos ... es asi?...
No no. Lo que quise decir es que cualquier cosa que escribas en un archivo.h se va a "pegar" en el archivo.cpp justo ahí donde hayas puesto "#include archivo.h". Es como si el compilador hiciera un "buscar y reemplazar", y ahí donde encuentre "#include archivo.h" lo va a reemplazar por el contenido de ese archivo. Sea lo que sea que haya escrito en ese .h.

Citar
... sin embargo, si instancio dos tipos Archivo2 en un mismo archivo, ahi si estaria utilizando la misma variable estatica para ambos casos.... ?
Esta parte no la entiendo. Si a lo que te refieres es a si escribes dos veces el mismo #include en un mismo *.cpp, si has puesto la guarda "pragma once" (o las directivas #ifndef ... #define ... #endif) el compilador ignorará la segunda inclusión; y si no la has puesto, tendrás un error al compilar, porque estarías violando la regla "ODR" (one definition rule". (Puedes consultar la definición en https://en.cppreference.com/w/cpp/language/definition)

Citar
Suponiendo que tengo una clase llamada Alpha, que tiene un campo publico estático llamado myName ...
Aquí sí, es como dices y se muestra en el ejemplo que mencionas. Pero en este caso ya no sería una variable static sino un dato miembro declarado static, que es otra cosa. Siguen reglas distintas.
En línea

digimikeh

Desconectado Desconectado

Mensajes: 184


Ver Perfil
Re: Variables estaticas...
« Respuesta #5 en: 29 Agosto 2019, 22:16 pm »

La cita 2 está relacionada con la 3... es que no me supe explicar correctamente...lo siento  :rolleyes:

Entonces la solución que tengo es lo que planteaba Manolo std::string con la palabra extern de lo contrario sería usar objetos persistentes pero no creo que esto sea muy elegante....


En línea

Dungeons & dragons;
dragons.Attack();
Loretz

Desconectado Desconectado

Mensajes: 112


Ver Perfil
Re: Variables estaticas...
« Respuesta #6 en: 29 Agosto 2019, 22:32 pm »

Si lo que necesitas es una misma variable accesible desde distintos cpp, deberías declararla "extern", pero ya no sería posible que fuera "static", porque en este sentido son contradictorias.

Por ejemplo:
en Archivo1.h

Código:
#pragma once

struct Archivo1 {
    void printVal() const;
};

en Archivo2.h
Código:
#pragma once

namespace x {
    extern int num;  // no puede ser static
}

en Archivo1.cpp
Código:
#include "Archivo1.h"
#include "Archivo2.h"
#include <iostream>

void Archivo1::printVal() const {
    std::cout << "Desde Archivo1 -> " << x::num << " Memoria : " << &x::num << '\n';
}

en main.cpp
Código:
#include <iostream>
#include "Archivo2.h"
#include "Archivo1.h"

int x::num = 10; // definida aquí o en cualquier otro cpp

int main() {
    std::cout << "Desde main -> " << x::num << " Memoria : " << &x::num << '\n';
    Archivo1 a;
    a.printVal();
    return 0;
}

Salida:
Código:
Desde main -> 10 Memoria : 00FBC000  // mismo valor, misma dirección de memoria.
Desde Archivo1 -> 10 Memoria : 00FBC000

Al declararla como "extern" le dices al compilador que está definida en algún otro lado, y es conocida en todo el programa, en cualquier cpp donde se incluya su declaración (por medio de #include Archivo2.h).

Esto mismo también puede hacerse (a partir de C++17) con
Archivo2.h
Código:
#pragma once

namespace x {
    inline int num = 10;
}

Y ya no necesitas definir x::num en ninguno de los cpp.



En línea

digimikeh

Desconectado Desconectado

Mensajes: 184


Ver Perfil
Re: Variables estaticas...
« Respuesta #7 en: 30 Agosto 2019, 17:22 pm »

De acuerdo, me parece lógico...

Bueno, en este caso he querido usar un int como ejemplo para describir mi duda, en el programa que estoy intentando hacer, lo que quiero usar como variable global es un tipo propio que se inicializa con un constructor.  En el constructor de ese tipo propio (que se llama Sesion) se inicializan los campos privados, por lo que ...

Código
  1. extern Sesion s;
  2.  

...estaría inicializando dichos campos automáticamente, aún asi debo volver a definir tal como lo hiciste cuando escribiste esta linea ? :

Código
  1. int x::num = 10; // definida aquí o en cualquier otro cpp
  2.  

O es que al escribir extern Sesion s en realidad no estoy ejecutando el constructor con su inicialización?

Saludos! y gracias por las respuestas... han sido de mucha ayuda @std::string Manolo y @Loretz.
En línea

Dungeons & dragons;
dragons.Attack();
Loretz

Desconectado Desconectado

Mensajes: 112


Ver Perfil
Re: Variables estaticas...
« Respuesta #8 en: 30 Agosto 2019, 19:31 pm »

Para objetos de alguna clase es lo mismo que para tipos nativos, puedes usar las dos formas, declarar el objeto como extern o como inline (mejor).

Por ejemplo, usando extern podría ser algo así:
Archivo1.h
Código:
#pragma once
#include <string>

extern struct X {
    X(std::string str) : str(str) {}
    int num = 10;
    std::string str;
} x;

Y en algún cpp
Código:
X x{"hola"};

Usando inline no necesitas que la definición esté en un cpp
Código:
#pragma once
#include <string>

inline struct X {
    X(std::string str) : str(str) {}
    int num = 10;
    std::string str;
} x{"hola"};

Estos son un par de ejemplos de cómo podía hacerse antes y ahora con el estándar C++17, pero hay otras cosas a considerar, probablemente necesites un constructor por defecto, y asignarle valores a tu objeto cuando el programa los conozca, o crear el objeto en la memoria libre (usando un smart pointer, por supuesto), o ... Bueno, ya verás.

[EDITO] Ah, me olvidaba
Citar
O es que al escribir extern Sesion s en realidad no estoy ejecutando el constructor con su inicialización?
No, no estás ejecutando el constructor, porque extern Sesion es una declaración no una definición.


« Última modificación: 30 Agosto 2019, 19:33 pm por Loretz » En línea

digimikeh

Desconectado Desconectado

Mensajes: 184


Ver Perfil
Re: Variables estaticas...
« Respuesta #9 en: 31 Agosto 2019, 23:07 pm »

ok, entiendo, pero yo tenía entendido que cuando tu definías algo, estas usando el constructor... o es que extern es la excepción?

Alpha.h
Código
  1. class Alpha{
  2.     int x;
  3. public:
  4.     Alpha() : x{5}{}
  5.     //hacer otras cosas
  6. }
  7.  

main.cpp
Código
  1. #include "Alpha.h"
  2.  
  3. int main (){
  4.     Alpha a;            //Nota (a)
  5. }
  6.  

Nota (a) : A pesar de estar declarando un objeto llamado a de tipo Alpha se estaría inicializando el campo privado x y valdría 5... (es asi como yo tengo en mi programa el objeto Sesion inicializa sus campos privados a un string "NA".

Sin embargo, acabo de darme cuenta que incializar y definir no son la misma cosa...


En línea

Dungeons & dragons;
dragons.Attack();
Páginas: [1] 2 Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
CMS Páginas estaticas
PHP
Kevxfire 1 2,347 Último mensaje 8 Julio 2011, 19:46 pm
por Nakp
Problema con declaraciones estáticas « 1 2 »
.NET (C#, VB.NET, ASP)
WHK 11 3,745 Último mensaje 12 Julio 2013, 16:06 pm
por Novlucker
(PyQt) Variables estaticas en Python
Scripting
F3niX14 2 2,382 Último mensaje 29 Septiembre 2013, 19:17 pm
por F3niX14
variables estaticas en main
Programación C/C++
fafafa01 1 726 Último mensaje 13 Diciembre 2016, 05:16 am
por engel lex
Listas Estaticas
Programación C/C++
angeljonh 1 1,004 Último mensaje 30 Septiembre 2017, 12:37 pm
por ivancea96
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines