Tutorial modul yang dinamai (C++)

Tutorial ini tentang membuat modul C++20. Modul adalah peningkatan signifikan pada file header.

Dalam tutorial ini, pelajari cara:

  • Membuat dan mengimpor modul
  • Buat unit antarmuka modul utama
  • Membuat berkas partisi modul
  • Membuat file implementasi unit modul

Prasyarat

Tutorial ini memerlukan Visual Studio 2022 17.1.0 atau yang lebih baru.

Apa itu modul C++

File header adalah bagaimana deklarasi dan definisi dibagikan antara file sumber di C++. Berkas header itu rapuh dan dapat dikompilasi secara berbeda tergantung pada urutan Anda menyertakan mereka atau pada makro yang ditentukan atau tidak. Mereka dapat memperlambat waktu kompilasi karena diolah ulang untuk setiap file sumber yang menyertakannya.

C++20 memperkenalkan modul sebagai pendekatan modern untuk mengomponensi program C++.

Seperti file header, modul memungkinkan Anda berbagi deklarasi dan definisi di seluruh file sumber. Tetapi tidak seperti file header, modul tidak membocorkan definisi makro atau detail implementasi privat.

Modul lebih mudah dibuat karena semantiknya tidak berubah karena definisi makro atau apa lagi yang telah diimpor, urutan impor, dan sebagainya. Mereka juga mempermudah kontrol apa yang terlihat oleh konsumen.

Modul memberikan jaminan keamanan ekstra yang tidak diberikan oleh file header. Kompilator dan linker bekerja sama untuk mencegah kemungkinan masalah tabrakan nama, dan memberikan jaminan aturan definisi tunggal yang lebih kuat (ODR).

Model kepemilikan yang kuat menghindari bentrokan antara nama pada waktu tautan karena linker melampirkan nama yang diekspor ke modul yang mengekspornya. Model ini memungkinkan pengkompilasi Microsoft Visual C++ untuk mencegah perilaku yang tidak terdefinisi yang disebabkan oleh penautan modul yang berbeda yang melaporkan nama serupa dalam program yang sama. Untuk informasi selengkapnya, lihat Strong Ownership.

Modul terdiri dari satu atau beberapa file kode sumber yang dikompilasi ke dalam file biner. File biner menjelaskan semua jenis, fungsi, dan templat yang diekspor dalam modul. Saat file sumber mengimpor modul, pengkompilasi membaca dalam file biner yang berisi konten modul. Membaca file biner jauh lebih cepat daripada memproses file header. Selain itu, file biner digunakan kembali oleh pengkompilasi setiap kali modul diimpor, menghemat lebih banyak waktu. Karena modul dibangun sekali daripada setiap kali diimpor, waktu build dapat dikurangi, terkadang secara dramatis.

Yang lebih penting, modul tidak memiliki masalah kerapuhan yang dimiliki oleh file header. Mengimpor modul tidak mengubah semantik modul, atau semantik modul impor lainnya. Makro, arahan praprosesor, dan nama yang tidak diekspor yang dideklarasikan dalam modul tidak terlihat oleh file sumber yang mengimpornya. Anda dapat mengimpor modul dalam urutan apa pun dan tidak akan mengubah arti modul.

Modul dapat digunakan berdampingan dengan file header. Fitur ini nyaman jika Anda memigrasikan basis kode untuk menggunakan modul karena Anda dapat melakukannya secara bertahap.

Dalam beberapa kasus, file header dapat diimpor sebagai unit header daripada sebagai file #include. Unit header adalah alternatif yang direkomendasikan untuk file header yang telah dikommpilasikan sebelumnya (PCH). Lebih mudah untuk menyiapkan dan menggunakan daripada file PCH bersama , tetapi memberikan manfaat kinerja yang serupa. Untuk informasi selengkapnya, lihat panduan : Membangun dan mengimpor unit header di Microsoft Visual C++.

