C++语言导学 第三章 模块化 - 3.3 模块(C++20)

C++语言导学 第三章 模块化 - 3.3 模块(C++20)

3.3 模块(C++20)

使用#include是一种古老的、易出错的且代价相当高的程序模块化组织方式。如果你在101个编译单元中使用#include header.h,编译器将会处理header.h的文件101次。如果你在header2.h之前使用#include header1.h,则header1.h中的声明和宏可能影响header2.h中代码的含义。相反,如果你在header1.h之前使用#include header2.h,则header2.h可能影响header1.h中的代码。显然,这不是一种理想的方式,实际上,自1972年这种机制被引入C语言之后,它就一直是额外代价和错误的主要来源。

我们的最终目的是想找到一种在C++中表达物理模块的更好方法。语言特性module尚未纳入ISO C++标准,但已是ISO技术规范[ModulesTS]。已有C++实现提供了module特性,因此我在这里冒一点风险推荐这个特性,虽然其细节可能发生改变,而且距离每个人都能使用它编写代码还有些时日。旧代码,即使用#include的代码,还会“生存”非常长的时间,因为代码更新代价很高且非常耗时。
我们考虑使用module表达3.2节中的Vectoe和use()例子:

//文件Vector.cpp:
module;	//
//...
export class Vector{
public:
	Vector(int s);
	double& operator[](int i);
	int size();
private:
	double* elem;
	int sz;
};

Vector::Vector(int s)
:elem{new double[s]}, sz{s}
{
}
double& Vector::opeartor[](int i)
{
	return elem[i];
}
int Vector::size()
{
	return sz;
}
export int size(const Vector& v){return v.size();}

这段代码定义了一个名为Vector的模块,它导出类Vector及其所有成员函数和非成员函数size()。

我们使用这个module的方式是在需要它的地方导入(import)它。例如:

//文件user.cpp:
import Vector;						//获取Vector的接口
#include <cmath>					//获取标准库数学函数接口,其中包含sqrt()
double sqrt_sum(Vector& v)
{
	double sum = 0;
	for(int i = 0; i != v.size(); ++i)
		sum += std::sqrt(v[i]);		//平方根求和
	return sum;
}

我本可以对标准库数学函数也采用import,但我使用了老式的#include,借此展示新旧风格是可以混合的。在渐进地将#include旧代码更新为import新式代码的过程中,这种混合方式是必要的。

头文件和模块的差异不仅是语法上的。

  • 一个模块只会编译一遍(而不是在使用它的每个编译单元中都编译一遍)。
  • 两个模块可以按任意顺序导入(import)而不会改变它们的含义。
  • 如果你将一些东西导入一个模块中,则模块的使用者不会隐式获得东西的访问权(但也不会被它们所困扰):import无传递性。

这些差异对可维护性和编译时性能的影响是惊人的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hank_W

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值