Newsgroup: it.comp.lang.c++
Titolo: membri static.

Torno a disturbarvi con i miei dubbi che definire amletici ï¿œ riduttivo.
Consideriamo una classe SavingsAccount definita in questi due files:
SavingsAccount.hpp
 
http://sprunge.us/ECGb?cpp
SavingsAccount.cpp
 
http://sprunge.us/jPZX?cpp
e questo client:
main.cpp
 
http://sprunge.us/Tghe?cpp
va tutto bene. Il mio dubbio ï¿œ, perchï¿œ togliendo l'inizializzazione del 
dato membro static a riga 3 di main.cpp
  short int SavingsAccount::annualInterestRate = 0;
a compile time mi arriva questo bell'errore?
  g++ -Wall main.cpp -o main SavingsAccount.o
SavingsAccount.o: In function 
`SavingsAccount::setAnnualInterestRate(short)':
SavingsAccount.cpp:(.text+0x75): undefined reference to 
`SavingsAccount::annualInterestRate'
SavingsAccount.o: In function `SavingsAccount::getAnnualInterestRate()':
SavingsAccount.cpp:(.text+0x83): undefined reference to 
`SavingsAccount::annualInterestRate'
collect2: ld returned 1 exit status
ovvero: manca il riferimento all'oggetto membro?
non riesco proprio a spiegarmelo, il mio manuale non prevede nulla del 
genere... sarï¿œ scremo io??
grazie, di nuovo, in anticipo
M

tilde ha scritto:

Cioï¿œ praticamente ï¿œ come se il compilatore evitasse di mettere i 
riferimenti al membro static nel file oggetto se non esplicitamente 
richiesto... il che mi pare abbastanza strano. Se lo scrivo nell'header 
che quel membro c'ï¿œ, ï¿œ ovvio che lo voglio poter usare poi. Tra l'altro 
ne faccio uso nell'implementazione delle funzioni membro, e nella 
compilazione della classe non fa una piega :S

 genere... sarï¿œ scremo io??
Le variabili static di classe vanno dichiarate nella classe (tipicamente 
nel *.h) e definite fuori (tipicamente nel *.cpp). Definire la variabile 
nel main.cpp era concettualmente sbagliato, ma faceva il suo dovere. La 
cosa giusta ï¿œ definire la variabile in SavingsAccount.cpp
E.

 genere... sarò scremo io??
a volte il C++ è eccessivamente sintetico nel suo essere 
terso e rarefatto .... Il punto è (come peraltro ti ha già 
detto ?Manu*) che quella che hai chiamato una 
inizializzazione non è soltanto quello : è una DEFINIZIONE, 
con contestuale inizializzazione. L'inizializzazione è 
cortesia, la definizione è obbligatoria.
La variabile static è soltanto "in scope" dentro la classe 
(laddove viene infatti solo DICHIARATA), ma come "memoria 
fisica", passami la brutta immagine, è esterna ad essa, 
prova ne sia la necessità di definizione esterna.
Una volta che ometti la definizione, cadi in una situazione 
simile a mettere solo direttive extern senza nessuna 
definizione. Il compilatore si illude di conoscere il tipo 
di un oggetto, ma poi si accorge che nessuno lo costruisce.
(la differenza è che con extern addirittura se ne accorge 
poi solo il linker, dato il linkaggio esterno dell'oggetto, 
mentre qui, implicando lo STATIC un lincaggio interno, lo 
rileva già il compilatore perché chiude i conti a livello di 
unità di compilazione, e quel che non trova non confida che 
sia definito altrove).
Credo che se invece di omettere l'intera riga avessi tolto 
soltanto il = 0 finale, avrebbe compilato correttamente. Non 
so se quel valore iniziale fosse rilevante o meno, ma 
potresti tentare solo x verifica
ciao
Soviet


 
Giï¿œ, anche togliendo l'inizializzazione il tutto compila correttamente, 
e ho capito la logica secondo la quale opera il linguaggio, grazie a 
entrambi per l'aiuto.
Ma, piccolo ot, non capisco come mai questa cosa. Perchï¿œ il compilatore 
vuole una definizione ulteriore FUORI (come ha giustamente detto manu) 
dal file dove vengono dichiarati i membri static? Ha giï¿œ tutto quello 
che gli serve per definirla: nome, tipo (quindi informazioni sulla 
dimensione in memoria) e, ovviamente, ambito di visibilitï¿œ...
Che il compilatore debba sapere prima di ogni uso dove allocare la 
memoria? Heap o stack? Ma avevo  letto da qualche parte che le variabili 
statiche vengono allocate diversamente da quelle automatiche, ne so poco 
a dire il vero...

 a dire il vero...
No, non ï¿œ questo il problema. Le variabili globali sono tutte allocate 
staticamente (nï¿œ heap, nï¿œ stack). L'indirizzo di memoria viene scelto 
nella fase di linking.
E.

 E.
ciao
Soviet

Chiarissimi, quindi non sarebbe preferibile una definzione (con o senza 
inizializzazione) implicita in quanto, essendo static, possono esserci 
problemi nel caso in cui manchi proprio la risorsa contenente la 
definizione di quello che sto usando. Detto grezzamente, puï¿œ andare no?
Saluti
M

 problemi quella maledetta direttiva dimenticata
Ecco, infatti.
E.

tilde ha scritto:

Sï¿œ. Questa ï¿œ una situazione tipica delle scelte del linguaggio C/C++. La 
comoditï¿œ per l'utente viene messa in secondo piano rispetto alla 
possibilitï¿œ che il compilatore abbia la sicurezza di interpretare 
correttamente il codice. Questo puï¿œ essere svantaggioso per progetti 
molto piccoli, ma ï¿œ un bel vantaggio per progetti molto grossi.
Ad esempio in un linguaggio come python, se sbagli a scrivere il nome di 
una variabile puoi andare in grossi guai. L'interprete non puï¿œ 
accorgersene e non ti puï¿œ avvertire del disastro.
E.

?manu* ha scritto:

Perchï¿œ in python avviene la dichiarazione && definizione && 
inizializzazione di una variabile tutta in una botta sola, senza nemmeno 
il bisogno di specificatori particolari giusto? Tutto implicito n'somma.
Comincio ad apprezzare davvero queste scomoditï¿œ del c++, ma se non ci 
foste voi dubito che riuscirei a venirne a capo cosï¿œ velocemente ^^
M