J'ai vu des utilisations de ces deux expressions: portée globale et espace de noms global. Quelle est la différence entre eux?
Réponses
Trop de publicités?En C++, chaque nom a son champ d'application en dehors de laquelle il n'existe pas. Un champ peut être défini de plusieurs façons différentes : il peut être défini par l'espace de noms, fonctions, classes et juste { }.
Si un espace de noms global ou autrement, définit un champ d'application. L'espace de noms global se rapporte à l'utilisation d' ::
, et les symboles définis dans cet espace de noms sont dit d'avoir une portée globale. Un symbole, par défaut, existe dans un espace de noms global, sauf si elle est définie à l'intérieur d'un bloc commence avec le mot-clé namespace
, ou c'est un membre d'une classe, ou une variable locale d'une fonction:
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.
};
Notez également qu'un nom peut être dissimulé par l'intérieur de la portée définie par l'espace de noms, de la fonction ou de la classe. Ainsi, le nom de l' a
à l'intérieur de l'espace de noms N
cache le nom de l' a
dans le global namspace. De la même manière, le nom de la fonction et de la classe cache le nom de l'espace de noms global. Si vous faites face à une telle situation, vous pouvez utiliser ::a
de mentionner le nom défini dans l'espace de noms 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
}
}
"Portée" est un terme plus général que "espace de noms". Chaque espace de noms, la classe et le bloc de code définit un cadre dans lequel des noms déclarés à l'intérieur, il peut être utilisé; un espace de noms est un conteneur pour les noms déclarés à l'extérieur des classes et des fonctions.
"De portée mondiale" et "espace de noms global" peut être utilisé plus ou moins indifféremment; la portée d'un nom déclaré dans un espace de noms couvre l'ensemble de cet espace de noms. Utiliser "espace de noms" si vous êtes en se référant expressément à l'espace de noms, et la "portée" si vous faites allusion à la visibilité des noms à l'intérieur.
Par exemple, lorsque vous déclarez une variable globale int i
, on dit i is in the global namespace
et has the global namespace scope
. C'est tout.
Extrait 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).
La portée indique la durée de vie d'un objet, vous pouvez avoir une variable globale qui existera aussi longtemps que votre programme s'exécute, ou vous pouvez avoir une variable avec un bloc de portée qui existera tant que le bloc de code est exécuté. Considérons cet exemple:
#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;
}
Lors de l'exécution de l'instruction imprimer local a is: 200
, ce qui devrait évidemment, puisque nous sommes redéfinir a
en main
ce qui laisse le champ d'application de son bloc enfermant. Nous avons également imprimer le global ::a
qui imprime de nouveau la valeur de 100, parce que nous avons demandé pour l'espace de noms global ::
.
Un espace de noms sémantique est surtout logique, c'est une façon d'isoler symblos l'un de l'autre, dans l'espoir d'éviter les collisions de noms, il n'affecte pas la durée de vie d'un objet.
La portée, d'autre part, indique la durée de vie d'un objet, le global a
vu le jour avant l' a
parce qu'il se construit beaucoup plus tôt que le principal est exécuté. Toutefois, la portée aussi les forces d'un espace de noms sur le symbole, mais pas de la même façon qu'un namespace
n'. Il existe différents types de sondes, global
, class
, function
, block
, file
etc...
La confusion, c'est que la portée est parfois surchargé pour désigner la visibilité d'un symbole particulier, qui est quelque chose d'emprunté à partir de C, où la notion d'espaces de noms n'existaient pas et la portée a été utilisé pour désigner à la fois, la durée de vie et de la visibilité. En C++, cependant, les règles ont un peu changé,mais le terme de champ d'application est encore utilisée de la même façon, parce que les deux langues partagent un grand nombre de concepts.
@Dmitriy Ryajov
Le sujet est un peu vieux, mais je tiens à offrir mon aide à ce sujet. Je pense que vous ne devriez pas faire des choses plus compliquées qu'elles ne le sont vraiment. Scope
d'un identificateur est la partie d'un programme d'ordinateur où l'identifiant, un nom qui fait référence à une entité dans le programme, peut être utilisé pour trouver de l'entité. Ainsi, le terme ne s'applique qu'à des identificateurs et il ne faut pas le mélanger avec la durée de vie de l'objet. Ils sont un peu liés, mais ne doivent pas être confondus. La durée de vie de l'objet est désigné par où nous allouer la mémoire pour un objet. Ainsi, par exemple, si une mémoire est alloué sur la pile, il sera libérée dès que la fonction se termine. Donc, cela dépend de là où nous stockons l'objet et qui dénote de sa durée de vie. La portée seulement dit: "Ici, c'est un nom pour un objet et nous pouvons utiliser ce nom pour l'objet jusqu'alors, et alors". Donc, comme je l'ai dit, le terme scope
seulement pour les identificateurs des objets et de la durée de vie est quelque chose d'autre qui est dénoté par le lieu de stockage de l'objet.
En outre, je veux dire quelque chose à propos de linkage
qui est étroitement lié à ce. Ce peut être aussi parfois source de confusion. Disons que nous avons des identificateurs dans l' translation unit
que de se référer à certains objets. Si les mêmes identifiants other
de l'unité de traduction fera référence à la même entité est désignée par le lien. Ainsi, par exemple, si un identificateur a une liaison externe, nous pouvons nous référer à l'entité que ce symbole fait référence à mais provenant d'une autre unité de traduction par déclarer avec le mot-clé extern
. Maintenant, disons que nous ne voulons pas utiliser cette entité dans d'autres unités de traduction. Ensuite, l'entité exist
jusqu'à la fin du programme, mais quand on n'a pas le déclarer, nous ne serons pas en mesure de les consulter. Notez aussi que maintenant j'ai mélangé les termes de couplage et la durée de vie. Mais c'est parce qu' global
des entités ont une liaison externe. Un identifiant à l'intérieur d'une fonction ne peut pas être référencé par rapport aux autres parties du programme.
Conclusion: essayez de Toujours garder les choses simples. J'ai été surpris de voir comment les différentes personnes parler de ces termes différemment. L'ensemble du processus de compilation séparée est source de confusion, parce qu'il y a plusieurs termes qui ont presque le même sens, et probablement tout le monde sera coincé à ce point.