Kode Anda dapat secara otomatis menggunakan modul dalam proyek yang sama atau proyek yang dirujuk dengan menggunakan referensi proyek-ke-proyek ke proyek pustaka statis.

Membuat proyek

Proyek berikut mengimplementasikan API menggunakan modul alih-alih file header.

Di Visual Studio 2022 atau yang lebih baru, pilih Buat proyek baru lalu jenis proyek Console App (untuk C++). Jika jenis proyek ini tidak tersedia, Anda mungkin belum memilih Pengembangan desktop dengan C++ workload saat Anda menginstal Visual Studio. Anda dapat menggunakan Alat Penginstal Visual Studio untuk menambahkan beban kerja C++.

Beri nama proyek baru ModulesTutorial dan buat proyek.

Karena modul adalah fitur C++20, gunakan opsi pengkompilasi /std:c++20 atau /std:c++latest. Di Jelajah Solusi, klik kanan pada nama proyek ModulesTutorial, lalu pilih Properti . Dalam dialog Halaman Properti Proyek, ubah Konfigurasi menjadi Semua Konfigurasi dan Platform menjadi Semua Platform. Pilih Properti Konfigurasi > Umum di panel tampilan pohon di sebelah kiri. Pilih properti Standar Bahasa C++ . Gunakan dropdown untuk mengubah nilai properti menjadi ISO C++20 Standard (/std:c++20). Pilih OK untuk menerima perubahan.

Cuplikan layar halaman properti ModulesTutorial dengan panel kiri terbuka ke Properti Konfigurasi > Umum, dan menu tarik-turun Standar Bahasa C++ terbuka dengan ISO C++20 Standard (/std:c++20) dipilih

Membuat unit antarmuka modul utama

Modul terdiri dari satu atau beberapa file. Salah satu dari file ini pasti merupakan apa yang disebut unit antarmuka modul utama . Ini mendefinisikan apa yang diekspor modul; yaitu, apa yang dilihat oleh importir modul. Hanya ada satu unit antarmuka modul utama per modul.

Untuk menambahkan unit antarmuka modul utama, di Penjelajah Solusi, klik kanan File Sumber lalu pilih Tambahkan modul>.

Dialog Tambah Item di Penjelajah Solusi dengan Tambah Modul >... disorot untuk mengilustrasikan tempat mengklik untuk menambahkan modul.

Dalam dialog Tambahkan Item Baru yang muncul, beri modul baru nama BasicPlane.Figures.ixx dan pilih Tambahkan.

Konten default file modul yang dibuat memiliki dua baris:

export module BasicPlane;

export void MyFunc();

Kata kunci export module di baris pertama menyatakan bahwa file ini adalah unit antarmuka modul. Ada titik halus di sini: untuk setiap modul bernama, harus ada tepat satu unit antarmuka modul tanpa partisi modul yang ditentukan. Unit modul tersebut disebut unit antarmuka modul utama.

Unit antarmuka modul utama adalah tempat Anda mendeklarasikan fungsi, jenis, templat, modul lain, dan partisi modul untuk diekspos saat file sumber mengimpor modul. Modul dapat terdiri dari beberapa file, tetapi hanya file antarmuka modul utama yang mengidentifikasi apa yang harus diekspos.

Ganti konten file BasicPlane.Figures.ixx dengan:

export module BasicPlane.Figures; // the export module keywords mark this file as a primary module interface unit

Baris ini mengidentifikasi file ini sebagai antarmuka modul utama dan memberi modul nama: BasicPlane.Figures. Periode dalam nama modul tidak memiliki arti khusus untuk pengkompilasi. Periode dapat digunakan untuk menyampaikan bagaimana modul Anda diatur. Jika Anda memiliki beberapa file modul yang bekerja sama, Anda dapat menggunakan titik untuk menunjukkan pemisahan kekhawatiran. Dalam tutorial ini, tanda titik menunjukkan area fungsional yang berbeda dari API.

