Variabili Globali (extern)

di il
15 risposte

Variabili Globali (extern)

Buonasera.
Ho buttato giù un programmino che mi aiutasse a capire come definire ed usare una variabile globale, ma sono ancora a zero.
Spero non vi arrabbiate se allego questo programma, sperando che qualcuno mi possa dare una dritta per venirne a capo.
Main.cpp...
#include "h_000_dichiarative.h"
#include "h_001_classe_uno.h"

#include "gtkmm.h"

#include <iostream>
using namespace std;

int main() {
Glib::RefPtr<Gtk::Application> app = Gtk::Application::create();

H_001_Classe_Uno *Istanza_Classe_Uno = new H_001_Classe_Uno;

int risposta = app->run(*Istanza_Classe_Uno);

return risposta;

}



Dichiarative.h...
#ifndef H_000_DICHIARATIVE_H
#define H_000_DICHIARATIVE_H

#include "gtkmm.h"

#include <iostream>
using namespace std;

extern string Testo1;

class H_000_Dichiarative {
public:
H_000_Dichiarative();
};

#endif // H_000_DICHIARATIVE_H



Dichiarative.cpp...
#include "h_000_dichiarative.h"

H_000_Dichiarative::H_000_Dichiarative() {

}



H_001_Classe_Uno.h...
#ifndef H_001_CLASSE_UNO_H
#define H_001_CLASSE_UNO_H
#include "h_000_dichiarative.h"

#include "gtkmm.h"

#include <iostream>
using namespace std;

string Testo1 = "Inizializzato in classe uno - "; // COMMENTO_1

class H_001_Classe_Uno : public Gtk::Window
{
public:
H_001_Classe_Uno();

// string Testo1 = "Inizializzato in classe uno - ";

};

#endif // H_001_CLASSE_UNO_H



H_001_Classe_Uno.cpp...
#include "h_001_classe_uno.h"
#include "h_002_classe_due.h"
//#include "h_000_dichiarative.h"

H_001_Classe_Uno::H_001_Classe_Uno() {

Testo1 += "Passato da Classe_Uno - ";

H_002_Classe_Due IstanzaClasseDue;

}



H_002_Classe_Due.h...
#ifndef H_002_CLASSE_DUE_H
#define H_002_CLASSE_DUE_H
#include "h_000_dichiarative.h"

#include "gtkmm.h"

#include <iostream>
using namespace std;

// string Testo1 = "Inizializzato in classe due - ";

class H_002_Classe_Due : public Gtk::Window
{
public:
H_002_Classe_Due();

// string Testo1 = "Inizializzato in classe due - ";

};

#endif // H_002_CLASSE_DUE_H



H_002_Classe_Due.cpp...
#include "h_002_classe_due.h"
//#include "h_000_dichiarative.h"

H_002_Classe_Due::H_002_Classe_Due() {

Testo1 += "Passato da Classe_Due - ";

cout << Testo1 << endl;

}
Sembra che non ne voglia sapere della extern indicata in Dichiarative: così com'è mi dice "multiple definition of Testo1", se invece invalido l'istruzione contrassegnata con COMMENTO_1 mi dà l'errore che Testo1 non è definito.
Se non sono troppo seccante, mi sapete spiegare cosa sbaglio nell'uso di extern ?

