Newsgroup: it.comp.lang.c++
Titolo: errore incomprensibile !

Salve,
    non riesco a capire perche questo codice non compila:
/*-----------------------------------------*/
include <iostream>
static const int int_1 = 1;
static const char * const name_1[] = { "zero", "one", "two" };  //(0)
static const string str_1[] = { "zero", "one", "two"  };               // (1)
class P
{
  static const int int_2 = 1;                                                    //(4)
  static const char * const name_2[] = { "zero", "one", "two"  }; //(2)
  static const string str_2[] = { "zero", "one", "two"  };               // (3)
public:
  P()  {};
    // ...
 };
/* ------------------------------------------- */
il compilatore da i seguenti errori (alle linee segnate con (2) e (3)):
pro.cc:13: invalid initializer
pro.cc:14: field initializer is not constant
pro.cc:14: initializer invalid for static member with constructor
pro.cc:14: (you really want to initialize it separately)
le linee (2) e (3) sono però analoghe a quelle segnate con (0) e (1).
Inoltre la linea (4) viene correttamente accettata
Non riesco a capire perche questo tipo di inizializzazioen è proibita all'interno di una classe
mentre è consentita fuori come variabile globale. Vorrei mantenerle all'interno per limitare lo scope delle definizioni ma non so come fare
Siete in grado di aiutarmi ?
Grazie,
    Fabrizio
--
     +-
     | Fabrizio Cannizzo
     +-
     |   Addr:   Via Cesare Battisti, 20 - 56125 Pisa - IT
     |   Phone:  cell:
+39 3384614539
, home: +39 5026227
     |   EMail:  
fcan...@cribecu.sns.it
     |   Web HP: 
http://studenti.ing.unipi.it/~s154320
     +-

>
i membri statici di una classe non vanno inizializzati nella dichiarazione ma all'esterno (essendo essi una definizione) premettendo il nome della classe (P::int_2) un po' come dichiarare una variabile globale extern da una parte e definirla da un'altra parte.
Antonio Donatiello


#include <iostream>
#include <string>
static const int int_1 = 1;
static const char * const name_1[] = { "zero", "one", "two" };  //(0)
static const string str_1[] = { "zero", "one", "two"  };               // (1)
class P
{
  static const int int_21;
  static const char * const name_2[];
  static const string str_2[];
public:
  P(){}
  ~P(){}
};
const int P::int_21=1;
const string P::str_2[]={ "zero", "one", "two"  };               // (3)
const char * const P::name_2[]={ "zero", "one", "two"  };
Marco Guidi

>

i membri statici di una classe non vanno inizializzati nella dichiarazione
ma all'esterno (essendo essi una definizione) premettendo il nome della
classe (P::int_2) un po' come dichiarare una variabile globale extern da
una parte e definirla da un'altra parte.


il punto e' che i membri sono sia static che const e quindi la dichiarazione


la definizione e la inizializzazione, se non erro, coincidono. Infatti la linea


        static const int int_2 = 1;


viene correttamente compilata. Il problema si pone per gli "static const char *" e per


i "static const string" per quali ottengo gli errori (invalid initializer).






>

i membri statici di una classe non vanno inizializzati nella dichiarazione
ma all'esterno (essendo essi una definizione) premettendo il nome della
classe (P::int_2) un po' come dichiarare una variabile globale extern da
una parte e definirla da un'altra parte.

Antonio Donatiello

il punto e' che si tratta di "static const" quindi dichiarazione definizione
e inizializzazione coincidono. Infatti la linea

static const int int_2=1

viene correttamente compilata.

Il problema si pone per "static const string" e "static const char *
const".









Scusate per le numerose mail... ho avuto un piccolo problema.
    Fabrizio

Scusate per le numerose mail... ho avuto un piccolo problema.
Ce ne siamo accorti.
Il Ghenio

