红魔咖啡馆

头发越掉越多,头发越掉越少

0%

【C++】模块

模块

拓展名

  • 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模块下的分区,故使用冒号

使用模块时,我们只要导入主模块,分区模块会被自动导入

编译时,最好要按照依赖顺序编译,否则可能编译错误