Portée (C++)

Lorsque vous déclarez un élément de programme tel qu’une classe, une fonction ou une variable, son nom peut uniquement être « vu » et utilisé dans certaines parties de votre programme. Le contexte dans lequel un nom est visible est appelé son étendue. Par exemple, si vous déclarez une variable x dans une fonction, x elle est visible uniquement dans ce corps de fonction. Elle a une étendue locale. Vous pouvez avoir d’autres variables par le même nom dans votre programme ; tant qu’elles se trouvent dans différentes étendues, elles ne respectent pas la règle de définition unique et aucune erreur n’est générée.

Pour les variables non statiques automatiques, l’étendue détermine également quand elles sont créées et détruites dans la mémoire du programme.

Il existe six types de portée :

  • L’étendue globale Un nom global est un nom global déclaré en dehors de n’importe quelle classe, fonction ou espace de noms. Toutefois, dans C++, même ces noms existent avec un espace de noms global implicite. L’étendue des noms globaux s’étend du point de déclaration à la fin du fichier dans lequel ils sont déclarés. Pour les noms globaux, la visibilité est également régie par les règles de liaison qui déterminent si le nom est visible dans d’autres fichiers du programme.

  • L’étendue de l’espace de noms Un nom déclaré dans un espace de noms, en dehors de toute définition de classe ou définition d’énumération ou bloc de fonction, est visible de son point de déclaration à la fin de l’espace de noms. Un espace de noms peut être défini dans plusieurs blocs sur différents fichiers.

  • L’étendue locale Un nom déclaré dans une fonction ou un lambda, y compris les noms de paramètres, a une étendue locale. Ils sont souvent appelés « locaux ». Elles ne sont visibles qu’à partir de leur point de déclaration jusqu’à la fin de la fonction ou du corps lambda. L’étendue locale est un type d’étendue de bloc, qui est abordée plus loin dans cet article.

  • Les noms d’étendue de classe des membres de classe ont une étendue de classe, qui s’étend dans toute la définition de classe, quel que soit le point de déclaration. L’accessibilité des membres de classe est contrôlée par les mot clé et protected les publicprivatemot clé. Les membres publics ou protégés sont accessibles uniquement à l’aide des opérateurs de sélection de membre (ou->) ou des opérateurs pointeur à membre (ou* -).>*

  • Les noms d’étendue d’instruction déclarés dans un for, , ifwhileou switch une instruction sont visibles jusqu’à la fin du bloc d’instructions.

  • L’étendue de fonction Une étiquette a une étendue de fonction, ce qui signifie qu’elle est visible dans un corps de fonction même avant son point de déclaration. L’étendue de la fonction permet d’écrire des instructions comme goto cleanup avant que l’étiquette cleanup soit déclarée.

Masquage des noms

Vous pouvez masquer un nom en le déclarant dans un bloc englobé. Dans l'illustration suivante, i est redéclaré dans le bloc interne, masquant ainsi la variable associée à i dans la portée de bloc externe.

Diagram that shows block scope name hiding.
Bloquer l’étendue et le masquage du nom

La sortie du programme représentée dans l'illustration est la suivante :

i = 0
i = 7
j = 9
i = 0

Remarque

L’argument szWhat est considéré comme étant dans la portée de la fonction. Par conséquent, il est traité comme s'il avait été déclaré dans le bloc le plus à l'extérieur de la fonction.

Masquage des noms de classes

Vous pouvez masquer les noms de classe en déclarant une fonction, un objet, une variable ou un énumérateur dans la même portée. Toutefois, le nom de la classe est toujours accessible lorsqu’il classest préfixé par le mot clé.

// hiding_class_names.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;

// Declare class Account at global scope.
class Account
{
public:
    Account( double InitialBalance )
        { balance = InitialBalance; }
    double GetBalance()
        { return balance; }
private:
    double balance;
};

double Account = 15.37;            // Hides class name Account

int main()
{
    class Account Checking( Account ); // Qualifies Account as
                                       //  class name

    cout << "Opening account with a balance of: "
         << Checking.GetBalance() << "\n";
}
//Output: Opening account with a balance of: 15.37

Remarque

N’importe quel endroit pour lequel le nom de classe (Account) est appelé, la classe mot clé doit être utilisée pour la différencier du compte de variable à étendue globale. Cette règle ne s’applique pas lorsque le nom de classe apparaît à gauche de l’opérateur de résolution de portée (::). Les noms à gauche de l'opérateur de résolution de portée sont toujours considérés comme des noms de classe.

L’exemple suivant montre comment déclarer un pointeur vers un objet de type Account à l’aide de l’mot clé class :

class Account *Checking = new class Account( Account );

L’initialiseur Account (entre parenthèses) de l’instruction précédente a une étendue globale ; il est de type double.

Remarque

La réutilisation des noms d'identificateur, comme l'indique cet exemple, est considérée comme un style de programmation médiocre.

Pour plus d’informations sur la déclaration et l’initialisation d’objets de classe, consultez Classes, Structures et Unions. Pour plus d’informations sur l’utilisation new des opérateurs de magasin libre et delete gratuits, consultez les opérateurs nouveaux et supprimés.

Masquage de noms avec une étendue globale

Vous pouvez masquer les noms avec une étendue globale en déclarant explicitement le même nom dans l’étendue de bloc. Toutefois, les noms d’étendue globale sont accessibles à l’aide de l’opérateur de résolution d’étendue (::).

#include <iostream>

int i = 7;   // i has global scope, outside all blocks
using namespace std;

int main( int argc, char *argv[] ) {
   int i = 5;   // i has block scope, hides i at global scope
   cout << "Block-scoped i has the value: " << i << "\n";
   cout << "Global-scoped i has the value: " << ::i << "\n";
}
Block-scoped i has the value: 5
Global-scoped i has the value: 7

Voir aussi

Concepts de base