< Langage C++
fin de la boite de navigation du chapitre


Portée du code

En C++, la notion de "portée du code" est très importante car elle permet de décrire ce qui se passe, dans quel cadre, et dans une certaine mesure ce qui existe et ce qui n'existe pas encore au travers de contextes d'exécutions.

Portée Globale

La portée globale fournit un espace de partage pour toute l'application.

Démonstration
// Début de portée "Globale"
// Déclarations Globale d'inclusion d'entête
#include <iostream> // nécessaire pour utiliser std::cout

//Déclare l'indirection de la portée nommée "std" vers la portée 
//globale (décompartimentation)(voir portée nommée plus bas)
using namespace std; // nécessaire pour utiliser directement cout 

//Déclaration de constante Globale
const int gMaConstanteGlobale = 1;

//Déclaration de variable Globale
int gMaVariableGlobale = 1;

//Déclaration de la méthode globale "main"
int main(int argc, char* argv[])
{
     return 0;
}

// Fin de portée "Globale"

La portée Globale englobe tout le programme.

Bien qu’il soit facile de s'en servir de fourre-tout, il est déconseillé de le faire. En fait, si on le faisait, on se retrouverait avec une myriade de types et de noms de variables que l’on ne pourrait pas distinguer des types et variables que l’on crée soit même[pas clair].

C'est pour cela qu’il existe les autres portées et notamment la portée nommée.

Portée Nommée "Espace de nom"

La portée nommée (aussi appelée "Espace de nom" du fait du mot clé qui les déclare "namespace") est la portée la plus simple à la disposition du développeur. Elle permet de fournir des noms pour encapsuler des constantes, des variables des types et des méthodes ceci afin de restreindre le champ d'application de ces objets ou de fournir une architecture pour leur utilisation. Ce type de portée est surtout utilisé dans le but de diviser pour mieux régner et délivre toute sa puissance dans l'implémentation des énumérations au sein d'un IDE graphique.

Exemple
// Début de portée "Globale"
// Déclarations Globale d'inclusion d'entête
#include <iostream> // nécessaire pour utiliser std::cout

//Déclare le déréférencement de la portée nommée "std" vers la portée 
//globale (décompartimentation)(voir portée nommée plus bas)
using namespace std; // nécessaire pour utiliser directement cout 

//Déclaration de constante Globale
const int gMaConstanteGlobale = 1;

//Déclaration de variable Globale
int gMaVariableGlobale;

namespace NVariablesProgramme
{
     //Déclaration d'un nouveau type "NVInteger" basé sur le type int
     typedef int NInteger;

     //Déclaration de constante de portée nommée
     const int nvMaConstanteDePorteeNommee = 2;

     //Déclaration de variable de portée nommée
     int nvMaVariableDePorteeNommee;
}

//Déclaration de la méthode globale "main"
int main(int argc, char* argv[])
{
     // Déréférencement manuel de la portée NVariablesProgramme obligatoire ici 
     // car on a pas utilisé using avec cet espace de nom.
     NVariablesProgramme::nvMaVariableDePorteeNommee = gMaConstanteGlobale;
     gMaVariableGlobale = NVariablesProgramme::nvMaConstanteDePorteeNommee;
     return 0;
}

// Fin de portée "Globale"
Fin de l'exemple

Il peut être tentant de fournir des noms identiques à des types/variables/méthodes pour des d'espaces de noms différents. Mais cela est à éviter pour trois raisons :

  • Cela porte à confusion,
  • Ne sachant pas comment les utilisateurs vont les utiliser, il vaut mieux éviter les homonymes (risque d'inversion de variables),
  • Cela provoque des erreurs de compilations si l'utilisateur met des using sur les deux namespaces simultanément et l'obligera à taper le nom du namespace à chaque fois.

Portée Locale

La portée locale et la plus petite portée qui existe. C'est la portée disponible dans les méthodes, les boucles et les structures de tests conditionnels. Elle est généralement déterminée par les accolades. La portée locale est la portée pour laquelle les variables déclarées dans cette même portée sont accessibles. C'est pour cette raison que les portées locales doivent être clairement identifiées et identifiables. Pour cela, il est impératif de les écrire toutes explicitement et de bonne pratique de tabuler chaque niveau de portées afin que l’on puisse facilement les dissocier. La tabulation standard des éditeurs de textes des IDE du marché tourne entre 4 et 6 espaces. Dans le projet LINUX, les recommandations de tabulation sont de 8 espaces. La plupart des développeurs modernes vous maudiront si vous tabulez en dessous de 4 espaces.

Exemple
#include <iostream> // nécessaire pour utiliser std::cout

using namespace std; // nécessaire pour utiliser directement cout 

const int gMaConstanteGlobale = 1;

int gMaVariableGlobale;

namespace NVariablesProgramme
{
     typedef int NInteger;

     const int nvMaConstanteDePorteeNommee = 2;

     int nvMaVariableDePorteeNommee;
}

//Déclaration de la méthode globale "main"
int main(int argc, char* argv[])
{
     // Portée locale de la méthode.
     int j = 2; // "int j" est créé dans cette portée

     if(1 < argc)
     {
          // Portée locale du test
          int i = 1; // "int i" existe ici !
          j = i; // ici j existe car l’on se trouve dans une portée sous-jacente à celle de sa déclaration.
          cout << argc << endl;
     }
     // ici "int i" n'existe plus car on est sorti de sa portée de définition

     NVariablesProgramme::nvMaVariableDePorteeNommee = gMaConstanteGlobale;
     gMaVariableGlobale = NVariablesProgramme::nvMaConstanteDePorteeNommee;
     return 0;
}
Fin de l'exemple

Portée "STATIQUE"

La portée statique est la portée des membres statiques du programme. Elle se distingue des autres types de portées par le fait qu'une variable statique existe au chargement du programme dans la mémoire mais n'est accessible que dans la portée locale de sa déclaration.

Exemple
#include <iostream> // nécessaire pour utiliser std::cout

using namespace std; // nécessaire pour utiliser directement cout

static int vInteger = 0; // Cette variable n'existe qu'en 1 seul exemplaire et est créée 
                         // au chargement du programme. Elle est accessible partout car 
                         // elle est déclarée dans la portée globale.

int TestStatic()
{
     static int vInteger2 = 0; // Cette variable n'existe qu'en 1 seul exemplaire et est créée 
                               // au chargement du programme. Elle n'est accessible qu’à l'intérieur 
                               // de la méthode car elle n'a pas été déclarée dans la portée globale.
                               // Par contre, comme elle est statique et qu'elle a été créée au 
                               // chargement du programme, elle conserve sa valeur même en dehors de 
                               // la méthode. 
                               // Cette instruction n'est par conséquent exécutée qu'une seule fois.

     return vInteger2++;       // Comme vous pourrez le constater, vInteger2 est incrémenté à chaque 
                               // appel, ce qui prouve que la déclaration n'est exécutée qu'une seule 
                               // fois et que la variable garde sa valeur en dehors de la méthode 
                               // contrairement à une variable non statique.
}

//Déclaration de la méthode globale "main"
int main(int argc, char* argv[])
{
     int vControle = 0;
     while (vControle < 10)
     {
          vControle = TestStatic();
          cout << vControle << endl;
     }
     return 0;
}
Fin de l'exemple
Cet article est issu de Wikiversity. Le texte est sous licence Creative Commons - Attribution - Partage dans les Mêmes. Des conditions supplémentaires peuvent s'appliquer aux fichiers multimédias.