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

2021/12/31 11:09:00

本文主要是介绍C++语言导学 第三章 模块化 - 3.3 模块(C++20),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

第三章 模块化

  • 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无传递性。

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



这篇关于C++语言导学 第三章 模块化 - 3.3 模块(C++20)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程