Nama ini adalah asal-usul dari istilah "bernama" dalam "modul bernama". File yang merupakan bagian dari modul ini menggunakan nama ini untuk mengidentifikasi diri mereka sebagai bagian dari modul bernama. Modul bernama adalah kumpulan unit modul dengan nama modul yang sama.

Kita harus berbicara tentang API yang akan kita terapkan sejenak sebelum melangkah lebih jauh. Ini berdampak pada pilihan yang kita buat selanjutnya. API mewakili berbagai bentuk. Kita hanya akan memberikan beberapa bentuk dalam contoh ini: Point dan Rectangle. Point dimaksudkan untuk digunakan sebagai bagian dari bentuk yang lebih kompleks seperti Rectangle.

Untuk mengilustrasikan beberapa fitur modul, kami memperhitungkan API ini menjadi beberapa bagian. Salah satu bagiannya adalah API Point. Bagian lain adalah Rectangle. Bayangkan bahwa API ini dapat tumbuh menjadi sesuatu yang lebih kompleks. Pembagian ini berguna untuk memisahkan masalah atau mengurangi pemeliharaan kode.

Sejauh ini, kami telah membuat antarmuka modul utama yang akan mengekspos API ini. Sekarang mari kita buat API Point. Kami ingin ini menjadi bagian dari modul ini. Untuk alasan organisasi logis, dan potensi efisiensi build, kami ingin menjadikan kode untuk bagian API ini sebagai partisi modul file.

Partisi modul berguna untuk membaru implementasi modul menjadi bagian yang dapat dikelola. File partisi modul adalah bagian dari modul. Yang membuatnya unik adalah dapat diperlakukan sebagai bagian individual dari modul --tetapi hanya dalam modul. Partisi modul tidak dapat digunakan di luar modul.

Saat Anda mengimpor partisi ke dalam modul utama, semua deklarasinya menjadi terlihat oleh modul utama terlepas dari apakah mereka diekspor. Partisi dapat diimpor ke antarmuka partisi apa pun, antarmuka modul utama, atau unit modul yang termasuk dalam modul bernama.

Membuat sebuah file partisi modul

contoh partisi modul Point

Untuk membuat file partisi modul, di Penjelajah Solusi klik kanan File Sumber, lalu pilih Tambahkan Modul>. Beri nama file BasicPlane.Figures-Point.ixx dan pilih Tambahkan.

Karena ini adalah file partisi modul, kami menambahkan tanda hubung dan nama partisi ke nama modul. Konvensi ini membantu pengkompilasi dalam kasus baris perintah karena pengkompilasi menggunakan aturan pencarian nama berdasarkan nama modul untuk menemukan file .ifc yang dikompilasi untuk partisi. Dengan cara ini Anda tidak perlu memberikan argumen baris perintah /reference eksplisit untuk menemukan partisi yang termasuk dalam modul. Ini juga berguna untuk mengatur file milik modul berdasarkan nama karena Anda dapat dengan mudah melihat file mana yang termasuk dalam modul mana.

Ganti konten BasicPlane.Figures-Point.ixx dengan:

export module BasicPlane.Figures:Point; // defines a module partition, Point, that's part of the module BasicPlane.Figures

export struct Point
{
    int x, y;
};

File dimulai dengan export module. Kata kunci ini juga merupakan bagaimana antarmuka modul utama dimulai. Apa yang membuat file ini berbeda adalah titik dua (:) mengikuti nama modul, diikuti dengan nama partisi. Konvensi penamaan ini mengidentifikasi file sebagai partisi modul . Karena mendefinisikan antarmuka modul untuk partisi, itu tidak dianggap sebagai antarmuka modul utama.

Nama BasicPlane.Figures:Point mengidentifikasi partisi ini sebagai bagian dari modul BasicPlane.Figures (ingat, periode dalam nama tidak memiliki arti khusus untuk pengkompilasi). Titik dua menunjukkan bahwa file ini berisi partisi modul bernama Point milik modul BasicPlane.Figures. Kita dapat mengimpor partisi ini ke file lain yang merupakan bagian dari modul bernama ini.

