Diferencia entre revisiones de «Correctitud de constantes»
Contenido eliminado Contenido añadido
m Bot: 8 - Estandarizaciones y otras mejoras automatizadas |
Corrijo ortografía, gramática, estilo y formato; traduzco categorías; retiro plantilla de mantenimiento, traducción revisada; cambios menores |
||
Línea 1:
En [[programación]], la '''correctitud de constantes''' ({{lang-en|const correctness
El uso de la palabra reservada <code>const</code> indica lo que el programador
▲En [[programación]], la '''correctitud de constantes''' (const correctness en Inglés) es el tipo de [[correctitud]] que hace referencia a la correcta declaración de variables u objetos como [[Objeto inmutable|inmutable]]s. El término es mayormente usado en el contexto de [[C (lenguaje de programación)|C]] o [[C++]], y recibe su nombre de la palabra reservada <code>const</code> de estos lenguajes.
El hecho de que sea posible modificar datos calificados con <code>const</code> en [[Tiempo de ejecución|tiempo de ejecución]] prueba que estos no se almacenan en memoria de sólo lectura. Para realizar estos cambios en tiempo de ejecución, deben evitarse las verificaciones que el compilador realiza sobre los valores <code>const</code> mediante el uso de [[Conversión de tipos|conversiones de tipo]] o [[Union (programación)|
▲El uso de la palabra reservada <code>const</code> indica lo que el programador ''debe'' hacer, no necesariamente lo que el programador ''puede'' hacer, pues calificar datos con esta palabra reservada no provoca que se almacenen en un tipo de [[Memoria (informática)|memoria]] de sólo lectura, si no que ordena al [[compilador]] realizar verificaciones sobre el [[Código fuente|código]] en [[tiempo de compilación]] para finalizar con un error el proceso de compilación en el caso de intentar modificar un dato constante.
▲El hecho de que sea posible modificar datos calificados con <code>const</code> en [[Tiempo de ejecución|tiempo de ejecución]] prueba que estos no se almacenan en memoria de sólo lectura. Para realizar estos cambios en tiempo de ejecución deben evitarse las verificaciones que el compilador realiza sobre los valores <code>const</code> mediante el uso de [[Conversión de tipos|conversiones de tipo]] o [[Union (programación)|union]]es.
<source lang=cpp>const int constante = 0; // Valor constante
Línea 36 ⟶ 34:
*u.punteroA_No_Constante = 4;</source>
Cabe destacar que el compilador puede decidir realizar [[Optimización de software|optimizaciones]] sobre los valores calificados con <code>const</code>
Los [[Método (informática)|
En C++, un campo puede ser declarado como [[mutable (Informática)|<code>mutable</code>]], indicando que la anterior restricción no se aplica sobre él
==
En C y otros lenguajes derivados, todos los tipos de datos (incluyendo los definidos por el usuario) pueden ser declarados con <code>const</code>, una adecuada correctitud de constantes dicta que todas las variables u objetos deben ser declarados constantes a no ser que exista intención de modificarlos. Este uso pro-activo de <code>const</code> hace que los valores sean "más fáciles de entender, rastrear y razonar sobre ellos"<ref>[[Herb Sutter]] y [[Andrei Alexandrescu]] (2005). ''C++ Coding Standards''. p. 30. Boston: Addison Wesley. ISBN 0-321-11358-6</ref> además de mejorar la legibilidad y comprensión del código facilitando las tareas del equipo encargado del mantenimiento del código ya que el propio código muestra la intención de uso de cada valor.▼
▲En C y otros lenguajes derivados, todos los tipos de datos
===Tipos de datos simples===▼
Para tipos de datos simples (excepto punteros), el calificador <code>const</code> puede situarse en ambos lados del tipo (es decir, <code>const char foo = 'a';</code> equivale a <code>char const foo = 'a';</code>). En algunos compiladores usar <code>const</code> en ambos lados del tipo (por ejemplo, <code>const char const</code>) genera una advertencia pero no un error.▼
▲=== Tipos de datos simples ===
La flexibilidad para situar el calificador <code>const</code> existe por razones históricas,<ref>Preguntas frecuentes sobre C++ por [[Bjarne Stroustrup]] http://www.stroustrup.com/bs_faq2.html#constplacement</ref> el C y C++ previo a la estandarización imponía pocas o ninguna regla de ordenación en los calificadores de tipo, dado que usar el calificador antes o despues del tipo no provoca ambigüedades, se decidió no desarrollar una regla de ordenación para este caso.▼
▲Para tipos de datos simples
===Punteros y referencias===▼
El significado de <code>const</code> es más complicado para [[Puntero (informática)|puntero]]s y [[Referencia (informática)|referencia]]s (tanto el puntero como el dato apuntado, incluso ambos, pueden ser calificados con <code>const</code>). Además, la sintaxis puede ser confusa. Pueden declararse punteros constantes que apunten a datos no constantes, o punteros modificables que apunten a datos no modificables, o punteros constantes a valores constantes. No se puede cambiar el dato al que apunta un puntero constante, pero puede modificarse el dato apuntado. Por el contrario, puede modificarse el dato al que apunta un puntero constante (que debe ser un dato del mismo tipo o un tipo convertible al del puntero), pero no puede modificarse el valor apuntado a través del mismo. Finalmente, puede declararse un puntero constante a un dato constante, el cuál no puede cambiarse el dato al que apunta ni modificar el valor del dato apuntado a través del mismo. El siguiente ejemplo ilustra estos matices:▼
▲La flexibilidad para situar el calificador <code>const</code> existe por razones históricas
▲=== Punteros y referencias ===
▲El significado de <code>const</code> es más complicado para [[Puntero (informática)|
<source lang=c>
Línea 72 ⟶ 73:
}</source>
Según las convenciones de C para declaraciones, la declaración sigue al uso, por lo que escribir <code>*</code> sobre un puntero indica su desreferenciación. Así pues, en la declaración <code>int *puntero</code>, al desreferenciar el puntero <code>*puntero</code> se obtiene <code>int</code>, mientras que <code>puntero</code> es un puntero a <code>int</code>. En consecuencia, <code>const</code> modifica el identificador a su derecha.
Sin embargo, las convenciones de C++ asocian el <code>*</code> con el tipo, como en <code>int* puntero</code> y <code>const</code> modifica el tipo a la izquierda. <code>int const * punteroAConstante</code> puede leerse como
<source lang=c>int *puntero; // *puntero es un valor int
Línea 85 ⟶ 86:
Según la convención de C++ de analizar el tipo, no el valor, la [[rule of thumb|regla general]] es leer la declaración de derecha a izquierda. Así pues, todo lo que quede a la izquierda del [[asterisco]] pertenece al tipo apuntado y aquello a la derecha del mismo pertenece a las propiedades del puntero. En el anterior ejemplo, <code>int const *</code> puede ser interpretado como un puntero de sólo lectura que apunta a un entero de lectura-escritura.
También está permitido situar <code>const</code> a la izquierda del tipo en C y C++, como en la siguiente sintaxis:
<source lang="cpp">const int* punteroAConst; // identico a: int const * punteroAConst
Línea 97 ⟶ 98:
const int* const punteroConstanteAConst;</source>
Las [[Referencia (informática)|referencias]] de C++ siguen normas similares. Declarar una referencia <code>const</code> es redundante, ya que no es posible hacer que una referencia apunte a otro objeto:
<source lang=cpp>int i = 22;
int const & referenciaAConst = i; // Correcto
int & const referenciaConstante = i; // Error, el "const" es redundante</source>
Se pueden obtener declaraciones realmente complicadas usando [[array|vectores]] multidimensionales y referencias
=== Parámetros y variables ===
<code>const</code> puede ser usado tanto en parámetros de función como en variables ([[Variable estática|estáticas]] o automáticas, incluyendo globales o locales). La interpretación varía entre usos. Una variable <code>const</code> estática (variable global o variable estática local) es una constante, y debe usarse para representar datos como constantes matemáticas, por ejemlo: <code>const double PI = 3.14159</code> o parámetros generales en tiempo de compilación. Una variable <code>const</code> automática (variable local no estática) debe ser [[inicialización|inicializada]], aunque puede usarse un valor diferente en cada llamada, por ejemplo <code>const int x_al_cuadrado = x*x;</code>. Un parámetro pasado como referencia <code>const</code> indica que el valor referenciado no se modificará (forma parte del [[Diseño por contrato (informática)|contrato]]). Por ello, se suele favorecer el uso de <code>const</code> en parámetros pasados por referencia pero no en los parámetros pasados por valor.▼
▲<code>const</code> puede ser usado tanto en parámetros de función como en variables
===Métodos===▼
Para aprovechar el diseño por contrato en tipos definidos por el usuario (estructuras y clases), que pueden tener tanto métodos como campos, el programador debe marcar los métodos de instancia como <code>const</code> si no tiene intención de modificar los campos del objeto. Usar el calificador <code>const</code> sobre los métodos de instancia que lo requieran es esencial para cumplir con la correctitud de constantes, aunque este tipo de correctitud no esté disponible en otros lenguajes de [[Programación orientada a objetos|programación orientada a objetos]] como [[Java (lenguaje de programación)|Java]] y [[C Sharp|C#]] o en la [[interfaz de línea de comandos|CLI]] de [[Microsoft]] o en las [[Managed Extensions for C++]].▼
▲=== Métodos ===
Los métodos calificados con <code>const</code> pueden ser llamados desde objetos constantes y no constantes indistintamente mientras que los métodos sin calificación <code>const</code> sólo pueden llamarse desde objetos no constantes.▼
▲Para aprovechar el diseño por contrato en tipos definidos por el usuario
El calificador <code>const</code> aplicado sobre un método de instancia afecta al objeto apuntado por el puntero <code>this</code>, que es un argumento implícito pasado a todos los métodos de instancia. Por lo tanto, los métodos constantes es la manera de aplicar la correctitud de constantes al parámetro implícito "<code>this</code>". Por ejemplo:▼
▲Los métodos calificados con <code>const</code> pueden ser llamados desde objetos constantes y no constantes indistintamente, mientras que los métodos sin calificación <code>const</code> sólo pueden llamarse desde objetos no constantes.
▲El calificador <code>const</code> aplicado sobre un método de instancia afecta al objeto apuntado por el puntero <code>this</code>, que es un argumento implícito pasado a todos los métodos de instancia. Por lo tanto, los métodos constantes
<source lang="cpp">class C
Línea 135 ⟶ 138:
</source>
En el ejemplo anterior, el puntero implícito
Es posible declarar un método con el mismo nombre pero con diferente calificación <code>const</code>
<source lang="cpp">
Línea 157 ⟶ 161:
</source>
La calificación <code>const</code> del objeto determina qué versión de <code>MiVector::Get()</code> será llamada, y si se obtendrá una referencia que pueda ser modificada o de sólo lectura.
Técnicamente, ambos métodos tienen diferentes [[firma___busca (informática)|firmas]], ya que sus punteros
=== Excepciones a la correctitud de constantes ===
La primera excepción, tan sólo aplicable a C++, es el uso de <code>const_cast</code>, que permite eliminar la calificación <code>const</code> de un dato, haciéndolo modificable. La necesidad de eliminar la calificación <code>const</code> surge del uso de [[código heredado]], o de [[Biblioteca (informática)|bibliotecas]] que no pueden cambiarse pero que no cumplen con la correctitud de constantes. Por ejemplo:
<source lang="cpp">
Línea 183 ⟶ 188:
En el ejemplo anterior, si el puntero <code>ptr</code> apunta a una variable global, local, o campo calificado con <code>const</code>, o a un objeto creado dinámicamente mediante <code>new const int<code>, el código sólo será correcto si la función <code>LibraryFunc</code> realmente no modifica el valor apuntado por <code>ptr</code>.
Existe una excepción{{Citation needed|reason=no está claro por qué es una excepción - podría ser considerado como una característica del lenguaje|date=February 2013}} que se aplica tanto a C como a C++:
<source lang="cpp">
Línea 202 ⟶ 207:
</source>
Aunque el objeto <code>e</code> pasado a <code>Foo()</code> sea constante,
Por este motivo, se ha argumentado que la calificación por defecto para punteros y referencias miembro debe ser una correctitud de constantes más profunda, pudiendo modificar el comportamiento por defecto con el calificador <code>mutable</code> cuando el dato apuntado no pertenezca al objeto contenedor, pero aplicar este cambio crearía problemas de compatibilidad con código existente.
La anterior excepción puede ser corregida usando una clase que oculte el puntero tras una interfaz que cumpla con la correctitud de constantes
Finalmente, varias funciones en la [[Biblioteca estándar de C|biblioteca estándar de C]] no cumplen con la correctitud de constantes, dado que reciben punteros <code>const</code> a cadenas de caracteres y
Algunas [[Implementación|implementaciones]] de la
===
El cualificador <code>volatile</code> de C y C++, indica que un objeto puede ser cambiado externamente en cualquier momento por medios ajenos al programa y por lo tanto debe volverse a leer de la memoria cuando se accede a él.▼
Este calificador se suele encontrar en código que manipula [[hardware]] directamente (en [[Sistema_embebido|sistemas embebidos]] y [[Driver|controladores de dispositivos]]) y en aplicaciones [[Thread|multihilo]] (aunque se suele usar de manera incorrecta en este contexto{{Citation needed|reason=harían falta ejemplos|date=August 2013}}).▼
▲El cualificador <code>volatile</code> de C y C++
<code>volatile</code> se puede usar de la misma manera que <code>const</code> en declaraciones de variables, punteros, referencias y métodos, de hecho <code>volatile</code> es usado en ocasiones para implementar estrategias de diseño por contrato que [[Andrei Alexandrescu]] denomina correctitud de volátiles,<ref>[http://www.drdobbs.com/cpp/184403766 "Generic<Programming>: volatile — Multithreaded Programmer's Best Friend Volatile-Correctness or How to Have Your Compiler Detect Race Conditions for You"] por Andrei Alexandrescu en ''[[C/C++ Users Journal]]'' Foro de expertos C++</ref> aunque es mucho menos común que la correctitud de constantes. El calificador <code>volatile</code> también puede ser eliminado mediante <code>const_cast</code>, y puede combinarse con el calificador <code>const</code> como puede verse en este ejemplo:▼
▲Este calificador se suele encontrar en código que manipula [[hardware]] directamente
▲<code>volatile</code> se puede usar de la misma manera que <code>const</code> en declaraciones de variables, punteros, referencias y métodos
<source lang="cpp">// Configura una referencia a un registro de hardware de solo lectura
Línea 228 ⟶ 234:
Dado que <code>registroDeHardware</code> es <code>volatile</code>, aunque el programador no pueda modificar su valor, no existen garantías de que mantenga los mismos datos en lecturas sucesivas. Las semánticas de esta variable indican que es de sólo lectura pero no inmutable.
== <code>const</code> e <code>immutable</code> en D ==
En la segunda versión del [[D (lenguaje de programación)|lenguaje D]], exiten dos [[Palabra reservada|palabras reservadas]] relacionadas con la correctitud de constantes
La palabra reservada <code>const</code> se refiere a una referencia inmutable de un dato mutable. ▼
* la palabra reservada <code>immutable</code> denota un dato que no puede ser modificado a través de ninguna referencia;
Al contrario que el <code>const</code> de C++, <code>const</code> e <code>immutable</code> de D son [[relación transitiva|transitivos]], y cualquier dato alcanzable a través de <code>const</code> o <code>immutable</code> es <code>const</code> o <code>immutable</code> respectivamente.▼
▲
▲Al contrario que el <code>const</code> de C++, <code>const</code> e <code>immutable</code> de D son [[relación transitiva|transitivos]], y cualquier dato alcanzable a través de <code>const</code> o <code>immutable</code> es <code>const</code> o <code>immutable</code>, respectivamente.
▲'''Ejemplo de const e immutable en D'''
<source lang = "D">int[] foo = new int[5]; // foo es mutable.
const int[] bar = foo; // bar apunta a foo de manera inmutable.
Línea 242 ⟶ 252:
int[] mutableNums = nums; // Error: No se puede crear una referencia mutable a un dato inmutable.</source>
<source lang = "D">class Foo {
Foo next;
Línea 253 ⟶ 264:
== <code>final</code> en Java ==
En [[Java (lenguaje de programación)|Java]], el calificador <code>final</code> indica que el campo o variable no es asignable
<source lang="java">final int i = 3;
i = 4; // Error! No se puede modificar un objeto "final"</source>
Línea 264 ⟶ 276:
Respecto a los punteros, una referencia <code>final</code> en Java tiene un significado similar a un puntero constante en C++.
<source lang="cpp">Foo *const bar = direccion_de_memoria; // puntero constante</source>
En el ejemplo anterior, <code>bar</code> debe ser inicializado en el momento de la declaración y no puede cambiar su valor en adelante, pero el valor al que apunta
<source lang="java">final Foo i; // una declaracion Java</source>
También se puede declarar un puntero a datos de
<source lang="cpp">const Foo *bar;</source>
En el ejemplo anterior, <code>bar</code> puede modificarse para que apunte a cualquier dato de tipo <code>Foo</code>; sin embargo el valor apuntado no podrá ser modificado mediante el puntero <code>bar</code>. No existe un mecanismo equivalente en Java. Así pues, tampoco existen métodos <code>const</code>.
No se puede forzar la correctitud de constantes en Java
Los métodos en Java pueden ser declarados como
▲Los métodos en Java pueden ser declarados como "<code>final</code>", pero este tipo de declaración no tiene relación con la correctitud de constantes sino con la herencia (significa que el método no puede ser [[Sobreescritura de Métodos|sobreescrito]] en clases derivadas). Curiosamente, el lenguaje Java marca <code>const</code> como palabra reservada (no puede usarse como nombre de variable) pero no le asocia semántica alguna.
== Código <code>const</code> y <code>readonly</code> en C# ==▼
▲Se reservó esta palabra clave para desarrollar una extensión del lenguaje Java que incluyese métodos <code>const</code> y punteros a tipos <code>const</code> al estilo C++{{Citation needed|date=February 2011}}. Existe una petición para implementar correctitud de constantes en [[Java Community Process|el Proceso de la Comunidad Java]], pero fue cerrada en 2005 indicando que es imposible implementar dicho cambio de manera que sea retrocompatible.<ref>[http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4211070 Ticket for adding const parameters in Java]</ref>
En [[C_Sharp|lenguaje C#]], el calificador <code>readonly</code> tiene el mismo efecto sobre campos que el calificador <code>final</code> de Java y el calificador <code>const</code> de C++; el calificador <code>const</code> en C# tiene un efecto similar al <code>#define</code> de C++.
▲==Código <code>const</code> y <code>readonly</code> en C#==
▲En C#, el calificador <code>readonly</code> tiene el mismo efecto sobre campos que el calificador <code>final</code> de Java y el calificador <code>const</code> de C++; el calificador <code>const</code> en C# tiene un efecto similar al <code>#define</code> de C++ (El efecto inhibidor de herencia que Java aplica con el calificador <code>final</code> sobre métodos, es equivalente al calificador <code>sealed</code> de C#).
El contrario que C++, C# no permite calificar métodos y parámetros con <code>const</code>. Sin embargo, también se pueden utilizar parámetros de sólo lectura
== Referencias ==
{{listaref}}
[[Categoría:Variables (programación)]]
[[Categoría:Lenguaje de programación C]]
[[
[[Categoría:Artículos con códigos de ejemplo]]
|