Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questa esercitazione illustra la creazione di moduli C++20. I moduli sostituiscono i file di intestazione. Si apprenderà come i moduli sono un miglioramento dei file di intestazione.
In questa esercitazione, scopri come:
- Creare e importare un modulo
- Creare un'unità di interfaccia del modulo principale
- Creare un file di partizione del modulo
- Creare un file di implementazione dell'unità di modulo
Prerequisiti
Questa esercitazione richiede Visual Studio 2022 17.1.0 o versione successiva.
Durante l'uso dell'esempio di codice in questa esercitazione potrebbero verificarsi errori IntelliSense. Lavorare sul motore IntelliSense sta recuperando con il compilatore. Gli errori di IntelliSense possono essere ignorati e non impediscono la compilazione dell'esempio di codice. Per tenere traccia dello stato di avanzamento del lavoro di IntelliSense, vedere questo problema.
Che cosa sono i moduli C++
I file di intestazione sono il modo in cui le dichiarazioni e le definizioni vengono condivise tra i file di origine in C++. I file di intestazione sono fragili e difficili da comporre. Possono essere compilati in modo diverso a seconda dell'ordine in cui sono inclusi o nelle macro che sono o non sono definite. Possono rallentare il tempo di compilazione perché vengono rielaborati per ogni file di origine che li include.
C++20 introduce un approccio moderno alla componentizzazione di programmi C++: moduli.
Come i file di intestazione, i moduli consentono di condividere dichiarazioni e definizioni tra i file di origine. A differenza dei file di intestazione, tuttavia, i moduli non perdono definizioni di macro o dettagli di implementazione privata.
I moduli sono più facili da comporre perché la semantica non cambia a causa di definizioni di macro o di altri elementi importati, dell'ordine delle importazioni e così via. Consentono inoltre di controllare più facilmente ciò che è visibile ai consumer.
I moduli garantiscono una maggiore sicurezza che i file di intestazione non lo siano. Il compilatore e il linker interagiscono per evitare possibili problemi di collisione dei nomi e garantire una regola di definizione (ODR) più efficace.
Un modello di proprietà avanzata evita conflitti tra nomi in fase di collegamento perché il linker collega i nomi esportati al modulo che li esporta. Questo modello consente al compilatore Microsoft Visual C++ di impedire il comportamento non definito causato dal collegamento di moduli diversi che segnalano nomi simili nello stesso programma. Per altre informazioni, vedere Strong Ownership.For more information, see Strong Ownership.
Un modulo è costituito da uno o più file di codice sorgente compilati in un file binario. Il file binario descrive tutti i tipi, le funzioni e i modelli esportati nel modulo. Quando un file di origine importa un modulo, il compilatore legge nel file binario che contiene il contenuto del modulo. La lettura del file binario è molto più veloce rispetto all'elaborazione di un file di intestazione. Inoltre, il file binario viene riutilizzato dal compilatore ogni volta che il modulo viene importato, risparmiando ancora più tempo. Poiché un modulo viene compilato una sola volta anziché ogni volta che viene importato, il tempo di compilazione può essere ridotto, a volte notevolmente.
Ancora più importante, i moduli non presentano i problemi di fragilità che i file di intestazione fanno. L'importazione di un modulo non modifica la semantica del modulo o la semantica di qualsiasi altro modulo importato. Le macro, le direttive del preprocessore e i nomi non esportati dichiarati in un modulo non sono visibili al file di origine che lo importa. È possibile importare moduli in qualsiasi ordine e non cambierà il significato dei moduli.
I moduli possono essere usati affiancati ai file di intestazione. Questa funzionalità è utile se si esegue la migrazione di una codebase per usare i moduli perché è possibile eseguire questa operazione in fasi.
In alcuni casi, un file di intestazione può essere importato come unità di intestazione anziché come #include
file. Le unità di intestazione sono l'alternativa consigliata ai file di intestazione precompilati (PCH). Sono più facili da configurare e usare rispetto ai file PCH condivisi, ma offrono vantaggi di prestazioni simili. Per altre informazioni, vedere Procedura dettagliata: Creare e importare unità di intestazione in Microsoft Visual C++.
Il codice può utilizzare moduli nello stesso progetto o in qualsiasi progetto a cui si fa riferimento, usando automaticamente riferimenti da progetto a progetto ai progetti di libreria statica.
Creare il progetto
Durante la compilazione di un progetto semplice, verranno esaminati vari aspetti dei moduli. Il progetto implementerà un'API usando un modulo anziché un file di intestazione.
In Visual Studio 2022 o versione successiva scegliere Crea un nuovo progetto e quindi il tipo di progetto App console (per C++). Se questo tipo di progetto non è disponibile, è possibile che non sia stato selezionato il carico di lavoro Sviluppo di applicazioni desktop con C++ durante l'installazione di Visual Studio. È possibile usare il Programma di installazione di Visual Studio per aggiungere il carico di lavoro C++.
Assegnare al nuovo progetto il nome ModulesTutorial
e creare il progetto.
Poiché i moduli sono una funzionalità C++20, usare l'opzione del compilatore o /std:c++latest
./std:c++20
Nel Esplora soluzioni fare clic con il pulsante destro del mouse sul nome ModulesTutorial
del progetto, quindi scegliere Proprietà. Nella finestra di dialogo Pagine delle proprietà del progetto impostare Configurazione su Tutte le configurazioni e piattaforma su Tutte le piattaforme. Selezionare Proprietà>di configurazione Generale nel riquadro della visualizzazione albero a sinistra. Selezionare la proprietà Standard del linguaggio C++. Usare l'elenco a discesa per modificare il valore della proprietà in ISO C++20 Standard (/std:c++20). Selezionare OK per accettare la modifica.
Creare l'unità di interfaccia del modulo principale
Un modulo è costituito da uno o più file. Uno di questi file deve essere quello denominato unità di interfaccia del modulo primario. Definisce le esportazioni del modulo; ovvero ciò che verranno visualizzati gli import del modulo. Può essere presente una sola unità di interfaccia del modulo primaria per modulo.
Per aggiungere un'unità di interfaccia del modulo principale, in Esplora soluzioni fare clic con il pulsante destro del mouse su File di origine e quindi scegliere Aggiungi>modulo.
Nella finestra di dialogo Aggiungi nuovo elemento visualizzato assegnare al nuovo modulo il nome BasicPlane.Figures.ixx
e scegliere Aggiungi.
Il contenuto predefinito del file di modulo creato ha due righe:
export module BasicPlane;
export void MyFunc();
Le export module
parole chiave nella prima riga dichiarano che questo file è un'unità di interfaccia del modulo. C'è un punto sottile qui: per ogni modulo denominato, deve essere presente esattamente un'unità di interfaccia del modulo senza alcuna partizione di modulo specificata. Tale unità di modulo è denominata unità di interfaccia del modulo primario.
L'unità di interfaccia del modulo principale è la posizione in cui si dichiarano le funzioni, i tipi, i modelli, gli altri moduli e le partizioni del modulo da esporre quando i file di origine importano il modulo. Un modulo può essere costituito da più file, ma solo il file di interfaccia del modulo primario identifica gli elementi da esporre.
Sostituire il contenuto del BasicPlane.Figures.ixx
file con:
export module BasicPlane.Figures; // the export module keywords mark this file as a primary module interface unit
Questa riga identifica questo file come interfaccia del modulo primario e assegna al modulo un nome: BasicPlane.Figures
. Il punto nel nome del modulo non ha un significato speciale per il compilatore. Un periodo può essere usato per comunicare come è organizzato il modulo. Se sono presenti più file di modulo che interagiscono, è possibile usare i periodi per indicare una separazione delle problematiche. In questa esercitazione si useranno i periodi per indicare diverse aree funzionali dell'API.
Questo nome è anche il percorso da cui deriva "named" in "named module". I file che fanno parte di questo modulo usano questo nome per identificarsi come parte del modulo denominato. Un modulo denominato è la raccolta di unità modulo con lo stesso nome del modulo.
È consigliabile parlare dell'API che verrà implementata per un attimo prima di proseguire. Influisce sulle scelte effettuate successivamente. L'API rappresenta forme diverse. In questo esempio verranno fornite solo due forme: Point
e Rectangle
. Point
è progettato per essere usato come parte di forme più complesse, ad esempio Rectangle
.
Per illustrare alcune funzionalità dei moduli, questa API verrà inserita in parti. Una parte sarà l'API Point
. L'altra parte sarà Rectangle
. Si supponga che questa API cresca in qualcosa di più complesso. La divisione è utile per separare i problemi o semplificare la manutenzione del codice.
Finora è stata creata l'interfaccia del modulo principale che esporrà questa API. A questo punto si creerà l'API Point
. Si vuole che faccia parte di questo modulo. Per motivi di organizzazione logica e potenziale efficienza di compilazione, vogliamo rendere questa parte dell'API facilmente comprensibile da sola. A tale scopo, verrà creato un file di partizione del modulo.
Un file di partizione del modulo è una parte o un componente di un modulo. Ciò che lo rende univoco è che può essere considerato come una singola parte del modulo, ma solo all'interno del modulo. Le partizioni del modulo non possono essere utilizzate all'esterno di un modulo. Le partizioni del modulo sono utili per dividere l'implementazione del modulo in parti gestibili.
Quando si importa una partizione nel modulo primario, tutte le relative dichiarazioni diventano visibili al modulo primario indipendentemente dal fatto che vengano esportate. Le partizioni possono essere importate in qualsiasi interfaccia di partizione, interfaccia del modulo primario o unità di modulo appartenente al modulo denominato.
Creare un file di partizione del modulo
Point
partizione del modulo
Per creare un file di partizione del modulo, nella Esplora soluzioni fare clic con il pulsante destro del mouse su File di origine e quindi scegliere Aggiungi>modulo. Assegnare un nome al file BasicPlane.Figures-Point.ixx
e scegliere Aggiungi.
Poiché si tratta di un file di partizione del modulo, è stato aggiunto un trattino e il nome della partizione al nome del modulo. Questa convenzione consente al compilatore nel caso della riga di comando perché il compilatore usa regole di ricerca dei nomi basate sul nome del modulo per trovare il file compilato .ifc
per la partizione. In questo modo non è necessario fornire argomenti espliciti /reference
della riga di comando per trovare le partizioni che appartengono al modulo. È anche utile organizzare i file che appartengono a un modulo in base al nome, perché è possibile vedere facilmente quali file appartengono ai moduli.
Sostituire il contenuto di BasicPlane.Figures-Point.ixx
con:
export module BasicPlane.Figures:Point; // defines a module partition, Point, that's part of the module BasicPlane.Figures
export struct Point
{
int x, y;
};
Il file inizia con export module
. Queste parole chiave sono anche il modo in cui inizia l'interfaccia del modulo primario. Ciò che rende questo file diverso è il punto (:
) che segue il nome del modulo, seguito dal nome della partizione. Questa convenzione di denominazione identifica il file come partizione del modulo. Poiché definisce l'interfaccia del modulo per una partizione, non viene considerata l'interfaccia del modulo principale.
Il nome BasicPlane.Figures:Point
identifica questa partizione come parte del modulo BasicPlane.Figures
. Tenere presente che il punto nel nome non ha alcun significato speciale per il compilatore. I due punti indicano che questo file contiene una partizione di modulo denominata Point
che appartiene al modulo BasicPlane.Figures
. È possibile importare questa partizione in altri file che fanno parte di questo modulo denominato.
In questo file la export
parola chiave rende struct Point
visibile ai consumer.
Rectangle
partizione del modulo
La partizione successiva che verrà definita è Rectangle
. Creare un altro file di modulo seguendo gli stessi passaggi di prima: in Esplora soluzioni fare clic con il pulsante destro del mouse su File di origine e quindi scegliere Aggiungi>modulo. Assegnare un nome al file BasicPlane.Figures-Rectangle.ixx
e selezionare Aggiungi.
Sostituire il contenuto di BasicPlane.Figures-Rectangle.ixx
con:
export module BasicPlane.Figures:Rectangle; // defines the module partition Rectangle
import :Point;
export struct Rectangle // make this struct visible to importers
{
Point ul, lr;
};
// These functions are declared, but will
// be defined in a module implementation file
export int area(const Rectangle& r);
export int height(const Rectangle& r);
export int width(const Rectangle& r);
Il file inizia con export module BasicPlane.Figures:Rectangle;
il quale dichiara una partizione di modulo che fa parte del modulo BasicPlane.Figures
. L'oggetto :Rectangle
aggiunto al nome del modulo lo definisce come partizione del modulo BasicPlane.Figures
. Può essere importato singolarmente in uno qualsiasi dei file di modulo che fanno parte di questo modulo denominato.
import :Point;
Viene quindi illustrato come importare una partizione di modulo. L'istruzione import
rende visibili al modulo tutti i tipi, le funzioni e i modelli esportati nella partizione del modulo. Non è necessario specificare il nome del modulo. Il compilatore sa che questo file appartiene al BasicPlane.Figures
modulo a causa dell'oggetto all'inizio export module BasicPlane.Figures:Rectangle;
del file.
Il codice esporta quindi la definizione di struct Rectangle
e le dichiarazioni per alcune funzioni che restituiscono varie proprietà del rettangolo. La export
parola chiave indica se rendere visibile ciò che precede ai consumer del modulo. Viene usato per rendere visibili le funzioni area
, height
e width
all'esterno del modulo.
Tutte le definizioni e le dichiarazioni in una partizione di modulo sono visibili all'unità del modulo di importazione indipendentemente dal fatto che abbiano o meno la export
parola chiave . La export
parola chiave determina se la definizione, la dichiarazione o il typedef saranno visibili all'esterno del modulo quando si esporta la partizione nell'interfaccia del modulo primario.
I nomi vengono resi visibili ai consumer di un modulo in diversi modi:
- Inserire la parola chiave
export
davanti a ogni tipo, funzione e così via, che si vuole esportare. - Se si inserisce
export
davanti a uno spazio dei nomi, ad esempioexport namespace N { ... }
, tutti gli elementi definiti all'interno delle parentesi graffe vengono esportati. Tuttavia, se altrove nel modulo definitonamespace N { struct S {...};}
,struct S
non è disponibile per i consumer del modulo. Non è disponibile perché la dichiarazione dello spazio dei nomi non è preceduta daexport
, anche se esiste un altro spazio dei nomi con lo stesso nome. - Se un tipo, una funzione e così via non deve essere esportato, omettere la
export
parola chiave. Sarà visibile ad altri file che fanno parte del modulo, ma non agli import del modulo. - Usare
module :private;
per contrassegnare l'inizio della partizione del modulo privato. La partizione del modulo privato è una sezione del modulo in cui le dichiarazioni sono visibili solo a tale file. Non sono visibili ai file che importano questo modulo o ad altri file che fanno parte di questo modulo. Si consideri una sezione che sia locale statica per il file. Questa sezione è visibile solo all'interno del file. - Per rendere visibile un modulo o una partizione di modulo importata, usare
export import
. Un esempio è illustrato nella sezione successiva.
Comporre le partizioni del modulo
Ora che sono state definite le due parti dell'API, è possibile riunirle in modo che i file che importano questo modulo possano accedervi nel suo complesso.
Tutte le partizioni del modulo devono essere esposte come parte della definizione del modulo a cui appartengono. Le partizioni vengono esposte nell'interfaccia del modulo primario. Aprire il BasicPlane.Figures.ixx
file, che definisce l'interfaccia del modulo primario. Sostituisci il contenuto con:
export module BasicPlane.Figures; // keywords export module marks this as a primary module interface unit
export import :Point; // bring in the Point partition, and export it to consumers of this module
export import :Rectangle; // bring in the Rectangle partition, and export it to consumers of this module
Le due righe che iniziano con export import
sono nuove qui. Se combinati in questo modo, queste due parole chiave indicano al compilatore di importare il modulo specificato e renderlo visibile ai consumer di questo modulo. In questo caso, i due punti (:
) nel nome del modulo indicano che si sta importando una partizione del modulo.
I nomi importati non includono il nome completo del modulo. Ad esempio, la :Point
partizione è stata dichiarata come export module BasicPlane.Figures:Point
. Eppure qui si sta importando :Point
. Poiché si trova nel file di interfaccia del modulo primario per il modulo BasicPlane.Figures
, il nome del modulo è implicito e viene specificato solo il nome della partizione.
Finora è stata definita l'interfaccia del modulo principale, che espone la superficie API che si vuole rendere disponibile. Ma è stato dichiarato, non definito, area()
, height()
o width()
. A questo scopo, si creerà un file di implementazione del modulo.
Creare un file di implementazione dell'unità di modulo
I file di implementazione dell'unità di modulo non terminano con un'estensione .ixx
. Si tratta di file normali .cpp
. Aggiungere un file di implementazione dell'unità di modulo creando un file di origine con un clic con il pulsante destro del mouse nella Esplora soluzioni in File di origine, selezionare Aggiungi>nuovo elemento e quindi selezionare File C++ (con estensione cpp). Assegnare al nuovo file il nome BasicPlane.Figures-Rectangle.cpp
, quindi scegliere Aggiungi.
La convenzione di denominazione per il file di implementazione della partizione del modulo segue la convenzione di denominazione per una partizione. Ma ha un'estensione .cpp
perché si tratta di un file di implementazione.
Sostituire il contenuto del BasicPlane.Figures-Rectangle.cpp
file con:
module;
// global module fragment area. Put #include directives here
module BasicPlane.Figures:Rectangle;
int area(const Rectangle& r) { return width(r) * height(r); }
int height(const Rectangle& r) { return r.ul.y - r.lr.y; }
int width(const Rectangle& r) { return r.lr.x - r.ul.x; }
Questo file inizia con module;
il quale introduce un'area speciale del modulo denominata frammento di modulo globale. Precede il codice per il modulo denominato ed è la posizione in cui è possibile usare direttive del preprocessore, #include
ad esempio . Il codice nel frammento di modulo globale non è di proprietà o esportato dall'interfaccia del modulo.
Quando si include un file di intestazione, in genere non si vuole che venga considerato come parte esportata del modulo. In genere si include il file di intestazione come dettaglio di implementazione che non deve far parte dell'interfaccia del modulo. Ci possono essere casi avanzati in cui si vuole farlo, ma in genere non si è. Non vengono generati metadati separati (.ifc
file) per #include
le direttive nel frammento di modulo globale. I frammenti di modulo globali offrono un'ottima soluzione per includere file di intestazione, ad windows.h
esempio , o in Linux, unistd.h
.
Il file di implementazione del modulo che si sta creando non include librerie perché non ne ha bisogno come parte dell'implementazione. Ma se lo fosse, quest'area è la posizione in #include
cui le direttive sarebbero andate.
La riga module BasicPlane.Figures:Rectangle;
indica che questo file fa parte del modulo BasicPlane.Figures
denominato . Il compilatore inserisce automaticamente i tipi e le funzioni esposte dall'interfaccia del modulo principale in questo file. Un'unità di implementazione del modulo non ha la parola chiave prima della export
module
parola chiave nella dichiarazione del modulo.
Di seguito è riportata la definizione delle funzioni area()
, height()
e width()
. Sono stati dichiarati nella Rectangle
partizione in BasicPlane.Figures-Rectangle.ixx
. Poiché l'interfaccia del modulo principale per questo modulo ha importato le Point
partizioni del modulo e Rectangle
, tali tipi sono visibili qui nel file di implementazione dell'unità di modulo. Una caratteristica interessante delle unità di implementazione del modulo: il compilatore rende automaticamente visibili tutti gli elementi nell'interfaccia primaria del modulo corrispondente al file. Non imports <module-name>
è necessario.
Qualsiasi elemento dichiarato all'interno di un'unità di implementazione è visibile solo al modulo a cui appartiene.
Importare il modulo
A questo punto si userà il modulo definito. Apri il file ModulesTutorial.cpp
. È stato creato automaticamente come parte del progetto. Attualmente contiene la funzione main()
. Sostituisci il contenuto con:
#include <iostream>
import BasicPlane.Figures;
int main()
{
Rectangle r{ {1,8}, {11,3} };
std::cout << "area: " << area(r) << '\n';
std::cout << "width: " << width(r) << '\n';
return 0;
}
L'istruzione import BasicPlane.Figures;
rende visibili tutte le funzioni e i tipi esportati dal BasicPlane.Figures
modulo a questo file. Può venire prima o dopo qualsiasi #include
direttiva.
L'app usa quindi i tipi e le funzioni del modulo per restituire l'area e la larghezza del rettangolo definito:
area: 50
width: 10
Anatomia di un modulo
Verranno ora esaminati in dettaglio i vari file di modulo.
Interfaccia del modulo primario
Un modulo è costituito da uno o più file. Uno di essi definisce l'interfaccia che gli utilità di importazione vedranno. Questo file contiene l'interfaccia del modulo Primario. Può essere presente una sola interfaccia del modulo principale per modulo. Come indicato in precedenza, l'unità di interfaccia del modulo esportata non specifica una partizione del modulo.
Ha un'estensione .ixx
per impostazione predefinita. Tuttavia, è possibile trattare un file di origine con qualsiasi estensione come file di interfaccia del modulo. A tale scopo, impostare la proprietà Compile As nella scheda Avanzate per la pagina delle proprietà del file di origine su Compile As Module (/interface):To do do so, set the Compile As property in the Advanced tab for the source file properties page to Compile As Module (/interface):
La struttura di base di un file di definizione dell'interfaccia del modulo è:
module; // optional. Defines the beginning of the global module fragment
// #include directives go here but only apply to this file and
// aren't shared with other module implementation files.
// Macro definitions aren't visible outside this file, or to importers.
// import statements aren't allowed here. They go in the module preamble, below.
export module [module-name]; // Required. Marks the beginning of the module preamble
// import statements go here. They're available to all files that belong to the named module
// Put #includes in the global module fragment, above
// After any import statements, the module purview begins here
// Put exported functions, types, and templates here
module :private; // optional. The start of the private module partition.
// Everything after this point is visible only within this file, and isn't
// visible to any of the other files that belong to the named module.
Questo file deve iniziare con module;
per indicare l'inizio del frammento di modulo globale o export module [module-name];
per indicare l'inizio del modulo purview.
Il modulo purview è la posizione in cui funzioni, tipi, modelli e così via, si vuole esporre dal modulo.
È anche possibile esporre altre partizioni di moduli o moduli tramite le export import
parole chiave, come illustrato nel BasicPlane.Figures.ixx
file.
Il file di interfaccia principale deve esportare tutte le partizioni di interfaccia definite per il modulo direttamente o indirettamente oppure il programma non è formato correttamente.
La partizione del modulo privato è la posizione in cui è possibile inserire elementi che si desidera essere visibili solo in questo file.
Le unità di interfaccia del modulo prefano la parola chiave con la parola module
chiave export
.
Per un'analisi più approfondita della sintassi dei moduli, vedere Moduli.
Unità di implementazione del modulo
Le unità di implementazione del modulo appartengono a un modulo denominato. Il modulo denominato a cui appartengono è indicato dall'istruzione module [module-name]
nel file. Le unità di implementazione del modulo forniscono dettagli di implementazione che, per motivi di igiene del codice o altri motivi, non si vuole inserire nell'interfaccia del modulo principale o in un file di partizione del modulo.
Le unità di implementazione del modulo sono utili per suddividere un modulo di grandi dimensioni in parti più piccole, che possono comportare tempi di compilazione più rapidi. Questa tecnica è descritta brevemente nella sezione Procedure consigliate .
I file di unità di implementazione del modulo hanno un'estensione .cpp
. La struttura di base di un file di unità di implementazione del modulo è:
// optional #include or import statements. These only apply to this file
// imports in the associated module's interface are automatically available to this file
module [module-name]; // required. Identifies which named module this implementation unit belongs to
// implementation
File di partizione del modulo
Le partizioni del modulo consentono di componentizzare un modulo in parti o partizioni diverse. Le partizioni del modulo devono essere importate solo nei file che fanno parte del modulo denominato. Non possono essere importati all'esterno del modulo denominato.
Una partizione ha un file di interfaccia e zero o più file di implementazione. Una partizione di modulo condivide la proprietà di tutte le dichiarazioni nell'intero modulo.
Tutti i nomi esportati dai file di interfaccia di partizione devono essere importati ed esportati nuovamente (export import
) dal file di interfaccia primaria. Il nome di una partizione deve iniziare con il nome del modulo, seguito da due punti e quindi dal nome della partizione.
La struttura di base di un file di interfaccia di partizione è simile alla seguente:
module; // optional. Defines the beginning of the global module fragment
// This is where #include directives go. They only apply to this file and aren't shared
// with other module implementation files.
// Macro definitions aren't visible outside of this file or to importers
// import statements aren't allowed here. They go in the module preamble, below
export module [Module-name]:[Partition name]; // Required. Marks the beginning of the module preamble
// import statements go here.
// To access declarations in another partition, import the partition. Only use the partition name, not the module name.
// For example, import :Point;
// #include directives don't go here. The recommended place is in the global module fragment, above
// export imports statements go here
// after import, export import statements, the module purview begins
// put exported functions, types, and templates for the partition here
module :private; // optional. Everything after this point is visible only within this file, and isn't
// visible to any of the other files that belong to the named module.
...
Procedure consigliate per il modulo
Un modulo e il codice che lo importa devono essere compilati con le stesse opzioni del compilatore.
Denominazione dei moduli
- È possibile usare i punti ('.') nei nomi dei moduli, ma non hanno un significato speciale per il compilatore. Usarli per trasmettere significato agli utenti del modulo. Ad esempio, iniziare con la libreria o lo spazio dei nomi principale del progetto. Terminare con un nome che descrive la funzionalità del modulo.
BasicPlane.Figures
è progettato per trasmettere un'API per i piani geometrici e in particolare figure che possono essere rappresentate su un piano. - Il nome del file che contiene l'interfaccia primaria del modulo è in genere il nome del modulo. Ad esempio, dato il nome
BasicPlane.Figures
del modulo , il nome del file contenente l'interfaccia primaria sarà denominatoBasicPlane.Figures.ixx
. - Il nome di un file di partizione del modulo è in genere
<primary-module-name>-<module-partition-name>
dove il nome del modulo è seguito da un trattino ('-') e quindi dal nome della partizione. Ad esempio, usareBasicPlane.Figures-Rectangle.ixx
Se si esegue la compilazione dalla riga di comando e si usa questa convenzione di denominazione per le partizioni del modulo, non sarà necessario aggiungere /reference
in modo esplicito per ogni file di partizione del modulo. Il compilatore li cercherà automaticamente in base al nome del modulo. Il nome del file di partizione compilato (che termina con un'estensione .ifc
) viene generato dal nome del modulo. Si consideri il nome BasicPlane.Figures:Rectangle
del modulo : il compilatore prevede che il file di partizione compilato corrispondente per Rectangle
è denominato BasicPlane.Figures-Rectangle.ifc
. Il compilatore usa questo schema di denominazione per semplificare l'uso delle partizioni dei moduli individuando automaticamente i file di unità di interfaccia per le partizioni.
È possibile denominarli usando una convenzione personalizzata. È tuttavia necessario specificare gli argomenti corrispondenti /reference
per il compilatore della riga di comando.
Moduli fattore
Usare file e partizioni di implementazione del modulo per tenere conto del modulo per semplificare la manutenzione del codice e tempi di compilazione potenzialmente più veloci.
Ad esempio, lo spostamento dell'implementazione di un modulo dal file di definizione dell'interfaccia del modulo e in un file di implementazione del modulo significa che le modifiche apportate all'implementazione non causeranno necessariamente la ricompilazione di ogni file che importa il modulo (a meno che non siano presenti inline
implementazioni).
Le partizioni dei moduli semplificano il fattore logico di un modulo di grandi dimensioni. Possono essere usati per migliorare il tempo di compilazione in modo che le modifiche apportate a una parte dell'implementazione non causi la ricompilazione di tutti i file del modulo.
Riepilogo
In questa esercitazione sono state presentate le nozioni di base dei moduli C++20. È stata creata un'interfaccia del modulo principale, è stata definita una partizione del modulo e è stato compilato un file di implementazione del modulo.
Vedi anche
Panoramica dei moduli in C++
module
parole chiave , import
, export
Panoramica dei moduli C++ in Visual Studio
Moduli C++20 pratici e futuro degli strumenti relativi ai moduli C++
Spostamento di un progetto in C++ denominato Modules
Procedura dettagliata: Compilare e importare unità di intestazione in Microsoft Visual C++