Dalam file ini, kata kunci export membuat struct Point terlihat oleh konsumen.

contoh partisi modul Rectangle

Partisi berikutnya yang kami tentukan adalah Rectangle. Buat file modul lain menggunakan langkah yang sama seperti sebelumnya: Di Penjelajah Solusi, klik kanan File Sumber, lalu pilih Tambahkan Modul>. Beri nama file BasicPlane.Figures-Rectangle.ixx dan pilih Tambahkan.

Ganti konten BasicPlane.Figures-Rectangle.ixx dengan:

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);

File dimulai dengan export module BasicPlane.Figures:Rectangle; yang mendeklarasikan partisi modul yang merupakan bagian dari modul BasicPlane.Figures. :Rectangle ditambahkan ke nama modul mendefinisikannya sebagai partisi modul BasicPlane.Figures. Ini dapat diimpor satu per satu ke dalam salah satu file modul yang merupakan bagian dari modul bernama ini.

Selanjutnya, import :Point; menunjukkan cara mengimpor partisi modul. Pernyataan import membuat semua jenis, fungsi, dan templat yang diekspor dalam partisi modul terlihat oleh modul. Anda tidak perlu menentukan nama modul. Pengkompilasi tahu bahwa file ini milik modul BasicPlane.Figures karena export module BasicPlane.Figures:Rectangle; di bagian atas file.

Selanjutnya, kode mengekspor definisi struct Rectangle dan deklarasi untuk beberapa fungsi yang mengembalikan berbagai properti persegi panjang. Kata kunci export menunjukkan apakah akan membuat apa yang mendahuluinya terlihat oleh pengguna dari modul. Ini digunakan untuk membuat fungsi area, height, dan width terlihat di luar modul.

Semua definisi dan deklarasi dalam partisi modul terlihat oleh unit modul impor apakah mereka memiliki kata kunci export atau tidak. Kata kunci export mengatur apakah definisi, deklarasi, atau typedef terlihat di luar modul saat Anda mengekspor partisi di antarmuka modul utama.

Nama dibuat terlihat oleh konsumen modul dengan beberapa cara:

  • Letakkan kata kunci export di depan setiap jenis, fungsi, dan sebagainya, yang ingin Anda ekspor.
  • Jika Anda meletakkan export di depan namespace, misalnya export namespace N { ... }, semuanya yang ditentukan dalam kurung kurawal diekspor. Tetapi jika Anda mendefinisikan namespace N { struct S {...};}di tempat lain dalam modul, maka struct S tidak tersedia untuk konsumen modul. Ini tidak tersedia karena deklarasi namespace tidak diawali oleh export, meskipun ada namespace lain dengan nama yang sama yaitu.
  • Jika jenis, fungsi, dan sebagainya, tidak boleh diekspor, hilangkan kata kunci export. Ini terlihat oleh file lain yang merupakan bagian dari modul, tetapi tidak untuk pengimpor modul.
  • Gunakan module :private; untuk menandai awal partisi modul privat. Partisi modul privat adalah bagian dari modul tempat deklarasi hanya terlihat oleh file tersebut. Mereka tidak terlihat oleh file yang mengimpor modul ini atau untuk file lain yang merupakan bagian dari modul ini. Anggap saja sebagai bagian yang bersifat lokal statis ke file. Bagian ini hanya terlihat dalam file.
  • Untuk membuat modul atau partisi modul yang diimpor terlihat, gunakan export import. Contoh ditampilkan di bagian berikutnya.

Menyusun partisi modul

Sekarang setelah kita memiliki dua bagian API yang ditentukan, mari kita satukan sehingga file yang mengimpor modul ini dapat mengaksesnya secara keseluruhan.

