Disponible la nueva versión "donationware" 7.3 de OrganiZATOR
Descubre un nuevo concepto en el manejo de la información.
La mejor ayuda para sobrevivir en la moderna jungla de datos la tienes aquí.

Curso C++

[Home]  [Inicio]  [Índice]


4.1.8c  static

§1  Sinopsis

La característica de las variables automáticas ( 4.1.8a) de perder su valor al salir del bloque en que han sido definidas, es un serio inconveniente en algunas ocasiones. Para resolver el problema se inventaron las variables estáticas, un tipo especial de variable que no fuese destruida cuando la ejecución saliese de su ámbito y que conservase su valor.  Este nuevo tipo se declara mediante el especificador de tipo de almacenamiento static (una palabra-clave C++), con lo que se previene que una variable pierda su valor cuando se sale del bloque en que se ha definido.  Por ejemplo, entre llamadas sucesivas a una función.  Sin embargo, como veremos a continuación, static puede aplicarse tanto a variables como a funciones e incluso a miembros de clases.

§2  Sintaxis:

static <definición-de-dato> ;
static <nombre-de-función> <definición-de-función> ;

Ejemplos:

static int i;
static void printnewline(void) { /* ... */ }


Dependiendo del lugar en que se aplique, las entidades static pueden ser globales (externas) o locales. El primer caso es cuando se aplica a entidades del espacio global de un fichero (pueden ser variables o funciones), el segundo cuando se aplica dentro del cuerpo de una función (es evidente que aquí no puede aplicarse a funciones).

Desafortunadamente, el especificador static tiene dos significados distintos en C++ según que la entidad sea global o local. En cualquier caso confiere al objeto (que suponemos es una variable) la propiedad antes señalada de ser persistente. Precisamente decimos que es un especificador de almacenamiento porque, para hacerlas persistentes, el compilador sitúa estas variables en una zona especial del segmento de datos ( 1.3.2).

Hay que advertir que desde el punto de vista de la persistencia, la aplicación de static a entidades globales sería superfluo, ya que "por definición", las entidades del espacio global de una unidad de compilación son persistentes, de forma que los apelativos "global", "externo", "persistente" o "duración estática" aplicados a un objeto significan lo mismo.  Sin embargo ocurre que la aplicación de static sobre objetos globales tiene además el efecto de limitar su ámbito, de forma que en esta nueva faceta static es un especificador de ámbito. (ver una exposición más detallada en 4.1.8d)

§3.1  Estática local

Una variable estática local actúa como una variable local en cuanto a visibilidad, pero como una externa en cuanto a duración. Es decir, solo son conocidas en la función o bloque de código en el que se declaran, pero conservan su último valor entre llamadas sucesivas a la función. Su existencia es muy útil en C++, pues permite la existencia de rutinas independientes que conserven ciertos valores entre llamadas. "Recuerdan" cual era su valor la última vez que se invocó la función.

Ejemplo:

int func (int n, int b = 0)  {
   static int suma = 0;
   if (!n ) return suma;
   return (suma += b);
}

§3.2  Estática global

Cuando se aplica el modificador static a una variable global se indica al compilador que cree una variable global que será conocida únicamente en el archivo en que se declara, de forma que las funciones de otros archivos no las reconocerán ni podrán alterar su valor.  Dicho en otras palabras: significa que la variable tendrá enlazado interno ( 1.4.4).

Es inmediato deducir que esta propiedad del especificador static está fuera de contexto, ya que se refiere a la "visibilidad" en vez de a la "permanencia" del objeto (esta característica es una desafortunada herencia del C). En realidad, la declaración de static sobre una variable global debería ser simplemente redundante, ya que por definición, las variables globales de un fichero son de duración estática.

Consciente de esta dificultad, la última versión del Estándar (Julio 1998) ha desaconsejado ("Deprecate") la utilización de static como especificador de ámbito.  En su lugar, cuando se desee limitar la visibilidad de un identificador del espacio global de un fichero al ámbito de este, se aconseja utilizar un subespacio anónimo ( 4.1.11b).

Ejemplo:

// Utilización antigua
   static int x = 10;
   static void func () { /* .... */ }
 
// Forma aconsejada
namespace {
  int x = 10;
  static void func () { /* .... */ }
}

Ver comentarios adicionales sobre esta cuestión en: ( 2.2.6 El concepto static)


Recordemos que en C++ las funciones normales (que no son miembros de clases) son globales al fichero, por lo que su declaración como static supone que solo serán conocidas en el fichero en que se hayan declarado.  La función tiene entonces enlazado interno y por tanto cualquier función con el mismo nombre en otro fichero es una entidad distinta.

Por contra, en ausencia de este modificador, la existencia de dos funciones iguales en dos módulos distintos origina una colisión (en el espacio general de nombres 4.1.11) con el consiguiente error de compilación. Pero recuerde que debido a la posibilidad de sobrecarga ( 4.4.1), para que dos funciones sean iguales en C++, deben tener no solo el mismo nombre, también el mismo tipo y número de argumentos. Sin estas condiciones no existe colisión porque las funciones son consideradas distintas.

§4  El especificador static en clases

Las funciones, así como las propiedades y métodos de clases también pueden ser declarados estáticos.  Tales miembros tienen propiedades especiales ( 4.11.7).

Nota:  como puede verse en el citado capítulo 4.11.7, la utilización del especificador static con miembros de clases no tiene ninguna relación con el que hemos explicado aquí (especificador de ámbito local o global). Se trata de otro desafortunado caso de "sobrecarga" de una palabra-clave (o un operador), que es origen de bastante desconcierto inicial en el principiante; cierta dificultad añadida al aprendizaje del idioma y ácidas críticas por parte de sus detractores, al extremo de que alguno ha llegado a referirse al asunto como esquizofrénico ("Statics: Schizophrenia for C++ Programmers" de G. Bowden Wise).