February
6th,
2023
概念
现在模块化编程,替代头文件,解决模块间符号可见性控制问题
模块声明
编译单元默认普通单元
,module
关键字模块单元
,export module
定义模块对外接口
export module helloworld;
//符号默认对模块外不可见
void private_hello() {
std::cout << "Hello World!" << std::endl;
}
//定义外部可见函数
export void hello() {
private_hello():
}
//导出整个namespace,不推荐
export namespace hname {
int get_num() {
return 0;
}
}
//推荐namespace内细粒度控制
namespace xname {
export int get_num() {
return 0;
}
}
导入模块
import
关键字导入模块,让被引用模块的符号在本编译单元可见,类似using namespace
,可以用export import
将导入符号对外导出
///bye.cpp
export module bye;
import <iostream>
export void goodbye() {
std::cout << "Goodbye" << std::endl;
}
///helloworld.cpp
export module helloworld;
export import bye;
export void hello() {
std::cout << "Hello World!" << std::endl;
}
///main.cpp
import helloworld;
int main() {
helloe();
goodbye();
return 0;
}
导入头文件
import
与include
区别是,通过impor
导入头文件的编译单元定义的预处理宏
,是无法被import
导入的文件访问的,可以用模块片段
来实现使用预处理宏
影响头文件
全局模块片段
module;
//预处理宏指令
//模块声明
模块分区
模块的一个关键特性是可以划分为更多的子模块。在 C++ Modules 中,子模块主要有两种实现方式:通过模块名称进行区分(utils.image
)、利用模块分区特性(模块名:分区名
)。
//helloworld_a.cpp
export module helloworld:A;
//helloworld_b.cpp
export module helloworld:B
//helloworld.cpp
export module helloworld;
export import :A;
import :B;
模块所有权
使用模块的时候需要注意符号声明的所有权问题,这影响符号的实现位置和符号的链接性(linkage)
export module lib;
namespace hello { //命名空间不属于lib
extern "C++" int32_t f(); //外部链接c++方式符号,不属于lib
extern "C" int32_t g(); //外部链接c方式符号,不属于lib
int32_t x(); //hello::x属于lib,只能被同模块编译单元使用
export int32_t z(); //hello::z属于lib,可被其它模块编译单元使用
}