Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Constantes en una clase

Iniciado por sés, 15 de Octubre de 2002, 04:37:50 PM

« anterior - próximo »

sés

                                Vamos a ver, estoy hasta los co...

Quiero hacer lo siguiente:



class  unaclase {

   static const char *unavar = "Holaaaa";

   ...

   ...

}



Pero no va, ¿cómo se haría?

Sin embargo, esto otro SÍ FUNCIONA:



class  unaclase {

   static const int unavar = 69;

   ...

   ...

}




P.D.: Estoy utilizando Borland C++ Builder 5                                
Soy indeciso... ¿o no?

metaxas

                                Las únicas constantes que pueden inicializarse dentro de una clase son las de tipo entero.
Para tener dentro de la clase una constante de cualquier otro tipo lo que tienes que hacer es declararla solamente, e inicializarla explícitamente en el constructor. Por ejemplo:

class CPrueba

{

private:

 const char *str;



public:

 CPrueba() : str("Hola")

 {

 }

};


Metaxas                                

Cronodragón

                                En serio? Que porquería.                                

Grugnorr

                                Diox, que me rallo.

Lo que dice Metaxas no crea una constante para TODAS las instancias de la clase, sino que cada una tiene esa constante.

No recuerdo que se pudieran inicializar las variables estáticas(de clase) directamente dentro de la definición de la clase, ya probaré si funciona eso con un int.

Para crear una variable estática( de clase), haz ésto:




/*        .h           */

class CFoo

{

private:

     

     static TipoVariable ms_NombreVariable;

     

};



/*           .cpp        */



CFoo::ms_NombreVariable = Valor;




Si no me he explicado muy bien, decidlo, que llego tardeeeeeeeee                                
hat the hells!

metaxas

                                Efectivamente, si quieres declarar una constante global a todas las instancias de la clase la declaras como static y la inicializas fuera de la declaración de la clase, pero tienes que indicar también Grugnorr el tipo de la variable que estás inicializando.
Si se trata de un entero puedes inicializarlo dentro:

class CFoo

{

private:      

 static const char *str;

 static const int a = 5;

};



const char* CFoo::str = "Hola";



Metaxas                                

sés

                                Vale, ¿pero alguien me puede decir por qué se puede con un int y no con un char *? O sea, ¿alguna razón lógica?

Porque los dos tipos ocupan 4 bytes.


...mi no entender :o                                
Soy indeciso... ¿o no?

metaxas

                                Pues la razón exacta no la sé, el caso es que está hecho así ;-). Al menos eso es lo que dice el standard ANSI C++ (9.4.2.4):

"If  a  static  data  member  is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer   which   shall   be   an   integral  constant  expression (_expr.const_).  In that case, the member can appear in integral constant expressions within its scope.  The member shall still be defined in a namespace scope if it is used in the program  and  the  namespace scope definition shall not contain an initializer."


Metaxas                                

synchrnzr

                                Cada vez que instancias una clase se le reserva un espacio concreto para sus variables locales de forma dinámica y por tanto el apuntador a char que estás declarando en la definición de la clase sí se encuentra en una dirección fija en memoria. Pero sin embargo su contenido sería distinto para cada instancia de la clase porque la cadena en sí debe pertencer al espacio de variables de la instancia y por tanto el apuntador que habría que asignar a tu const char* también sería distinto para cada instancia, con lo cuál no tiene mucho de static... En el caso de ints, floats, etc... el inicializador siempre es el número que has puesto en cambio. El problema supongo que está en que el compilador adivinar la posición de memoria donde caerá la cadena...

Mucho ánimo ^_^'

Sync

PD: Hay que tomar drogas para entenderlo, ya lo sé  :-?
PPD: Que me corrija cualquier programador de compiladores si me equivoco, no estoy seguro del todo de lo que acabo de decir :loco:
PPPD: Pero mola ¿a que sí? :P                                

sés

                               

class unaclase {

 static const char *unavar = (char *)0x12345;

 ...

 ...

}



¿Y esto? ¿Por qué tampoco funciona? Le estoy dando un valor al puntero.
Da igual que exista o no algo en esa dirección mientras no lo use. Un valor es un valor, ¿no?

:llorando:                                
Soy indeciso... ¿o no?

Kabila

                                Bueno, si estamos hablando que no se puede inicializar un char dentro de una clase, eso es un char ¿no? pues eso.                                

sés

                                Ya, la cosa está en la razón, en si tiene lógica o no.
Poderse ya he visto que no :(                                
Soy indeciso... ¿o no?

metaxas

No funciona porque el compilador directamente pasa de ello, el lenguaje no lo permite, así de simple. El analizador sintáctico está esperando esto:

STATIC CONST TYPE var_name;

o si es un puntero:

STATIC CONST TYPE TOKEN(*) var_name;

y esto otro si se quiere inicializar un entero:

STATIC CONST INT var_name TOKEN(=) const_value TOKEN(;)

cualquier otra cosa lo hará petar.



Las variables estáticas definidas en una clase (variables de clase), están en un espacio de memoria único, que será compartido por todas las instancias de la clase. Respecto a lo que dices, synchrnzr, la cadena de texto también tiene que estar en memoria en un solo sitio, el compilador debería ser lo suficientemente listo para darse cuenta de que es un valor al que está apuntando una variable estática, da igual que se inicialice fuera de la clase o dentro, no hay ningún problema técnico (de hecho, en Java lo puedes hacer), simplemente que el estandar ANSI C++ está definido así. Al igual que no se puedan inicializar los floats dentro, como los ints, ¿por qué?, pues porque al Stroustroup le dio por hacerlo así :-)


Metaxas

nostromo

                                Hola, la razón como dice metaxas es que el lenguaje esta definido asi.

Por una parte una "variable" int tal que asi:
static const int n = 5;
esto último el compilador lo trata como si fuera un simple enum. En realidad no es una variable con la que trabajar.

Y esto es asi porque el C++ en sus clases quiere que las variables de un objeto se inicialicen "en su sitio". Me explico, quieren que inicialicemos estas mediante un constructor.

La solución más elegante para este tipo de cosas seria tener por una lado una clase(podria ser la misma) con estos datos y otra que la declare como static dentro de ella:

class String {

 char *p;

 String():p("hola) { };

};



class unaclase {

 static String str;



  ..........

};


Con esto el objeto str(en particular) lo tenemos solo una vez para todas las instancias de "unaclase".

Un saludo a todos

PD: El señor Bjarne Stroustrup sabia lo que hacia :)                                






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.