i "static const string" per quali ottengo gli errori (invalid initializer).
Infatti il problema e` proprio per questi ultimi...
non so se e` un limite del compilatore o e` previsto dallo
standard, ma fatto sta che gli "static const char *" non
possono essere inizializzati nella dichiarazione di classe,
devi farlo al di fuori.
Paolo
P.s.
   Evita di postare (anche?) in html
-----------------------------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
-----------------------------------------------------------------

 devi farlo al di fuori.
Vorrei solo precisare una cosa che forse non è molto chiara (per me non
lo era): i membri che è possibile inizializzare all'interno della classe
sono solo quelli static const (a parte l'eccezione dello static const
char *). Mentre devono essere definiti ed eventualmente inizializzati al
di fuori della classe quelli non-const.
EMG

di fuori della classe quelli non-const.
O non-static...
Precisazione piu` che doverosa, io l'avevo data per
sottintesa in tutto il discorso, aggiungo la spiegazione alla
cosa...
In pratica, il const stabilisce la non modificabilita`, il
qualificatore static invece ne stabilisce l'esistenza in unica
copia comune per tutte le istanze. Da questo si deduce il
perche` gli attributi static const possono essere inizializzati
dentro le classi (anche se non spiega perche` non si possa
fare la stessa cosa con gli static const char* e presumibilmente
qualsiasi puntatore, ma quest'ultima cosa non l'ho provata).
Per inciso cio` permette di scrivere
class array {
  private:
     static int size = 10;
     char Data[size];
     /* ... */
};
anzicche`
class array {
  private:
     enum { size = 10 };
     char Data[size];
     /* ... */
};
Con buona pace di noi puristi!!!!!
Paolo
Paolo


 Paolo
*Fabio*
-- 
If you look like your driver's license photo -- see a doctor.
If you look like your passport photo -- it's too late for a doctor.

 
questo va bene, compila ! non capisco pero' perche' con egcs non si
debba 
poter compilare
	static const char * const pointer str[]={"aaa", "bbb"}; 
visto che tutto č noto a tempo di compilazione.
Tra parentesi... il seguente codice produce un errore interno del
compilatore.
Forse e' per questo motivo che egcs (x linux, quello per win non lo so!)
sbombola:
/* ----------------- */ 
#include <iostream>
#include <string>
class P
{
    static const  string str = "ciao";
public:
  void stampa()
    { cout<<str<<endl; };
};
main()
{
  P p;
  p.stampa();
}
/* --------------------------- */
g++ -o prova prova.cc
prova.cc:6: Internal compiler error 109.
--
	Fab

       static char * const pointer = "pippo"; // leggittimo
Azz! Hai perfettamente ragione! Anche se il DJGPP emette comunque il
seguente warning:
"warning: ANSI C++ forbids initialization of member constant `pointer'
of non-integral type `char *const'"
Come mai?
EMG

non e' una costante ma una variabile! (colpo di scena :-)
E bravo!!!!!!!
Hai colto una finezza che ancora oggi a quanto pare continua a
"sfuggirmi", ovvero la differenza tra const T* e T* const...
Comunque continua a non funzionare, almeno sul mio compilatore
(BC++ 5.02)!
Per la cronaca, una (altra) cosa che mi era sfuggita:
basta che un membro sia static per poterlo inizializzare nella
definizione di classe...
class T {
  static int p = 6;
};
Nel mio precedente post ho fatto un po' di confusione col fatto che
un membro "static const int" possa essere usato al posto dei
tradizionali "enum ( Size = 4 }" per gli array.


 compilatore.
Il DJGPP invece dà il seguente messaggio di errore:
"in-class initialization of static data member of non-integral type
`const string'"
EMG

 tradizionali "enum ( Size = 4 }" per gli array.
Scusa, non ho capito questa frase ed in particolare le ultime tre
parole. Spiegami...
EMG

 EMG
si! parrebbe quindi che i compilatori si rifiutino di inizializzare
all'interno
di una classe variabili static const di tipi definiti dall'utente.

parole. Spiegami...
Prima dello standard l'unico modo *sicuro* di avere una costante di
tipo intero (all'interno della classe) da utilizzare come dimensione
per un membro array era la seguente:
class T {
   enum { Size = 20 };
   int ArrayMember[Size];
};
ora invece possiamo fare (meglio) nel seguente modo:
class T {
  static const int Size = 20;
  int ArrayMember[Size];
};
Nel post cui mi riferivo, cercavo di spiegare il
perche` un membro static const possa essere
inizializzato nella dichiarazione di classe.
Dal mio discorso si poteva dedurre (erroneamente)
che non bastasse solo static, mentre (almeno secondo
il mio compilatore) static e` sufficiente (almeno sui
tipi integrali)!


 è la linea giusta (anzi errata perche' non compila).
Ah, ecco. Il DJGPP mi dà solo un warning però poi, stranamente, il
linker mi dà "undefined reference str" se tento di accedere a str. :-?
EMG

 "static" con *una espressione costante*  ?
Un membro static non costante ha bisogno di una locazione 
di memoria, e il compilatore deve vedere la definizione
(una sola, in un file .c) per potergliela riservare.
La stessa cosa succede anche per i membri static const ma
non di un integral/enum type (anche loro hanno bisogno 
della locazione di memoria).  Invece nel caso degli
integral/enum, il compilatore non ha bisogno di riservare
la memoria, ma si limita a sostituire il valore della
constante in caso di necessita'.
	Mauro

linker mi dà "undefined reference str" se tento di accedere a str. :-?
Giustissimo, il linker ha ragione. Hai ridichiarato i membri static
all'esterno della dichiarazione della classe?
class MyClass
{
  static char * Pippo[];
};
static char * MyClass::Pippo[] = { "pluto", "minni" };
In teoria (non l'ho provato) questo codice dovrebbe funzionare.
Ciao, Giuseppe
---------------------------------------------------------------------------
_Guybrush su IRCNet canale #programmazione
ICQ: 42227764
---------------------------------------------------------------------------

static char * MyClass::Pippo[] = { "pluto", "minni" };
ripetere static nella inizializzazione dell'attributo dovrebbe
essere un errore (almeno lo e` sul mio compilatore).


constante in caso di necessita'.
Non credo che il problema sia l'allocazione di memoria...


 all'esterno della dichiarazione della classe?
Bravissimo! Ora funziona (anche se rimane il warning). Tra parentesi si
può anche inizializzare nella classe e non nella definizione esterna.
EMG

 e` comunque un errore ndr).
Non e' impossibile, ma e' molto piu'  difficiile (per
il compilatore).
La dichiarazione viene vista una volta per ogni file
che include l'header della classe, e il compilatore si 
ritrova con n file che dichiarano la classe (e il membro
static). Quando deve creare il fole .o cosa fa? Ci
mette la variabile static? (rischiando di trovarsene n)
Spera che ci abbia gia' pensato in una delle altre 
n-1 volte?
Naturalmente si potrebbe fare che il comilatore la mette
tutte le volte e il linker elimina quelle inutili (e
corregge i riferimenti), ma hanno pensato che e' molto
piu' semplice se ci pensa il programmatore e definire
la variabile in un file di implementazione.
	Mauro

può anche inizializzare nella classe e non nella definizione esterna.
Il mio compilatore non me lo permette (Turbo C++ 1.01).


essere un errore (almeno lo e` sul mio compilatore).
Si, hai ragione, non ci avevo fatto caso (non avevo provato il codice).


Il mio compilatore non me lo permette (Turbo C++ 1.01).
Decisamente piu` vecchio del mio!  ;-)
Scherzi a parte ti consiglio di aggiornarlo con uno
piu` recente.


piu` recente.
Purtroppo sono limitato a questo compilatore (real mode 16 bit, sigh :-( )
perché è l'unico non per Win che mi permette di utilizzare l'asm inline
all'interno di metodi e funzioni. Vorrei fortemente passare al DJGPP, ma
questo usa la notazione AT&T (invece di quella Intel) nell'asm inline, che
non fa al caso mio.
Purtroppo sono bloccato........


 wrote:
In una rivista tempo fa trovavi la versione completa del Borland C++
5.02, successore della serie Turbo C++ e che permette anche di compilare
per dos.
Era computer magazine di aprile.


Era computer magazine di aprile.
Ma il Borland C++ 5.02, quando compila per DOS, lo fa per modalità protetta
o modalità reale ?
Grazie in ogni caso per la dritta.


o modalità reale ?
Reale, con o senza overlay.


Reale, con o senza overlay.
Grazie 1000!