Semua partisi modul harus diekspos sebagai bagian dari definisi modul tempat partisi tersebut berada. Partisi diekspos di antarmuka modul utama. Buka file BasicPlane.Figures.ixx, yang menentukan antarmuka modul utama. Ganti isinya dengan:

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

Dua baris yang dimulai dengan export import baru di sini. Ketika digabungkan seperti ini, kedua kata kunci ini menginstruksikan pengompilasi untuk mengimpor modul yang ditentukan dan membuatnya terlihat oleh konsumen modul ini. Dalam hal ini, titik dua (:) dalam nama modul menunjukkan bahwa kami mengimpor partisi modul.

Nama yang diimpor tidak menyertakan nama modul lengkap. Misalnya, partisi :Point dinyatakan sebagai export module BasicPlane.Figures:Point. Namun di sini kita mengimpor :Point. Karena kita berada dalam file antarmuka modul utama untuk modul BasicPlane.Figures, nama modul tersirat, dan hanya nama partisi yang ditentukan.

Sejauh ini, kami telah mendefinisikan antarmuka modul utama, yang mengekspos permukaan API yang ingin kami sediakan. Tetapi kami hanya menyatakan, tidak mendefinisikan area(), height(), atau width(). Kami melakukannya selanjutnya dengan membuat file implementasi modul.

Membuat file implementasi modul unit

File implementasi unit modul tidak diakhir dengan ekstensi .ixx--file tersebut adalah file .cpp normal. Tambahkan file implementasi unit modul dengan membuat file sumber dengan klik kanan di Penjelajah Solusi di File Sumber, pilih Tambahkan item baru> lalu pilih File C++ (.cpp). Beri nama file baru BasicPlane.Figures-Rectangle.cpp, lalu pilih Tambahkan.

Konvensi penamaan untuk file implementasi partisi modul mengikuti konvensi penamaan untuk partisi. Tetapi memiliki ekstensi .cpp karena ini adalah file implementasi.

Ganti konten file BasicPlane.Figures-Rectangle.cpp dengan:

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; }

File ini dimulai dengan module; yang memperkenalkan area khusus modul yang disebut fragmen modul global . Ini mendahului kode untuk modul bernama dan merupakan tempat Anda dapat menggunakan arahan prapemrosesan seperti #include. Kode dalam fragmen modul global tidak dimiliki atau diekspor oleh antarmuka modul.

Saat Anda menyertakan file header, Anda umumnya tidak ingin file tersebut diperlakukan sebagai bagian yang diekspor dari modul. Anda biasanya menyertakan file header sebagai detail implementasi yang seharusnya tidak menjadi bagian dari antarmuka modul. Mungkin ada kasus lanjutan di mana ingin melakukan itu, tetapi umumnya Anda tidak. Tidak ada metadata terpisah (file.ifc) yang dihasilkan untuk arahan #include dalam fragmen modul global. Fragmen modul global menyediakan tempat yang baik untuk menyertakan file header seperti windows.h, atau di Linux, unistd.h.

File implementasi modul yang kami bangun tidak menyertakan pustaka apa pun karena tidak memerlukannya sebagai bagian dari implementasinya. Namun jika itu terjadi, area ini merupakan tempat direktif #include akan diletakkan.

Baris module BasicPlane.Figures:Rectangle; menunjukkan bahwa file ini adalah bagian dari modul bernama BasicPlane.Figures. Pengkompilasi secara otomatis membawa jenis dan fungsi yang diekspos oleh antarmuka modul utama ke dalam file ini. Unit implementasi modul tidak memiliki kata kunci export sebelum kata kunci module dalam deklarasi modulnya.

Selanjutnya adalah definisi fungsi area(), height(), dan width(). Mereka dinyatakan dalam partisi Rectangle di BasicPlane.Figures-Rectangle.ixx. Karena antarmuka modul utama untuk modul ini mengimpor partisi modul Point dan Rectangle, jenis tersebut terlihat di sini dalam file implementasi unit modul. Fitur menarik dari unit implementasi modul: Pengkompilasi secara otomatis membuat semuanya dalam antarmuka utama modul yang sesuai terlihat oleh file. Tidak ada imports <module-name> yang diperlukan.

