模块
拓展名
- msvc:.ixx
- gcc:.cxx
全局模块片段
1
2
3
4
module;
#include<iostream>
#define PI 3.1415
export module math;像这样从module到export module之间的代码称为全局模块片段
包含头文件、定义宏等,用于模块内部,对外不可见
export module 模块名用于声明导出一个模块,最好用一样的名字
export
在后面编写代码时,若在函数等前面添加了export关键字,表示将该函数导出,在其他源文件中便可导入该函数使用,若没有export关键字,表示该函数对外不可见
1
2
3
4
5
6
7
8
9
10
11
export template<typename T>
T add(T a, T b){
return a+b;
}
export double circle(double r){
return PI*r*r;
}
template<typename T>
T mul(T a, T b){
return a*b;
}import
其他源文件中,使用import 模块名声明来导入模块,可以使用被导出的函数
与include的区别:
- import是C++的一个声明,在编译和链接后才进行处理
- #include是一个预处理指令,预处理后会被替换为C++语句
编译
如上面的代码
首先需要编译iostream模块,然后就可以编译主程序与math模块
1
2
g++ -std=c++20 -fmodules-ts -xc++-system-header iostream
g++ -std=c++20 -fmodules-ts 路径 -o 输出文件名CMake中,在target_sources中使用FILE_SET CXX_MODULES即可编译
分区
我们可以通过分区将一个模块分为多个模块单元
例:
接口文件Geometry.cpp
1
2
3
4
export module Geometry;
export import :Rectangle;
export import :Circle;
export import :Shape;文件中导出模块Geometry,导入并导出三个子模块
Geometry-Shape.cpp文件,实现了Shape模块
1
2
3
4
export module Geometry:Shape;
export class Shape{
...
}这里需要使用主模块名:分区名的形式导出接口类
Geometry-Rectangle.cpp文件,实现了Rectangle模块
1
2
3
4
5
export module Geometry:Rectangle;
import :Shape;
export classs Rectangle: public Shape{
...
}这里Rectangle继承自Shape类,故需要导入Shape模块,而他们都是Geometry模块下的分区,故使用冒号
使用模块时,我们只要导入主模块,分区模块会被自动导入
编译时,最好要按照依赖顺序编译,否则可能编译错误