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.4 Visibilidad

§1 Sinopsis

La visibilidad de un identificador es la región de código fuente desde la que se puede legalmente acceder al objeto asociado al identificador. Ámbito y visibilidad coinciden generalmente, si bien pueden darse circunstancias en que un objeto puede aparecer oculto (invisible) temporalmente debido a la presencia de un identificador duplicado. El objeto existe, pero el identificador original no puede ser utilizado para accederlo hasta que el identificador duplicado es terminado.

Nota: la visibilidad no puede exceder al ámbito, pero este puede exceder a la visibilidad.

§2 Lo señalado en la página anterior respecto al ámbito ( 4.1.3) significa que también hay siete categorías para la visibilidad de un identificador: sentenciabloque (o local); función; prototipo de función; fichero; clase y espacio de nombres. Sin embargo, los más importantes y usuales son: de función; de fichero (global), y de programa.

Ejemplo:

  ...
{
  int i; char ch;  // auto por defecto
  i = 3;           // int i y char ch, en ámbito y visibles
   ...
  {
     double i;
     i = 3.0e3;    // double i en ámbito y visible
                   // int i=3 en ámbito pero oculto
     ch = 'A';     // char ch en ámbito y visible
  }                // double i es terminada aquí
                   // double i fuera de ámbito
  i += 1;          // int i visible, i == 4
   ...
// char ch todavía en ámbito y visible (ch = 'A')
} // int i y char ch son terminados aquí
   ...
// int i y char ch fuera de ámbito


Respecto a este asunto de la visibilidad, veremos que se aplican reglas especiales para los nombres de clases y miembros ocultos de clase. Bajo ciertas condiciones, los operadores de acceso permiten acceder identificadores ocultos cuando son miembros de clase.

§3 Variables locales

Las variables locales o de bloque, tienen visibilidad dentro del bloque, desde el punto de declaración ( 4.1.3) hasta el final del mismo. De este tipo son las variables automáticas, incluyendo los parámetros formales de las funciones. Ocultan cualquier otra variable o función externas del mismo nombre. Por ejemplo:

int x, y;
func(double x) {
  double y;    // oculta a int y
   ...         // double y visible desde aquí
 
}   // fin de visibilidad de double y

Ver también 4.1.3 Ocultación.

§4 Variables globales

Las variables globales a un fichero se declaran fuera de cualquier bloque, función o clase. Sintácticamente la declaración es idéntica que la de las variables locales, solo cambia la situación de la declaración. El hecho de colocarlas al principio evita tener que hacerlas visibles dentro de cada función con una declaración extern de cada variable ( 4.1.8d). La regla es:

Si la declaración de una variable externa ocurre antes que su uso en alguna función particular, entonces no hay necesidad de una declaración extern de la variable dentro de la función.

 Ejemplo:

extern x;      // punto de declaracón de x
...
void func1(int y) {
  x = x+y;     // correcto x es visible
}
 
void func2(int y) {
  z = z+y;     // incorrecto z no es visible
  extern z;
  z = z+y;     // correcto z es ahora visible
}


§4.1 El ámbito de una variable global es desde el punto de declaración hasta el final del fichero, por lo que tradicionalmente se suelen declarar al principio, junto con los prototipos de las funciones, ya que en caso contrario hay que declararlas dentro de cada función que las invoque (avisar a cada función que la variable en cuestión es externa).

Puesto que C++ no permite declaración de funciones dentro de funciones [1], sus identificadores son globales al fichero en que se han declarado (las funciones tienen ámbito global). Lo que sí se permite son prototipos de funciones dentro de otras funciones que las invocan (los prototipos son declaraciones, no definiciones).

Por supuesto, si las variables globales a un fichero deben ser vistas desde otros ficheros, es necesario declararlas al principio como extern (en los otros ficheros). Por esta razón y por comodidad, se acostumbra a agrupar todas las declaraciones de variables y funciones externas en unos ficheros que actúan como "repositorios" de declaraciones y definiciones que son incluidos mediante #include ( 4.9.10g) al principio de cada fuente (así no se olvida ningún "extern"). Por esta razón tales ficheros se denominan "de cabecera".

Nota:  por una larga tradición de C, las declaraciones de las funciones de las Librerías Estándar ( 5) se agrupan en una serie de ficheros de nombres conocidos, de los que los correspondientes a las librerías que se mantienen por compatibilidad con el antiguo C tienen la terminación .h, de "Header" (cabecera en inglés).


Por defecto, las variables externas y las funciones tiene la propiedad de que todas las referencias a sus nombres (incluso desde módulos compilados separadamente), referencian a la misma entidad, es decir, tienen enlazado externo ( 1.4.4).


§4.2 Como se verá a continuación, todas las variables globales a un fichero y por este simple hecho, tienen duración estática.

Nota: aunque desde cierta óptica, el empleo de variables globales facilita algunas cosas. Por ejemplo, hay que pasar menos parámetros a las funciones, es mala práctica abusar de ellas, los programas se hacen difíciles de manejar e interpretar y existe más posibilidad de colisiones de nombres (decimos que se "poluciona" el espacio global). Es preferible el estilo en que todos los datos que se necesitan en una función están definidos dentro del cuerpo o en su lista de parámetros.


§4.3 No olvidar que una variable global declarada static ( 4.1.8c) solo es visible desde el punto de declaración hasta el final del fichero y solo en ese fichero. Esto es también de aplicación para las funciones.

  Inicio.


[1] Precisamente, la introducción de objetos en C++, que permite englobar juntas variables y funciones, viene a paliar en cierta forma esta limitación.