15 Risposte

  • Re: Variabili Globali (extern)

    1) Non sai usare i moduli? Il tuo primo programma di test deve avere due moduli e basta, perché ti complichi la vita?
    2) Perché usi le classi per capire un concetto che al momento non c'entra nulla con le classi? Le classi non sono obbligatorie, non è Java
    3) Si era detto la dichiarazione nel modulo e non negli header proprio per evitare rogne, o sbaglio?
  • Re: Variabili Globali (extern)

    Con due moduli e basta gli effetti non si possono vedere: in uno lo definisci extern, nell'altro lo dichiari, come fai a verificare che sia stata creata una variabile globale che può usata dappertutto ? Poi mi è sembrato logico riprodurre in piccolo quello che mi serve: possibile che in questo banalissimo esempio la clausola extern non agisce come avevo letto da qualche parte ? Dammi qualche idea su come generare variabili globali in questa configurazione. Grazie.
  • Re: Variabili Globali (extern)

    Continuando a ricercare, ho trovato questo che mi risolve solo in parte il problema:
    http://www.programmiamo.altervista.org/C/funzioni/funz11.html
    Quindi le variabili globali le devo dichiarare normalmente in un heder senza classe e poi negli altri headers definirle nuovamente con la clausola extern.
    Ho modificato con queste nuove deduzioni il programmino, ma non mi spiego perché l'aggiornamento che avviene in ClasseUno non viene recepito in ClasseDue. La risposta che mi dà il cout è questa:"inizializzato in dichiarative - Passato da Classe_Due -".
    Riposto tutto il programma, perdonate la lunghezza del post.

    #include "h_000_dichiarative.h"
    #include "h_001_classe_uno.h"

    #include "gtkmm.h"

    #include <iostream>
    using namespace std;

    int main() {
    Glib::RefPtr<Gtk::Application> app = Gtk::Application::create();
    H_001_Classe_Uno *Istanza_Classe_Uno = new H_001_Classe_Uno;
    int risposta = app->run(*Istanza_Classe_Uno);
    return risposta;
    }



    #ifndef H_000_DICHIARATIVE_H
    #define H_000_DICHIARATIVE_H

    #include "gtkmm.h"

    #include <iostream>
    using namespace std;

    static string Testo1 = "inizializzato in dichiarative - ";

    #endif // H_000_DICHIARATIVE_H



    #ifndef H_001_CLASSE_UNO_H
    #define H_001_CLASSE_UNO_H
    #include "h_000_dichiarative.h"

    #include "gtkmm.h"

    #include <iostream>
    using namespace std;

    extern string Testo1;

    class H_001_Classe_Uno : public Gtk::Window
    {
    public:
    H_001_Classe_Uno();

    };

    #endif // H_001_CLASSE_UNO_H



    #include "h_001_classe_uno.h"
    #include "h_002_classe_due.h"
    #include "h_000_dichiarative.h"

    H_001_Classe_Uno::H_001_Classe_Uno() {

    Testo1 += "Passato da Classe_Uno - ";

    H_002_Classe_Due IstanzaClasseDue;

    }



    #ifndef H_002_CLASSE_DUE_H
    #define H_002_CLASSE_DUE_H
    #include "h_000_dichiarative.h"

    #include "gtkmm.h"

    #include <iostream>
    using namespace std;

    extern string Testo1;

    class H_002_Classe_Due : public Gtk::Window
    {
    public:
    H_002_Classe_Due();

    };

    #endif // H_002_CLASSE_DUE_H



    #include "h_002_classe_due.h"
    #include "h_000_dichiarative.h"

    H_002_Classe_Due::H_002_Classe_Due() {

    Testo1 += "Passato da Classe_Due - ";

    cout << Testo1 << endl;

    }
  • Re: Variabili Globali (extern)

    bvox123 ha scritto:


    Con due moduli e basta gli effetti non si possono vedere: in uno lo definisci extern, nell'altro lo dichiari, come fai a verificare che sia stata creata una variabile globale che può usata dappertutto ? Poi mi è sembrato logico riprodurre in piccolo quello che mi serve: possibile che in questo banalissimo esempio la clausola extern non agisce come avevo letto da qualche parte ? Dammi qualche idea su come generare variabili globali in questa configurazione. Grazie.
    Ti è stato detto esattamente come fare anche nell'altro topic, ma non lo vuoi fare e preferisci continuare a usare più di due moduli, classi e dichiarazioni nell'header... fatti due domande sul perché continui a sbatterci la testa
  • Re: Variabili Globali (extern)

    Non mi sembra una risposta che mi aiuti. La domanda è semplice, le tue osservazioni sono solo polemiche. Mi sai dire cosa sbaglio nell'esempio modificato come detto nel mio post precedente ?
  • Re: Variabili Globali (extern)

    Allora esplicito:

    globals.cpp: definizione e inizializzazione delle variabili globali (ovviamente non statiche)
    globals.h : dichiarazione extern delle stesse variabili (ovviamente senza inizializzazione)
    main.cpp: #include di globals.h
    modulo1.cpp: #include di globals.h ... stessa cosa con gli altri moduli

    Quando funziona prova a introdurre le strutture che sono più complicate.
    Quando funziona con le strutture, prova a introdurre le classi che sono più complicate
  • Re: Variabili Globali (extern)

    Bene, ora sì che sei stato gentile e costruttivo. Comunque ho risolto in un modo leggermente diverso, che lo spiego nel caso possa essere di aiuto a qualcun altro.
    Per poter usare variabili globali in una applicazione in C++, suggerisco (in alternativa ad altri metodi) di creare un file di dichiarative (Dichiarative.h) e includere in una struct tutte le variabili di cui si necessita con la clausola static, senza includere nessuna classe in questo header. Così:
    struct HRvbl {
    static string Testo1;
    static int Contatore1;
    }
    Nel corrispondente modulo Dichiarative.cpp inizializzare le variabili facendo riferimento al nome della struct precedente. Così:
    HRvbl::Testo1 = "Inizializzato Testo 1";
    HRvbl::Contatore1 = 1234;
    In Dichiarative.cpp non si deve fare riferimento a nessuna classe, ovvio visto che Dichiarative.h non definisce classi.
    In qualsiasi altro modulo dell'applicativo sarà sufficiente riferirsi a quelle variabili anteponendo il nome della struct, senza avere la necessità di ridefinire con extern le variabili. Quindi, se ho bisogno di aggiungere 101 in una classe al contatore globale, farò semplicemente così:
    HRvbl::Contatore1 += 101; e dopo questa istruzione il mio Contatore1 avrà il valore 1335.

    Se avete osservazioni e suggerimenti (possibilmente non polemici) vi prego di dirmeli.
  • Re: Variabili Globali (extern)

    In questo modo si hanno un bel po' di errori e warning (ovviamente) durante la compilazione. Tu non ne hai? Come stai compilando?

    Ma perché non usi l'extern e ti sei fissato con lo static che non c'entra nulla?

    In dichiarative.h

    extern int Contatore1;

    in dichiarative.cpp

    int Contatore1 = 1234;

    in main.cpp

    Contatore1 += 101;
  • Re: Variabili Globali (extern)

    Sei sicuro di questa sintassi ? Nelle prove che ho fatto, per giungere ad un risultato accettabile ma non corretto è stato quello di dichiarare extern int Contatore1 in tutti i moduli in cui mi serviva utilizzarlo, ma in classedue non risentiva delle variazioni apportate in classeuno. L'unico modo per avere un risultato corretto è stato quello di dichiarare la variabile prima del main ma non in dichiarative.h. Potrebbe anche andare bene, ma avendo molti moduli avrei dovuto dichiarare le struct all'inizio di ogni modulo per poi utilizzare le variabili senza prefisso e questo con una grande possibilità di duplicazione di nomi non segnalate dal compilatore. Col metodo che ho usato io questo inconveniente non ce l'ho.
    Comunque errori di compilazione non ne ho, ho qualche warning per effetto di conversioni non esplicitamente definite. Il programmino è scritto in Qt_Creator adattato per utilizzare le Gtkmm anziché le Qt. Ecco il risultato dell'esecuzione:
    Inizializzato in dichiarative - Passato da Classe_Uno -
    Inizializzato in dichiarative - Passato da Classe_Uno - Passato da Classe_Due -
    Inizializzato in dichiarative - Passato da Classe_Uno - Passato da Classe_Due -
    Press <RETURN> to close this window...

    Il file di configurazione .pro contiene, fra altre cose, le seguenti direttive:
    CONFIG += link_pkgconfig
    PKGCONFIG += gtkmm-3.0

    Dichiarative.h è ora così:
    #ifndef H_000_DICHIARATIVE_H
    #define H_000_DICHIARATIVE_H
    #include "gtkmm.h"
    #include <iostream>
    using namespace std;
    struct HRvbl {
    static string Testo1;
    } ;
    #endif // H_000_DICHIARATIVE_H

    mentre Dichiarative.cpp è questa:
    #include "h_000_dichiarative.h"
    string HRvbl::Testo1 = "Inizializzato in dichiarative - ";

    Classe_Uno.cpp e Classe_Due.cpp sono le seguenti:
    #include "h_001_classe_uno.h"
    #include "h_002_classe_due.h"
    H_001_Classe_Uno::H_001_Classe_Uno() {
    HRvbl::Testo1 += "Passato da Classe_Uno - ";
    cout << HRvbl::Testo1 << endl;
    H_002_Classe_Due IstanzaClasseDue;
    }

    #include "h_002_classe_due.h"
    H_002_Classe_Due::H_002_Classe_Due() {
    HRvbl::Testo1 += "Passato da Classe_Due - ";
    cout << HRvbl::Testo1 << endl;
    }

    Grazie comunque a tutti per avermi aiutato nella risoluzione.
  • Re: Variabili Globali (extern)

    Se sono certo della sintassi dici? Guarda... rinuncio alla discussione... buona fortuna
  • Re: Variabili Globali (extern)

    Ma guarda che non era un tono offensivo. Ho detto così perché avendo strutturato la prova con due moduli di classe, se non ricordo male dichiarandole in quel modo non avevo la permanenza della variazione apportata dalla prima classe e quando entrava nel costruttore di classedue si ritrovava la variabile come inizializzata in dichiarative, ma non modificata da classeuno. Se ti sei offeso mi scuso, ma non era questo il tono che volevo usare.
  • Re: Variabili Globali (extern)

    Nessuna offesa ma continui a fare quello che vuoi senza tener conto minimamente dei miei e altri consigli. Dunque è tempo perso e non ne ho tantissimo. Di nuovo auguri.
  • Re: Variabili Globali (extern)

    Ti sbagli, ho fatto tesoro dei vostri suggerimenti, ma ho trovato un modo che si addice meglio alla mia problematica. Ho riprovato col tuo metodo e funziona benissimo (sbagliavo a dubitare) ma resta il fatto che i nomi delle variabili si devono indicare senza prefisso e, nella quantità di moduli con oltre 1000 istruzioni in ognuno, potrebbe succedere che dichiari una variabile locale con lo stesso nome di una globale e questo causerebbe errori in esecuzione.
  • Re: Variabili Globali (extern)

    Bvox abbi pazienza, ma Oregon ha molti anni di esperienza in C++, può mai non essere sicuro di quello che dice?

    Il tuo problema, che è purtroppo comune a molti programmatori, è che non hai tempo o voglia di studiarti tutto il funzionamento del linker, che è una cosa molto lunga, e stai procedendo per tentativi o "alchimie", facendo pure l'errore di ritenere che chi ti sta dando suggerimenti stia pure lui procedendo per tentativi, quando invece è tutto molto chiaro. Chiaro che poi, se perseveri sulla tua strada, ti si lascia fare da solo
Devi accedere o registrarti per scrivere nel forum
15 risposte