当前位置: 首页 > article >正文

C++学习笔记----10、模块、头文件及各种主题(一)---- 模块(4)

8.1、实现分区

        在模块接口分区文件中不需要声明分区,也可以在模块实现分区文件中进行声明,在一个以.cpp为扩展名的正常源代码文件中,在这种情况下,它是一个实现分区,有时候叫内部分区。这样的分区无法导出,与模块接口分区相比,它必须被模块接口主文件导出。

例如,假定有下面的math主模块接口文件(math.cppm):

export module math; // math module declaration

export namespace Math
{
	double superLog(double z, double b);
	double lerchZeta(double lambda, double alpha, double s);
}

        接着假设数学函数的实现需要辅助函数必须被模块导出。实现分区是放置这样的辅助函数的绝佳之地。下面在math_helpers.cpp文件中定义了实现分区:

module math:details;  // math:details implementation partition

double someHelperFunction(double a)
{
	// Implementation omitted...
	return 42;
}

        其它的模块实现文件可以通过导入这个实现分区来访问这些辅助函数。例如,math模块实现文件(math.cpp)可能看起来像这样:

module math;

import :details;

double Math::superLog(double z, double b)
{
	// Implementation omitted...
	return someHelperFunction(z);
}

double Math::lerchZeta(double lambda, double alpha, double s)
{
	// Implementation omitted...
	return someHelperFunction(s);
}

        使用import  :details;声明,superLog()与lerchZeta()函数可以调用someHelperFunction()。

        当然了,使用这样的带有辅助函数的实现分区只有在多个其它源文件使用这些辅助函数时才说得通。

9、私有模块部分

        模块接口主文件可以包含私有模块部分。该私有模块部分以以下行开始:

module :private;

        这行之后的所有代码都是私有模块部分的代码。在这个私有模块部分定义的任何东东都不会导出,因此对模块的消费者也不可见。

        在《掌握类与对象》章节中演示了pimpl习语,也叫做私有实现习语。它隐藏了类的消费者的所有实现细节。在该章节中,解决方案要求两个文件:一个主模块接口文件和一个模块实现文件。使用私有模块部分,可以通过使用一个单独的文件来达到这个分隔。下面是一个准确的例子:

export module adder;

import std;

export class Adder
{
public:
	Adder();
	virtual ~Adder();
	int add(int a, int b) const;
private:
	class Impl;
	std::unique_ptr<Impl> m_impl;

public:
	Impl* getImplementation() { return m_impl.get(); }
};

module :private;

class Adder::Impl
{
public:
	~Impl()
	{
		std::println("Destructor of Adder::Impl");
	}

	int add(int a, int b) const
	{
		return a + b;
	}
};

Adder::Adder()
	: m_impl{ std::make_unique<Impl>() }
{
}

Adder::~Adder() {}

int Adder::add(int a, int b) const
{
	return m_impl->add(a, b);
}

        该类可以测试如下:

Adder adder;
println("Value: {}", adder.add(20, 22));

        现在,为了证明在私有模块部分中的所有代码都被隐藏,我们添加一个公共的成员函数getImplementation()在Adder类的尾部:

export class Adder
{
    /* ... as before, omitted for brevity ... */
private:
    class Impl;
    std::unique_ptr<Impl> m_impl;

public:
    Impl* getImplementation() { return m_impl.get(); }
};

        下面的代码编译与运行都没有问题:

Adder adder;
auto impl { adder.getImplementation() };

        从Adder模块消费者的观点来看,getImplementation()返回一个指向不完整类型的指针。该代码片断在一个叫做impl的变量中保存该指针。只要用auto类型推演,简单把指针保存在不完整类型中是没有问题的。然而,不能对该指针进行任何操作。在该不完整的指针上调用add()会产生一个错误:

auto result { impl-­>add(20, 22) };// Error!

        这个错误有点像:使用未定义的类型Adder::Impl。原因是Adder::Impl类是私有模块部分的一部分,因此Adder模块的消费者无法访问。

        如果从模块接口文件中去掉module :private;这一行,前面的代码段编译与运行就没有问题了。乍一看会很吃惊;毕竟Adder::Impl类没有显式导出。这是正确的--它没有显式导出,但是它是隐式导出的,因为Adder类被导出,Impl类在Adder类中被声明。


http://www.kler.cn/a/380922.html

相关文章:

  • LeetCode 209. 长度最小的子数组 (C++实现)
  • 深度学习每周学习总结J9(Inception V3 算法实战与解析 - 天气识别)
  • 如何使用 Python 执行 SQL 查询?
  • 【Qt】显示类控件:QLabel、QLCDNumber、QProgressBar、QCalendarWidget
  • 【游戏设计原理】22 - 石头剪刀布
  • 网络安全防范
  • MFCC特征与Fbank特征在语音识别中的应用
  • Unity3D PCG地图的使用与优化详解
  • npm入门教程2:npm历史
  • AI 写作(一):开启创作新纪元(1/10)
  • Qt 文件目录操作
  • Linux 进程终止 进程等待
  • linux同步执行命令脚本 (xcall)
  • ubuntu工具 -- ubuntu服务器临时没有网络,急需联网下载东西怎么办? 使用手机提供网络
  • AI打造超写实虚拟人物:是科技奇迹还是伦理挑战?
  • 【Python爬虫实战】深入 Selenium:从节点信息提取到检测绕过的全攻略
  • 基于C语言实现的TCP客户端
  • 哈希表相关知识
  • 解决wsl重启后debian配置vm.max_map_count不生效问题以及设置docker开机自启
  • Kafka在大数据处理中的作用及其工作原理
  • 20.04Ubuntu配置opencv并使用头文件
  • CSS--综合练习
  • 商业数据库 - oracle -数据字典
  • SQL 语法学习
  • Spring MVC 完整生命周期和异常处理流程图
  • MySQL学习正式篇