Apa pun yang Anda nyatakan dalam unit implementasi hanya terlihat oleh modul miliknya.

Mengimpor modul

Sekarang kita menggunakan modul yang telah kita tentukan. Buka file ModulesTutorial.cpp. Ini dibuat secara otomatis sebagai bagian dari proyek. Saat ini berisi fungsi main(). Ganti isinya dengan:

#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;
}

Pernyataan import BasicPlane.Figures; membuat semua fungsi dan jenis yang diekspor dari modul BasicPlane.Figures terlihat oleh file ini. Instruksi tersebut datang setelah semua direktif #include.

Aplikasi kemudian menggunakan jenis dan fungsi dari modul untuk menghasilkan area dan lebar persegi panjang yang ditentukan:

area: 50
width: 10

Anatomi sebuah modul

Sekarang, mari kita lihat berbagai file modul secara lebih rinci.

Antarmuka modul utama

Modul terdiri dari satu atau beberapa file. Salah satunya mendefinisikan antarmuka yang dilihat pengimpor. File ini berisi antarmuka modul utama . Hanya ada satu antarmuka modul utama per modul. Seperti yang ditunjukkan sebelumnya, unit antarmuka modul yang diekspor tidak menentukan partisi modul.

Ini memiliki ekstensi .ixx secara default. Namun, Anda dapat memperlakukan file sumber dengan ekstensi apa pun sebagai file antarmuka modul. Untuk melakukannya, atur properti Compile As di tab Tingkat Lanjut untuk halaman properti file sumber ke Compile As Module (/interface):

Cuplikan layar properti Konfigurasi file sumber hipotetis di bawah Properti konfigurasi > C/C++ > Advanced > Compile As, dengan Compile as C++ Module Code (/interface) disorot

Kerangka dasar file definisi antarmuka modul adalah:

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.

File ini harus dimulai dengan module; untuk menunjukkan awal fragmen modul global, atau export module [module-name]; untuk menunjukkan awal cakupan modul .

Cakupan modul adalah tempat fungsi, tipe, templat, dan sebagainya berada, yang ingin Anda ekspos dari modul.

Ini juga tempat Anda dapat mengekspos modul atau partisi modul lain melalui kata kunci export import, seperti yang ditunjukkan dalam file BasicPlane.Figures.ixx.

File antarmuka utama harus mengekspor semua partisi antarmuka yang ditentukan untuk modul secara langsung atau tidak langsung, atau program ini dibentuk salah.

Partisi modul privat adalah tempat Anda dapat menempatkan hal-hal yang anda inginkan hanya terlihat dalam file ini.

Unit antarmuka modul mengawali kata kunci module dengan kata kunci export.

Untuk melihat sintaks modul yang lebih mendalam, lihat modul .

Modul unit implementasi

Unit pelaksanaan modul termasuk dalam modul yang dinamakan. Modul bernama milik mereka ditunjukkan oleh pernyataan module [module-name] dalam file. Unit implementasi modul memberikan detail implementasi yang, untuk kebersihan kode atau alasan lain, Anda tidak ingin memasukkan antarmuka modul utama atau dalam file partisi modul.

Unit implementasi modul berguna untuk memecah modul besar menjadi bagian yang lebih kecil, yang dapat mengakibatkan waktu build yang lebih cepat. Teknik ini dibahas secara singkat di bagian Praktik terbaik.

File unit implementasi modul memiliki ekstensi .cpp. Kerangka dasar file unit implementasi modul adalah:

// optional #include statements. These only apply to this file
// optional 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 pembagian modul

Partisi modul menyediakan cara untuk membagi modul menjadi bagian yang berbeda, atau partisi. Partisi modul dimaksudkan untuk diimpor hanya pada file yang merupakan bagian dari modul yang disebutkan. Mereka tidak dapat diimpor di luar modul yang disebut.

