C++20 尝试将头文件模块化导入
北海梦星洋
编辑于 2023年01月28日 14:20
收录于文集
共3篇

前言

    众所周知,C++20标准增加了模块的支持。模块的优缺点相信大家已经很了解了,我就不再赘述。VS2022支持以导入的方式使用头文件,但是我在尝试导入时发现,不同类型的头文件需要使用不同的导入方法。下面我就用3个头文件举例,看看它们是如何导入的。

准备工作

    在使用模块之前,需要开启模块支持。

    创建一个空项目,进入项目属性,常规,将“C++语言标准”选项改为C++20,即可启用模块支持。

    

第一部分 直接导入

    直接导入法适用于标准库和部分第三方库。这里以<iostream>和<graphics.h>为例。

    创建一个源文件,尝试直接导入这两个头文件。

代码块
C++
自动换行
复制代码
//项目.cpp
import <iostream>;
import <graphics.h>;
int main() {}
复制成功

    显然,直接导入是不行的,提示找不到标头单元。

    根据文档介绍,标头单元是介于头文件和模块的过渡形式,用于从头文件向模块的转化过程。将头文件编译为标头单元后,可以像模块一样使用,

    VS支持自动将导入的头文件编译为标头单元。进入项目属性,C/C++,常规,将“扫描源以查找模块依赖关系”选项改为是,即可自动将导入的头文件转换为标头单元。

    此外,将下面的“将包含转换为导入”选项改为是。该选项可以将标准库中的连续包含分解为连续的模块导出,进一步细分文件。

    注意:经测试,开启“将包含转换为导入”选项后,可能导致奇怪的BUG出现,此时请尝试关闭该项。关闭该项后仍然可以自动编译标头单元,但不会将文件内的连续包含进一步细分。

    修改设定后运行,可以发现导入的头文件以模块的形式分别编译完成。

    但是,如果导入的是<windows.h>,情况便有所不同。

代码块
C++
自动换行
复制代码
//项目.cpp
import <windows.h>;
int main() {}
复制成功

    导入<windows.h>,按照与刚才相同的设置运行,会产生错误。

    这时候就需要使用第二种导入方法了。

第二部分 间接导入

    间接导入将需要导入的头文件加入到一个静态库项目中,其他项目引用该项目后,可以直接找到该项目所编译的标头单元。

    使用间接导入可以解决部分头文件无法直接导入的问题,还能形成一个通用的标头单元库,批量地将头文件转化为模块,节省时间。

    注意:能解决一部分直接导入报的问题,如果使用此方法仍有报错,则说明文件无法导入,只能在模块头中包含。

    根据上文步骤,创建一个空项目,创建一个源文件。

    对项目进行相关设置,启用模块支持,启用自动编译标头单元。其中C/C++选项卡需要在项目中创建一个源文件才可以看到,所以需要先创建源文件。

    随后进入项目属性,常规,将“配置类型”选项改为静态库。

    设置完静态库以后,在源文件中导入想要转化为模块的头文件。静态库不需要main函数。

代码块
C++
自动换行
复制代码
//静态库.cpp
import <windows.h>;
import <iostream>;
import <graphics.h>;
复制成功

    静态库到这里就准备完毕了,可以选择在此时对静态库进行一次生成。

    创建一个新的空项目,为新项目启用模板支持。不需要启用自动编译标头单元选项。

    在新项目中右键解决方案,添加现有项目。选择静态库项目添加到当前解决方案中。

    在新项目中右键引用,添加引用。

    在打开的窗口中勾选静态库项目。

    添加完毕后,不需要对新项目的设置进行其他改变,就可以自动寻找静态库项目中生成的标头单元了。

    在新项目中创建一个源文件,导入<windows.h>。

代码块
C++
自动换行
复制代码
//项目.cpp
import <windows.h>;
int main() {}
复制成功

    运行,正常生成。

总结

    文中所有项目需要先打开模块支持。

    对于标准库及部分第三方库,可以使用自动编译标头单元的方式直接导入。

    对于不能直接导入的库,可以为其创建一个静态库项目,在静态库项目中启用自动编译标头单元,随后在新项目中引用该静态库,实现间接导入。

    并且,间接导入可以批量准备多个标头单元,节省时间。

    开启“包含转换为导入”选项后,能导致奇怪的BUG出现,时请尝试关闭该项。

    对于直接导入和间接导入均报错的库,只能使用模块头包含的方式。

后记

    作者并非专业人员,学习编程仅仅是业余兴趣,所以显然会有很多不专业之处。这篇文章只是在作者探索头文件模块化这一过程时的历程总结,并不具有任何目的性和技术性,仅仅是记录一点经验和技巧而已。

    有所帮助的话希望给我点个赞,若发现文中的错误还请不要喷,谢谢!