{"id":67,"date":"2009-10-24T16:28:24","date_gmt":"2009-10-24T14:28:24","guid":{"rendered":"https:\/\/blogs.ua.es\/progoo\/?p=67"},"modified":"2011-10-25T00:33:19","modified_gmt":"2011-10-24T22:33:19","slug":"atributos-de-clase-constantes-en-c","status":"publish","type":"post","link":"https:\/\/blogs.ua.es\/progoo\/2009\/10\/24\/atributos-de-clase-constantes-en-c\/","title":{"rendered":"Atributos de clase constantes en C++"},"content":{"rendered":"<p>La inicializaci\u00f3n de atributos est\u00e1ticos constantes en C++ depende del tipo de constante que queramos crear.<\/p>\n<p>Veamos que ocurre con el siguiente ejemplo (en comentario aparecen los n\u00fameros de l\u00ednea para posterior referencia):<\/p>\n<blockquote>\n<pre>class Ejemplo {\r\n  public:\r\n  \u00a0static const int x=10; \/\/ 10\r\n   static const float PI =3.141592; \/\/ 11\r\n   static const string s1=\"HOLA\"; \/\/ 12\r\n   static const string s2=string(\"HOLA\"); \/\/ 13\r\n   static const Ejemplo ejemplo1; \/\/ 14\r\n   static const Ejemplo ejemplo2=Ejemplo(2); \/\/ 15\r\n   Ejemplo(int x=0) : val(x) {}\r\nprivate:\r\n  \u00a0int val;\r\n};<\/pre>\n<\/blockquote>\n<p>Al intentar compilar esta declaraci\u00f3n de clase con gcc (versi\u00f3n 4.3.3), aparecen estos errores:<\/p>\n<pre>atrib_constante.h:12: error: inicializaci\u00f3n en la clase inv\u00e1lida para el miembro de datos static de tipo \u2018const std::string\u2019 que no es integral\r\natrib_constante.h:13: error: a call to a constructor no puede aparece en una expresi\u00f3n constante\r\natrib_constante.h:13: error: inicializaci\u00f3n en la clase inv\u00e1lida para el miembro de datos static de tipo \u2018const std::string\u2019 que no es integral<\/pre>\n<p>que viene a decir que no se pueden inicializar constantes que no sean de tipo primitivo de C++ en la declaraci\u00f3n de la clase. En la l\u00ednea 15 el error de compilaci\u00f3n es diferente:<\/p>\n<pre>atrib_constante.h:15: error: invalid use of incomplete type \u2018class Ejemplo\u2019\r\natrib_constante.h:8: error: forward declaration of \u2018class Ejemplo\u2019\r\natrib_constante.h:15: error: inicializaci\u00f3n en la clase inv\u00e1lida para el miembro de datos static de tipo \u2018const Ejemplo\u2019 que no es integral<\/pre>\n<p>es decir, no podemos intentar crear en ese momento un objeto de clase Ejemplo, ya que \u00e9sta a\u00fan no est\u00e1 completamente definida. Sin embargo, s\u00ed podemos declarar objetos de clase (est\u00e1ticos) de tipo Ejemplo dentro de la propia clase (l\u00ednea 14), siempre y cuando no intentemos inicializarlos (construirlos) ah\u00ed. La soluci\u00f3n a estos errores es simplemente realizar la inicializaci\u00f3n en el fichero de implementaci\u00f3n (o a continuaci\u00f3n de la declaraci\u00f3n de la clase):<\/p>\n<pre>class Ejemplo {\r\npublic:\r\n static const int x=10;\r\n static const float PI =3.141592;\r\n static const string s1;\r\n static const string s2;\r\n static const Ejemplo ejemplo1;\r\n static const Ejemplo ejemplo2;\r\n Ejemplo(int x=0) : val(x) {}\r\nprivate:\r\n int val;\r\n};\r\n\r\nconst string Ejemplo::s1 = \"HOLA\";\r\nconst string Ejemplo::s2 = string(\"HOLA\");\r\nconst Ejemplo Ejemplo::ejemplo1;\r\nconst Ejemplo Ejemplo::ejemplo2 = Ejemplo(2);<\/pre>\n<p>En estas inicializaciones hay que tener en cuenta dos cosas:<\/p>\n<ol>\n<li>Hay que indicar el \u00e1mbito de las constantes, en este caso, la clase Ejemplo.<\/li>\n<li>No hay que poner el modificador &#8216;static&#8217;.<\/li>\n<\/ol>\n<p>Fij\u00e9monos en &#8216;ejemplo1&#8217;. La inicializaci\u00f3n no especifica a qu\u00e9 valor debe inicializarse el objeto. \u00bfEs por tanto necesaria? Si no lo hacemos obtendremos este bonito mensaje al intentar compilar y enlazar nuestro c\u00f3digo para crear un programa ejecutable:<\/p>\n<pre>atrib_constante.cc:(.text+0x152): undefined reference to `Ejemplo::ejemplo1'<\/pre>\n<p>Es decir, &#8216;ejemplo1&#8217; ha sido <strong>declarado<\/strong> pero <strong>no definido. <\/strong>Es necesario definirlo (construirlo) expresamente, mediante la instrucci\u00f3n de definici\u00f3n<\/p>\n<pre>const Ejemplo Ejemplo::ejemplo1;<\/pre>\n<p>Esto no es una declaraci\u00f3n de &#8216;ejemplo1&#8217; (\u00e9sta se hizo en la clase), sino su definici\u00f3n o, en otras palabras, su construcci\u00f3n. De hecho esa definici\u00f3n es equivalente a<\/p>\n<pre>const Ejemplo Ejemplo::ejemplo1=Ejemplo();<\/pre>\n<p>donde se ve expl\u00edcitamente que al definir &#8216;ejemplo1&#8217; estamos invocando al constructor por defecto de su clase.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>La inicializaci\u00f3n de atributos est\u00e1ticos constantes en C++ depende del tipo de constante que queramos crear. Veamos que ocurre con el siguiente ejemplo (en comentario aparecen los n\u00fameros de l\u00ednea para posterior referencia): class Ejemplo { public: \u00a0static const int x=10; \/\/ 10 static const float PI =3.141592; \/\/ 11 static const string s1=&#8221;HOLA&#8221;; \/\/ [&hellip;]<\/p>\n","protected":false},"author":1276,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[5986],"class_list":["post-67","post","type-post","status-publish","format-standard","hentry","category-general","tag-atributos"],"_links":{"self":[{"href":"https:\/\/blogs.ua.es\/progoo\/wp-json\/wp\/v2\/posts\/67","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.ua.es\/progoo\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.ua.es\/progoo\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.ua.es\/progoo\/wp-json\/wp\/v2\/users\/1276"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.ua.es\/progoo\/wp-json\/wp\/v2\/comments?post=67"}],"version-history":[{"count":10,"href":"https:\/\/blogs.ua.es\/progoo\/wp-json\/wp\/v2\/posts\/67\/revisions"}],"predecessor-version":[{"id":93,"href":"https:\/\/blogs.ua.es\/progoo\/wp-json\/wp\/v2\/posts\/67\/revisions\/93"}],"wp:attachment":[{"href":"https:\/\/blogs.ua.es\/progoo\/wp-json\/wp\/v2\/media?parent=67"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.ua.es\/progoo\/wp-json\/wp\/v2\/categories?post=67"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.ua.es\/progoo\/wp-json\/wp\/v2\/tags?post=67"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}