2012-04-22 11 views

Respuesta

66

En C++, cada nombre tiene su alcance fuera de lo cual no existe. Un ámbito se puede definir de muchas maneras: puede ser definido por espacio de nombres , funciones, clases y simplemente {}.

Por lo tanto, un espacio de nombre, global o de otro tipo, define un ámbito. El espacio de nombres global se refiere al uso de ::, y se dice que los símbolos definidos en este espacio de nombres tienen alcance global. Un símbolo, por defecto, existe en un espacio de nombres global, a menos que se define dentro de un bloque comienza con la palabra clave namespace, o es un miembro de una clase, o una variable local de una función:

int a; //this a is defined in global namespace 
     //which means, its scope is global. It exists everywhere. 

namespace N 
{ 
    int a; //it is defined in a non-global namespace called `N` 
      //outside N it doesn't exist. 
} 
void f() 
{ 
    int a; //its scope is the function itself. 
      //outside the function, a doesn't exist. 
    { 
     int a; //the curly braces defines this a's scope! 
    } 
} 
class A 
{ 
    int a; //its scope is the class itself. 
      //outside A, it doesn't exist. 
}; 

También tenga en cuenta que un nombre se puede ocultar por el ámbito interno definido por espacio de nombres, función o clase. Por lo tanto, el nombre a dentro del espacio de nombres N oculta el nombre a en el namspace global. De la misma manera, el nombre en la función y clase oculta el nombre en el espacio de nombres global. Si se enfrenta a esta situación, entonces se puede utilizar para referirse a ::a el nombre definido en el espacio de nombres global:

int a = 10; 

namespace N 
{ 
    int a = 100; 

    void f() 
    { 
     int a = 1000; 
     std::cout << a << std::endl;  //prints 1000 
     std::cout << N::a << std::endl; //prints 100 
     std::cout << ::a << std::endl; //prints 10 
    } 
} 
+0

¿Qué deberíamos hacer si queremos acceder a 'a' (definido en los espacios de nombre N) dentro de la función void f() {} – rimiro

+0

@rimiro: Si 'a' se declara en un alcance de función, no puede acceder desde * fuera * de la función. – Nawaz

2

Cuando se declara una variable global int i por ejemplo, decimos i is in the global namespace y has the global namespace scope. Eso es todo.

Extracto de C++ 03:

3.3.5 Namespace scope 

    The outermost declarative region of a translation unit is also a namespace, called 
    the global namespace. A name declared in the global namespace has global namespace 
    scope (also called global scope). 
4

"Ámbito" es un término más general que el "espacio de nombres". Cada bloque de espacio de nombres, clase y código define un ámbito en el que se pueden usar los nombres declarados en su interior; un espacio de nombres es un contenedor para nombres declarados fuera de clases y funciones.

"Ámbito global" y "espacio de nombre global" pueden usarse de manera más o menos intercambiable; el alcance de un nombre declarado en un espacio de nombres cubre la totalidad de ese espacio de nombres. Use "espacio de nombres" si se refiere específicamente al espacio de nombres, y "alcance" si se refiere a la visibilidad de los nombres que contiene.

3

El alcance denota la vida útil de un objeto, puede tener una variable global que existirá mientras el programa se ejecute, o puede tener una variable con un alcance de bloque que exista siempre que se ejecute ese bloque de código. Considere este ejemplo:

#include <iostream> 

int a = 100; 

main() { 
    int a = 200; 

    std::cout << "local a is: " << a << std::endl; 
    std::cout << "global a is: " << ::a << std::endl; 

    return 0; 
} 

Cuando ejecuta la instrucción imprimirá local a is: 200, que se espera, obviamente, porque estamos redefiniendo a en main que deja en el ámbito de que está encerrando bloque. También imprimimos el ::a global que nuevamente imprime el valor esperado 100, porque hemos solicitado el espacio de nombres global ::.

Una semántica de espacio de nombres es en su mayoría lógica, es una forma de aislar simbiosis entre sí, con la esperanza de evitar conflictos de nombres, no afecta la vida útil de un objeto.

El alcance, por otro lado, denota la vida útil de un objeto, el a global surgió antes que el a local porque se construye mucho antes de que se ejecute main. Sin embargo, el alcance también fuerza un espacio de nombre en el símbolo, pero no de la misma manera que lo hace un namespace. Hay diferentes tipos de ámbitos, global, class, function, block, file etc ...

La parte confusa es que alcance a veces sobrecargado para indicar la visibilidad de un símbolo en particular, que es algo tomado de C, donde la noción de espacios de nombres no existía y el alcance se usaba para denotar tanto la vida útil como la visibilidad. En C++, sin embargo, las reglas cambiaron un poco, pero el término alcance se sigue utilizando de la misma manera porque los dos idiomas comparten una gran cantidad de conceptos.

+0

Es bueno que haya resaltado la idea de que un alcance es inherente a la duración de un objeto. –

2

@Dmitriy Ryajov

El tema es un poco viejo pero quiero ofrecer mi ayuda en esto. Creo que no deberías hacer las cosas más complicadas de lo que realmente son. Scope de un identificador es la parte de un programa de computadora donde el identificador, un nombre que se refiere a alguna entidad en el programa, se puede usar para encontrar la entidad referida. Entonces, el alcance del término solo se aplica a los identificadores y no deberíamos mezclarlo con la duración del objeto. Están un tanto conectados, pero no deberían mezclarse. La vida del objeto se denota por donde asignamos la memoria para ese objeto. Entonces, por ejemplo, si se asigna una memoria en la pila, se liberará tan pronto como la función termine. Entonces depende de dónde almacenamos el objeto y eso denota su duración. El alcance solo dice: "Aquí hay un nombre para un objeto y podemos usar este nombre para el objeto hasta ese momento". Entonces, como dije, el término scope es solo para identificadores de los objetos y la duración es otra cosa que se denota por el lugar donde almacenamos el objeto.

Además, quiero decir algo sobre linkage que está estrechamente relacionado con esto. Esto también puede ser a veces confuso. Digamos que tenemos algunos identificadores en el translation unit que se refieren a algunos objetos. Si los mismos identificadores en la unidad de traducción other se referirán a las mismas entidades se denota mediante el enlace. Entonces, por ejemplo, si un identificador tiene un enlace externo, podemos referirnos a la entidad a la que se refiere este identificador pero desde otra unidad de traducción al declararlo con la palabra clave extern. Ahora, digamos que no queremos usar esa entidad en otras unidades de traducción. Entonces, la entidad va a exist hasta que el programa termine pero cuando no lo declaramos, no podremos referirnos a él. También tenga en cuenta que ahora he mezclado los términos vinculación y duración. Pero esto se debe a que solo las entidades global tienen enlaces externos. Un identificador dentro de una función no se puede referir a las otras partes del programa.

Conclusión: siempre trate de mantener las cosas simples. Me sorprendió cómo diferentes personas hablan sobre estos términos de manera diferente. Todo el proceso de compilación por separado es confuso, porque hay varios términos que tienen casi el mismo significado y probablemente todos se quedarán estancados en este punto.

Cuestiones relacionadas