Lien

De RAD Studio
Aller à : navigation, rechercher

Remonter à Déclarations - Index

Un programme exécutable est généralement créé par compilation de plusieurs unités de traduction autonomes, puis par connexion des fichiers objet résultants avec des bibliothèques préexistantes. Un problème se pose lorsque le même identificateur est déclaré dans des portées différentes (par exemple, dans des fichiers différents), ou s'il est déclaré plusieurs fois dans une même portée. La connexion, ou liaison, est le processus qui permet l'association correcte de chaque instance d'un identificateur à une fonction ou à un objet particulier. Tous les identificateurs possèdent l'un de ces trois attributs de liaison, en relation étroite avec leur portée : liaison externe, liaison interne ou absence d'attribut de liaison. Ces attributs sont déterminés par l'emplacement et le format de vos déclarations, ainsi que par l'utilisation explicite (ou implicite) du spécificateur de classe de stockage static ou extern.

Chaque instance d'un identificateur particulier caractérisé par une liaison externe représente le même objet ou la même fonction dans l'ensemble des fichiers et bibliothèques qui constituent le programme. Chaque instance d'un identificateur particulier caractérisé par une liaison interne représente le même objet ou la même fonction dans un seul fichier. Enfin, les identificateurs sans attribut de liaison représentent des entités uniques.

Règles des attributs de liaison externe et interne

Tout identificateur de fichier ou d'objet ayant une portée fichier sera caractérisé par une liaison interne si sa déclaration contient le spécificateur de classe de stockage static.

Si le même identificateur apparaît avec, à la fois, les attributs de liaison externe et interne dans le même fichier, il sera caractérisé en C++ par une liaison externe. En C, il aura une liaison interne.

Si la déclaration d'un identificateur d'objet ou de fonction contient le spécificateur de classe de stockage extern, il aura le même attribut de liaison que toute autre déclaration visible de cet identificateur à portée fichier. S'il n'existe pas de déclaration visible, l'identificateur sera caractérisé par une liaison externe.

Si une fonction est déclarée sans spécificateur de classe de stockage, son attribut de liaison est déterminé comme si le spécificateur extern était utilisé.

Si un identificateur d'objet à portée fichier est déclaré sans spécificateur de classe de stockage, il sera caractérisé par une liaison externe.

Les identificateurs suivants n'ont pas d'attribut de liaison :

  • Les identificateurs déclarés pour être autre chose qu'un objet ou une fonction (par exemple, un identificateur typedef)
  • Les paramètres de fonction
  • Les identificateurs à portée bloc (locale) pour des objets déclarés sans spécificateur de classe de stockage extern

Substantypage

Quand un module C++ est compilé, le compilateur génère des noms de fonctions qui tiennent compte des types de leurs arguments. Ce mécanisme est connu sous le nom de substantypage (name mangling en anglais). Il permet la surcharge des fonctions et aide le lieur à gérer les erreurs lors de l'appel de fonctions provenant d'autres modules. Mais ce dispositif n'est pas toujours souhaitable. Lors de la compilation d'un module C++ à lier avec un autre ne pratiquant pas le substantypage, le compilateur C++ doit être avisé de ne pas substantyper les noms des fonctions de l'autre module. Ce genre de situation est typiquement celui de la liaison avec des bibliothèques ou des fichiers .obj issus d'un compilateur C.

Pour indiquer au compilateur C++ de ne pas substantyper le nom d'une fonction, il suffit de la déclarer comme extern "C" :



 extern "C" void Cfunc( int );



Cette déclaration indique au compilateur de ne pas substantyper les références à la fonction Cfunc.

La déclaration extern "C" s'applique également à un bloc de noms :



 extern "C" {
    void Cfunc1( int );
    void Cfunc2( int );
    void Cfunc3( int );
 };



Cette déclaration "multiple" fonctionne comme celle concernant une seule fonction ; le compilateur ne substantype pas les références aux fonctions Cfunc1, Cfunc2 et Cfunc3. Cette forme de déclaration est également utilisable quand le bloc des noms de fonctions est contenu dans un fichier en-tête :



 extern "C" {
    #include "locallib.h"
 };



Remarque :  extern "C" ne peut pas être utilisé avec des identificateurs de classe.

Voir aussi