Partisi memiliki file antarmuka, dan nol atau lebih file implementasi. Partisi modul berbagi kepemilikan semua deklarasi di seluruh modul.

Semua nama yang diekspor oleh file antarmuka partisi harus diimpor dan diekspor ulang (export import) oleh file antarmuka utama. Nama partisi harus dimulai dengan nama modul, diikuti dengan titik dua, lalu nama partisi.

Kerangka dasar file antarmuka partisi terlihat seperti ini:

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.
...

Praktik terbaik untuk modul

Modul dan kode yang mengimpornya harus dikompilasi dengan opsi pengkompilasi yang sama.

Penamaan modul

  • Anda dapat menggunakan titik ('.') dalam nama modul Anda tetapi tidak memiliki arti khusus untuk pengkompilasi. Gunakan untuk menyampaikan makna kepada pengguna modul Anda. Misalnya, mulailah dengan namespace pustaka atau proyek utama. Selesaikan dengan nama yang menjelaskan fungsionalitas modul. BasicPlane.Figures dimaksudkan untuk menyampaikan API untuk bidang geometris, dan khususnya angka yang dapat diwakili di bidang.
  • Nama file yang berisi antarmuka utama modul umumnya adalah nama modul. Misalnya, mengingat nama modul BasicPlane.Figures, nama file yang berisi antarmuka utama akan diberi nama BasicPlane.Figures.ixx.
  • Nama file partisi modul umumnya <primary-module-name>-<module-partition-name> di mana nama modul diikuti dengan tanda hubung ('-') lalu nama partisi. Misalnya, BasicPlane.Figures-Rectangle.ixx

Jika Anda membangun dari baris perintah dan menggunakan konvensi penamaan ini untuk partisi modul, maka Anda tidak perlu secara eksplisit menambahkan /reference untuk setiap file partisi modul. Pengkompilasi mencarinya secara otomatis berdasarkan nama modul. Nama file partisi yang dikompilasi dihasilkan dari nama modul dan berakhir .ifc. Pertimbangkan nama modul BasicPlane.Figures:Rectangle: pengkompilasi mengantisipasi bahwa file partisi yang dikompilasi yang sesuai untuk Rectangle diberi nama BasicPlane.Figures-Rectangle.ifc. Pengkompilasi menggunakan skema penamaan ini untuk mempermudah penggunaan partisi modul dengan menemukan file unit antarmuka secara otomatis untuk partisi.

Anda dapat menamainya menggunakan konvensi Anda sendiri. Namun, Anda harus menentukan argumen /reference yang sesuai ke kompilator jalur perintah.

Modul faktor

Gunakan file implementasi modul dan partisi untuk memperhitungkan modul Anda untuk pemeliharaan kode yang lebih mudah dan waktu kompilasi yang berpotensi lebih cepat.

Misalnya, memindahkan implementasi modul dari file definisi antarmuka modul dan ke dalam file implementasi modul berarti bahwa perubahan pada implementasi tidak akan selalu menyebabkan setiap file yang mengimpor modul untuk dikombinasikan ulang (kecuali Anda memiliki implementasi inline).

Partisi modul memudahkan untuk memperhitungkan modul besar secara logis. Mereka dapat digunakan untuk meningkatkan waktu kompilasi sehingga perubahan pada sebagian implementasi tidak menyebabkan semua file modul dikombinasikan ulang.

Ringkasan

Dalam tutorial ini, Anda diperkenalkan dengan dasar-dasar modul C++20 dengan membuat antarmuka modul utama, menentukan partisi modul, dan membangun file implementasi modul.

Lihat juga

Ringkasan modul di C++
kata kunci module, import, export
Tur Modul C++ di Visual Studio
Modul C++20 Praktis dan Masa Depan Alat di Bidang Modul C++
Memindahkan proyek ke C++ bernama Modul
Panduan: Membangun dan mengimpor unit header di Microsoft Visual C++