Condividi tramite


Unità di conversione e collegamento

In un programma C++ un simbolo, ad esempio una variabile o un nome di funzione, può essere dichiarato un numero qualsiasi di volte all'interno dell'ambito. Tuttavia, può essere definito una sola volta. Questa regola è "One Definition Rule" (ODR). Una dichiarazione introduce (o reintroduce) un nome nel programma, insieme a informazioni sufficienti per associare successivamente il nome a una definizione. Una definizione introduce un nome e fornisce tutte le informazioni necessarie per crearla. Se il nome rappresenta una variabile, una definizione crea in modo esplicito l'archiviazione e la inizializza. Una definizione di funzione è costituita dalla firma più il corpo della funzione. Una definizione di classe è costituita dal nome della classe seguito da un blocco che elenca tutti i membri della classe. I corpi delle funzioni membro possono essere definiti separatamente in un altro file.

L'esempio seguente mostra alcune dichiarazioni:

int i;
int f(int x);
class C;

L'esempio seguente illustra alcune definizioni:

int i{42};
int f(int x){ return x * i; }
class C {
public:
   void DoSomething();
};

Un programma è costituito da una o più unità di traduzione. Un'unità di conversione è costituita da un file di implementazione e da tutte le intestazioni incluse direttamente o indirettamente. I file di implementazione in genere hanno un'estensione di file di .cpp o .cxx. I file di intestazione hanno in genere un'estensione di .h o .hpp. Ogni unità di conversione viene compilata in modo indipendente dal compilatore. Al termine della compilazione, il linker unisce le unità di traduzione compilate in un unico programma. Le violazioni della regola ODR vengono in genere visualizzate come errori del linker. Gli errori del linker si verificano quando lo stesso nome viene definito in più unità di conversione.

In generale, il modo migliore per rendere visibile una variabile in più file consiste nel dichiararla in un file di intestazione. Aggiungere quindi una #include direttiva in ogni .cpp file che richiede la dichiarazione. Aggiungendo protezioni di inclusione intorno al contenuto dell'intestazione, assicurarsi che i nomi dichiarati da un'intestazione vengano dichiarati una sola volta per ogni unità di conversione. Definire il nome in un solo file di implementazione.

In C++20 i moduli vengono introdotti come alternativa migliorata ai file di intestazione.

In alcuni casi, potrebbe essere necessario dichiarare una variabile o una classe globale in un .cpp file. In questi casi, è necessario un modo per indicare al compilatore e al linker il tipo di collegamento del nome. Il tipo di collegamento specifica se il nome dell'oggetto è visibile solo in un file o in tutti i file. Il concetto di collegamento si applica solo ai nomi globali. Il concetto di collegamento non si applica ai nomi dichiarati all'interno di un ambito. Un ambito viene specificato da un set di parentesi graffe di inclusione, ad esempio nelle definizioni di funzione o di classe.

Collegamento esterno e interno

Una funzione libera è una funzione definita nell'ambito globale o dello spazio dei nomi. Per impostazione predefinita, le variabili globali non const e le funzioni gratuite hanno un collegamento esterno. Sono visibili da qualsiasi unità di conversione nel programma. Nessun altro oggetto globale può avere tale nome. Un simbolo con collegamento interno o nessun collegamento è visibile solo all'interno dell'unità di conversione in cui è dichiarata. Quando un nome ha un collegamento interno, lo stesso nome può esistere in un'altra unità di conversione. Le variabili dichiarate all'interno di definizioni di classe o corpi di funzione non hanno alcun collegamento.

È possibile forzare il collegamento interno di un nome globale dichiarandolo in modo esplicito come static. Questa parola chiave limita la visibilità alla stessa unità di conversione in cui è dichiarata. In questo contesto, static significa qualcosa di diverso da quando applicato alle variabili locali.

Per impostazione predefinita, gli oggetti seguenti dispongono di collegamenti interni:

  • Oggetti const
  • Oggetti constexpr
  • Oggetti typedef
  • static oggetti nell'ambito dello spazio dei nomi

Per assegnare un collegamento esterno a un const oggetto, dichiararlo come extern e assegnargli un valore:

extern const int value = 42;

Per ulteriori informazioni, vedere extern.

Vedi anche

Concetti di base