Ridefinizione di variabili globali con clausa "extern"
-
Buongiorno: rieccomi qua.
Ieri pomeriggio ho postato una domanda simile a questa su un altro forum, ma è rimasta priva di risposta, quindi ci riprovo qui, avendo sperimentato che in questo forum ci sono dei guru più che esperti.
Ho letto che se si vogliono creare delle variabili globali bisogna definirle al di fuori della main e ripeterle con l'apposizione static in tutte le classi in cui si usano.
Dato che provengo da linguaggi in cui le classi non erano neppure immaginate (Assembler, Cobol, etc.) mi è difficile modificare la mia forma mentis di colpo e quindi ho pensato di fare un uso eccessivo di variabili globali. Il problema è che l'elenco di queste variabili è lungo (diciamo un centinaio) e doverle poi ripetere in tutte le classi che andrò a implementare diventerebbe un facile veicolo di errori. Per questo avrei pensato alla seguente soluzione.
Creo un file header in cui le prime istruzioni sono le seguenti:#define TIPODATO extern #ifndef HRNET_0010_DICHIARATIVE_H #define HRNET_0010_DICHIARATIVE_H #define TIPODATO static #endif // HRNET_0010_DICHIARATIVE_H TIPODATO int larghezzaschermo = -1; TIPODATO int altezzaschermo = -1; TIPODATO int altezzabarra = -1; TIPODATO int quadroestrattix = -1; TIPODATO int quadroestrattiy = -1; TIPODATO int quadroestrattilarghezza = -1; TIPODATO int quadroestrattialtezza = -1; TIPODATO int quadrosingolonumerox = -1; TIPODATO int quadrosingolonumeroy = -1; TIPODATO int quadrosingolonumerolarghezza = -1; TIPODATO int quadrosingolonumeroaltezza = -1;
Includendo questo header all'inizio della main e di tutte le classi dovrei avere nella main la variabile larghezzaschermo definita come "static int larghezzaschermo;" mentre nelle varie classi dovrebbe diventare "extern int larghezzaschermo".
L'idea penso che potrebbe essere buona, ma... non funziona: perché ?
Ecco gli errori che vengono fuori in compilazione:
Mi date per favore qualche dritta ? Grazie.
bvox -
Premessa: se hai bisogno di tutti quei global probabilmente il tu design merita una rivisitazione...
metti tutte le globali in una struct in un header file (ricorda gli include guards), assegna un valore in un cpp file e usali dove vuoi:
globali.h
#ifndef GLOBALI_H #define GLOBALI_H struct ContenitoreGlobali{ static int larghezzaschermo; static int altezzaschermo; // etc. }; #endif
globali.cpp
#include "globali.h" int ContenitoreGlobali::larghezzaschermo = -1; int ContenitoreGlobali::altezzaschermo = -1; // etc.
ora puoi usarle usando
ContenitoreGlobali::larghezzaschermo
eContenitoreGlobali::altezzaschermo
dopo aver aggiunto#include "globali.h"
all'inizio -
Grazie VRonin. Segretamente contavo su una tua risposta. Devo dire che più o meno avevo tentato questa strada, ma avevo letto che le struct sono in pratica delle classi, quindi avevo provato ad istanziarla e forse questo è stato l'errore. Poi una descrizione degli errori che è molto fuorviante mi aveva fatto scegliere quell'altra soluzione, che però non funziona. Domani mi adeguerò ai tuoi suggerimenti.
Grazie ancora.
bvox -
Non va... e non capisco il perché. Questo è il file header:
#ifndef HRNET_0010_DICHIARATIVE_H #define HRNET_0010_DICHIARATIVE_H struct HRvbl { const int larghezzaschermo; const int altezzaschermo; const int altezzabarra;
Questo è il main.cpp:
#include "hrnet_0000_classeprincipale.h" #include "hrnet_0010_dichiarative.h" #include <QApplication> #include <QDesktopWidget> #include <iostream> int main(int argc, char *argv[]) { QApplication applicazione(argc, argv); int HRvbl::larghezzaschermo = -1; // QApplication::desktop()->width(); HRvbl::altezzaschermo = -1; // QApplication::desktop()->height();
e questi sono gli errori di compilazione (non ci capisco niente):
Ho anche provato ad istanziare HRvbl, magari gli errori cambiano, ma ce ne sono sempre. Cosa faccio ?!?
-
stai usando
const int altezzaschermo;
ma non static come il mio post sopra. ti basta aggiunglo all'inizio:static const int altezzaschermo;
Ora il secondo problema: se usi
const
il valore della variabili o e' conosciuto al momento della copilazione ad esempioconst double pi_greco=3.14;
o deve essere conosciuto quando la variabile e' "costruita" (brutta traduzione di constructed). Quindi, nel mio esempio sopra, il valore deve essere determinato in globali.cpp. se vuoi fare una cosa tipoHRvbl::altezzaschermo = -1;
in main devi per forza togliere in const.P.S.
Di nuovo, dubito fortemente queste costanti ti servano sul serio -
Straordinario. Ho scritto const ma intendevo dire static. La variabili non sono come il pigreco, sono proprio variabili che variano nel tempo. Capisco bene che l'idea di un centinaio di variabili è fuori logica, ma il più avanzato linguaggio di programmazione che ho un po' approfondito è stato il vb6: niente classi. Lasciami fare un po' di retrospezione.
Con l'Assembler avevamo a disposizione non più di 50-60 vocaboli (istruzioni) e solo l'ingegno umano sapeva metterle insieme per realizzare pregetti informatici complessi. In fondo è a quei tempi che sono nati database gerarchici, soppiantati da quelli relazionali, metodi di compressione, sort e cose simili. Oggi i linguaggi si sono arricchiti di migliaia di forme di istruzioni, le classi, che hanno appesantito l'apprendimento degli stessi e il vantaggio di poter fare le cose più velocemente è solo un'utopia: chi ne ha una buona conoscenza fa tutto più velocemente, ma prima di arrivare a questa conoscenza, ne passa acqua sotto i ponti.
Grazie VRonin, prometto che mi impegnerò meglio a "studiare" le classi e le sintassi per utilizzarle senza errori. Buon fine settimana. -
Ma la pseudo-classe contenente le mie dichiarative nella struct la devo istanziare ?
Mi sembra strano che se i riferimenti alle variabili li inserisco nella main li ritrova, mentre mettendoli in un'altra classe dice "riferimento non definito". Suppongo che sia perché il primo modulo ad essere compilato è la main e qui include l'header dichiarative, poi prosegue a compilare le altre classi, ma qui il #ifndef fa saltare l'include, quindi non trova quelle variabili. Torno alla prima ipotesi: definire due strutture di dichiarative uguali, ma la seconda con tutte le variabili con la clausola extern.
Purtroppo mi sto scoraggiando e sono solo all'inizio... -
@bvox123 said in Ridefinizione di variabili globali con clausa "extern":
Ma la pseudo-classe contenente le mie dichiarative nella struct la devo istanziare ?
No. static serve a quello.
Mi sembra strano che se i riferimenti alle variabili li inserisco nella main li ritrova, mentre mettendoli in un'altra classe dice "riferimento non definito".
Puoi postare un esempio?
Hai generato una cosa come
globali.cpp
sopra? -
// main.cpp #include "hrnet_0000_classeprincipale.h" #include "hrnet_0010_dichiarative.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication applicazione(argc, argv); HRnet_0000 hrnet_0000; hrnet_0000.show(); int codiceritorno; codiceritorno = applicazione.exec(); return codiceritorno; }
#ifndef HRNET_0000_CLASSEPRINCIPALE_H #define HRNET_0000_CLASSEPRINCIPALE_H #include <QMainWindow> #include <QWidget> #include <QGroupBox> #include <QLineEdit> #include <QTextEdit> #include <QRadioButton> class HRnet_0000 : public QMainWindow { Q_OBJECT public: HRnet_0000(QWidget *parent = 0); ~HRnet_0000(); private: // QWidget *centralWidget; QWidget *qt5hrnet1; QWidget *qt5hrnet2; QWidget *qt5hrnet3;
#ifndef HRNET_0010_DICHIARATIVE_H #define HRNET_0010_DICHIARATIVE_H #include <QPoint> struct HRvbl { static int larghezzaschermo; static int altezzaschermo; static int altezzabarra;
#include "hrnet_0000_classeprincipale.h" #include "hrnet_0010_dichiarative.h" #include <QApplication> #include <QDesktopWidget> #include <iostream> HRnet_0000::HRnet_0000 (QWidget *parent) : QMainWindow(parent) { HRvbl::larghezzaschermo = 111; // QApplication::desktop()->width(); HRvbl::altezzaschermo = QApplication::desktop()->height();
e questo è l'elenco degli errori avendo spostato l'utilizzo delle variabili dalla main all'interno di una classe:
-
Esatto, ti manca l'equivalente del
globali.cpp
che ho postato.
aggiungi un filehrnet_0010_dichiarative.cpp
e mettici:#include "hrnet_0010_dichiarative.h" int HRvbl::larghezzaschermo = 0; int HRvbl::altezzaschermo =0;
i membri statici funzionano come i metodi: nel file h dici al compilatore che esistono (dichiarazione), nel file cpp chiarisci cosa fanno (definizione)
-
Quello che io avevo chiamato HRnet_0000_classeprincipale.cpp era proprio il corrispondente del tuo globali.cpp. Quindi il c++ è rigoroso anche nei nomi assegnati ai vari moduli ? In fondo il mio HRnet_0000 include il modulo HRnet_0010_dichiarative. E poi, anche se lo cambiassi di nome per renderlo simile all'header, non appena creassi una nuova classe non mi dirà che quella variabile non la riconosce ? Se la riconosce solo quando il nome del cpp è uguale al nome dell'header succederà così, penso. O no ? Se fosse così andrebbe a farsi friggere la mia idea di avere variabili globali da poter modificare in qualsiasi parte dell'applicativo.
-
@bvox123 said in Ridefinizione di variabili globali con clausa "extern":
Quello che io avevo chiamato HRnet_0000_classeprincipale.cpp era proprio il corrispondente del tuo globali.cpp
non nella sezione che hai postato almeno
@bvox123 said in Ridefinizione di variabili globali con clausa "extern":
c++ è rigoroso anche nei nomi assegnati ai vari moduli ?
No, assolutamente no, puoi chiamarli come vuoi
Un esempio:
hrnet_0010_dichiarative.h#ifndef HRNET_0010_DICHIARATIVE_H #define HRNET_0010_DICHIARATIVE_H struct HRvbl { // dichiaro static int larghezzaschermo; static int altezzaschermo; } #endif // HRNET_0010_DICHIARATIVE_H
hrnet_0010_dichiarative.cpp
#include "hrnet_0010_dichiarative.h" // definisco int HRvbl::larghezzaschermo; int HRvbl::altezzaschermo;
hrnet_0000_classeprincipale.cpp
HRnet_0000::HRnet_0000 (QWidget *parent) : QMainWindow(parent) { // uso HRvbl::larghezzaschermo = 111; // QApplication::desktop()->width(); HRvbl::altezzaschermo = QApplication::desktop()->height();
-
Sì, posso chiamarli come voglio, ma a due a due. Nel senso che se ho creato il modulo PIPPO.H come dichiarativo, devo obbligatoriamente chiamare PIPPO.CPP il modulo che lo definisce. Inoltre, il modulo che lo definisce non è una classe, io avevo preteso di inserire le definizioni nella prima classe dopo la main. Bene, ora funziona. Sei grande !!!
-
@bvox123 said in Ridefinizione di variabili globali con clausa "extern":
se ho creato il modulo PIPPO.H come dichiarativo, devo obbligatoriamente chiamare PIPPO.CPP
No.
Dettaglio minore qui visto che di solito e' consigliato chiamare entrambi i file con lo stesso nome.
Per chiarire: i file .h non vengono compilati, solo i file .cpp (o .c) contano. Ogni file .cpp viene compilato in un "object" (.obj in MSVC). Il linker poi prende tutti questi files e li mette assieme per generare l'eseguibile. La restrizione (a cui accenni sopra parlando di
extern
) e' che il linker, se vede la stessa cosa in 2 objects non sa cosa fare e crea un errore. In pratica non puoi definire la stessa variabile in piu' files .cpp.Puoi mettere l'intero contenuto di
hrnet_0010_dichiarative.cpp
inmain.cpp
. L'importante e' che non lo metti in multipli files .cpp