416 lines
36 KiB
HTML
416 lines
36 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh" dir="ltr" class="client-nojs" xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh">
|
|
<head><meta http-equiv="x-ua-compatible" content="ie=edge">
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
<title>模块 (C++20 起)</title>
|
|
<link rel="stylesheet" href="ext.css" />
|
|
<link rel="stylesheet" href="site_modules.css" />
|
|
</head>
|
|
<body class="mediawiki ltr sitedir-ltr ns-0 ns-subject page-cpp_language_modules skin-cppreference2 action-view cpp-navbar">
|
|
<div id="cpp-content-base">
|
|
<div id="content"><a id="top"></a>
|
|
<h1 id="firstHeading" class="firstHeading">模块 <span class="t-mark-rev t-since-cxx20">(C++20 起)</span></h1>
|
|
<div id="bodyContent">
|
|
<div id="contentSub"><span class="subpages">< <a href="cpp.html">cpp</a>‎ | <a href="cpp-language.html">language</a></span></div>
|
|
<div id="mw-content-text" lang="zh" dir="ltr" class="mw-content-ltr" xml:lang="zh">
|
|
<p>大多数 C++ 项目用到了多个翻译单元,因此它们需要在那些单元间分享<a href="cpp-language-declarations.html">声明</a>和<a href="cpp-language-definition.html">定义</a>。正是因为这样,使用头文件非常重要,例如标准库的声明通过 <a href="cpp-preprocessor-include.html"><tt>#include</tt></a> 对应的头提供。</p>
|
|
<p>模块是一个用于在翻译单元间分享声明和定义的语言特性。它们可以在某些地方替代使用头文件。</p>
|
|
<p>模块和<a href="cpp-language-namespace.html">命名空间</a>是正交的。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co1">// helloworld.cpp</span>
|
|
export module helloworld<span class="sy4">;</span> <span class="co1">// 模块声明</span>
|
|
import <span class="sy1"><</span>iostream<span class="sy1">></span><span class="sy4">;</span> <span class="co1">// 导入声明</span>
|
|
|
|
export <span class="kw4">void</span> hello<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span> <span class="co1">// 导出声明</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"Hello world!<span class="es1">\n</span>"</span><span class="sy4">;</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co1">// main.cpp</span>
|
|
import helloworld<span class="sy4">;</span> <span class="co1">// 导入声明</span>
|
|
|
|
<span class="kw4">int</span> main<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
|
|
hello<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<h3><span class="mw-headline" id=".E8.AF.AD.E6.B3.95">语法</span></h3>
|
|
<table class="t-sdsc-begin">
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td><code><b>export</b></code><span class="t-mark">(可选)</span> <code><b>module</b></code> <span class="t-spar">模块名</span> <span class="t-spar">模块分区</span><span class="t-mark">(可选)</span> <span class="t-spar">属性</span><span class="t-mark">(可选)</span> <code><b>;</b></code></td>
|
|
<td>(1)</td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td><code><b>export</b></code> <span class="t-spar">声明</span></td>
|
|
<td>(2)</td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td><code><b>export</b></code> <code><b>{</b></code> <span class="t-spar">声明序列</span><span class="t-mark">(可选)</span> <code><b>}</b></code></td>
|
|
<td>(3)</td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td><code><b>export</b></code><span class="t-mark">(可选)</span> <code><b>import</b></code> <span class="t-spar">模块名</span> <span class="t-spar">属性</span><span class="t-mark">(可选)</span> <code><b>;</b></code></td>
|
|
<td>(4)</td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td><code><b>export</b></code><span class="t-mark">(可选)</span> <code><b>import</b></code> <span class="t-spar">模块分区</span> <span class="t-spar">属性</span><span class="t-mark">(可选)</span> <code><b>;</b></code></td>
|
|
<td>(5)</td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td><code><b>export</b></code><span class="t-mark">(可选)</span> <code><b>import</b></code> <span class="t-spar">头名</span> <span class="t-spar">属性</span><span class="t-mark">(可选)</span> <code><b>;</b></code></td>
|
|
<td>(6)</td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td><code><b>module</b></code> <code><b>;</b></code></td>
|
|
<td>(7)</td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td><code><b>module : private</b></code> <code><b>;</b></code></td>
|
|
<td>(8)</td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
</table>
|
|
<div class="t-li1"><span class="t-li">1)</span> 模块声明。声明当前翻译单元是一个<i>模块单元</i>。</div>
|
|
<div class="t-li1"><span class="t-li">2,3)</span> 导出声明。导出 <span class="t-spar">声明</span> 或 <span class="t-spar">声明序列</span> 中所有具有命名空间作用域的声明。</div>
|
|
<div class="t-li1"><span class="t-li">4,5,6)</span> 导入声明。导入一个模块单元,模块分区,或头单元。</div>
|
|
<div class="t-li1"><span class="t-li">7)</span> 开始一个<i>全局模块片段</i>。</div>
|
|
<div class="t-li1"><span class="t-li">8)</span> 开始一个<i>私有模块片段</i>。</div>
|
|
<h3><span class="mw-headline" id=".E6.A8.A1.E5.9D.97.E5.A3.B0.E6.98.8E">模块声明</span></h3>
|
|
<p>翻译单元可以有一个模块声明,这种情况下它们被视为<i>模块单元</i>。<i>模块声明</i>在有提供时必须是翻译单元的首个声明(后面提到的<i>全局模块片段</i>除外)。每个模块单元都对应一个<i>模块名</i>(可以带一个分区),它在模块声明中提供。</p>
|
|
<table>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td class="t-sdsc-nopad"><code><b>export</b></code><span class="t-mark">(可选)</span> <code><b>module</b></code> <span class="t-spar">模块名</span> <span class="t-spar">模块分区</span><span class="t-mark">(可选)</span> <span class="t-spar">属性</span><span class="t-mark">(可选)</span> <code><b>;</b></code></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
</table>
|
|
<p>模块名包含由点分隔的一个或多个标识符(例如:<code>mymodule</code>,<code>mymodule.mysubmodule</code>,<code>mymodule2</code>...)。点没有内在含义,不过它们会非正式地用于表示继承关系。</p>
|
|
<p>一个<i>具名模块</i>是一组模块名相同的模块单元。</p>
|
|
<p>声明中带有关键词 <code><b>export</b></code> 的模块单元是<i>模块接口单元</i>。其他模块单元被称为<i>模块实现单元</i>。</p>
|
|
<p>对于每个具名模块,必须有恰好一个未指定模块分区的模块接口单元。这个模块单元被称为<i>主模块接口单元</i>。在导入对应的具名模块时可以使用它导出的内容。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co1">// (每行表示一个单独的翻译单元)</span>
|
|
|
|
export module A<span class="sy4">;</span> <span class="co1">// 为具名模块 'A' 声明主模块接口单元</span>
|
|
module A<span class="sy4">;</span> <span class="co1">// 为具名模块 'A' 声明一个模块实现单元</span>
|
|
module A<span class="sy4">;</span> <span class="co1">// 为具名模块 'A' 声明另一个模块实现单元</span>
|
|
export module A.<span class="me1">B</span><span class="sy4">;</span> <span class="co1">// 为具名模块 'A.B' 声明主模块接口单元</span>
|
|
module A.<span class="me1">B</span><span class="sy4">;</span> <span class="co1">// 为具名模块 'A.B' 声明一个模块实现单元</span></pre></div>
|
|
</div>
|
|
<h3><span class="mw-headline" id=".E5.AF.BC.E5.87.BA.E5.A3.B0.E6.98.8E.E5.92.8C.E5.AE.9A.E4.B9.89">导出声明和定义</span></h3>
|
|
<p>模块接口单元可以导出声明和定义,这些内容可以导入到其他翻译单元。它们可以有 <code><b>export</b></code> 关键词作为前缀,或者处于 <code><b>export</b></code> 块中。</p>
|
|
<table class="t-sdsc-begin">
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td class="t-sdsc-nopad"><code><b>export</b></code> <span class="t-spar">声明</span></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td class="t-sdsc-nopad"><code><b>export</b></code> <code><b>{</b></code> <span class="t-spar">声明序列</span><span class="t-mark">(可选)</span> <code><b>}</b></code></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
</table>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1">export module A<span class="sy4">;</span> <span class="co1">// 为具名模块 'A' 声明主模块接口单元</span>
|
|
|
|
<span class="co1">// hello() 会在所有导入 'A' 的翻译单元中可见</span>
|
|
export <span class="kw4">char</span> <span class="kw4">const</span><span class="sy2">*</span> hello<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span> <span class="kw1">return</span> <span class="st0">"hello"</span><span class="sy4">;</span> <span class="br0">}</span>
|
|
|
|
<span class="co1">// world() 不可见</span>
|
|
<span class="kw4">char</span> <span class="kw4">const</span><span class="sy2">*</span> world<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span> <span class="kw1">return</span> <span class="st0">"world"</span><span class="sy4">;</span> <span class="br0">}</span>
|
|
|
|
<span class="co1">// one() 和 zero() 均可见</span>
|
|
export <span class="br0">{</span>
|
|
<span class="kw4">int</span> one<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span> <span class="kw1">return</span> <span class="nu0">1</span><span class="sy4">;</span> <span class="br0">}</span>
|
|
<span class="kw4">int</span> zero<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span> <span class="kw1">return</span> <span class="nu0">0</span><span class="sy4">;</span> <span class="br0">}</span>
|
|
<span class="br0">}</span>
|
|
|
|
<span class="co1">// 也可以导出命名空间:hi::english() 和 hi::french() 均可见</span>
|
|
export <span class="kw1">namespace</span> hi <span class="br0">{</span>
|
|
<span class="kw4">char</span> <span class="kw4">const</span><span class="sy2">*</span> english<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span> <span class="kw1">return</span> <span class="st0">"Hi!"</span><span class="sy4">;</span> <span class="br0">}</span>
|
|
<span class="kw4">char</span> <span class="kw4">const</span><span class="sy2">*</span> french<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span> <span class="kw1">return</span> <span class="st0">"Salut!"</span><span class="sy4">;</span> <span class="br0">}</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<h3><span class="mw-headline" id=".E5.AF.BC.E5.85.A5.E6.A8.A1.E5.9D.97.E5.92.8C.E5.A4.B4">导入模块和头</span></h3>
|
|
<p>模块可以通过<i>导入声明</i>导入:</p>
|
|
<table class="t-sdsc-begin">
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td class="t-sdsc-nopad"><code><b>export</b></code><span class="t-mark">(可选)</span> <code><b>import</b></code> <span class="t-spar">模块名</span> <span class="t-spar">属性</span><span class="t-mark">(可选)</span> <code><b>;</b></code></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
</table>
|
|
<p>所有在给定具名模块的模块接口单元中导出的声明和定义都会在使用导入声明的翻译单元中可见。</p>
|
|
<p>导入的声明在模块接口单元里可以再导出。也就是说,如果模块 A 导入 B 后又导出,那么导入 A 也会使所有从 B 导出的内容可见。</p>
|
|
<p>在模块单元里,所有导入声明(包括带导出的导入)必须集中在模块声明后以及所有其他声明前。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co1">/////// A.cpp ('A' 的主模块接口单元)</span>
|
|
export module A<span class="sy4">;</span>
|
|
|
|
export <span class="kw4">char</span> <span class="kw4">const</span><span class="sy2">*</span> hello<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span> <span class="kw1">return</span> <span class="st0">"hello"</span><span class="sy4">;</span> <span class="br0">}</span>
|
|
|
|
<span class="co1">/////// B.cpp ('B' 的主模块接口单元)</span>
|
|
export module B<span class="sy4">;</span>
|
|
|
|
export import A<span class="sy4">;</span>
|
|
|
|
export <span class="kw4">char</span> <span class="kw4">const</span><span class="sy2">*</span> world<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span> <span class="kw1">return</span> <span class="st0">"world"</span><span class="sy4">;</span> <span class="br0">}</span>
|
|
|
|
<span class="co1">/////// main.cpp (非模块单元)</span>
|
|
<span class="co2">#include <iostream></span>
|
|
import B<span class="sy4">;</span>
|
|
|
|
<span class="kw4">int</span> main<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> hello<span class="br0">(</span><span class="br0">)</span> <span class="sy1"><<</span> <span class="st0">' '</span> <span class="sy1"><<</span> world<span class="br0">(</span><span class="br0">)</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<p>在模块单元里(<i>全局模块片段</i>以外)不能使用 <a href="cpp-preprocessor-include.html"><tt>#include</tt></a>,因为所有被包含的声明和定义都会作为模块的一部分。头可以改为通过<i>导入声明</i>导入:</p>
|
|
<table class="t-sdsc-begin">
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td class="t-sdsc-nopad"><code><b>export</b></code><span class="t-mark">(可选)</span> <code><b>import</b></code> <span class="t-spar">头名</span> <span class="t-spar">属性</span><span class="t-mark">(可选)</span> <code><b>;</b></code></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
</table>
|
|
<p>导入一个头文件会使其所有声明和定义可见。预处理宏也会可见(因为预处理器会识别导入声明)。然而与 <code>#include</code> 相反的是,在(导入这个头文件的)翻译单元中定义的预处理宏不会影响头文件的处理。这在某些场合会不方便(某些头文件用预处理宏作为配置方式),这种情况下需要使用<i>全局模块片段</i>。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co1">/////// A.cpp ('A' 的主模块接口单元)</span>
|
|
export module A<span class="sy4">;</span>
|
|
|
|
import <span class="sy1"><</span>iostream<span class="sy1">></span><span class="sy4">;</span>
|
|
export import <span class="sy1"><</span>string_view<span class="sy1">></span><span class="sy4">;</span>
|
|
|
|
export <span class="kw4">void</span> print<span class="br0">(</span><a href="cpp-string-basic_string_view.html"><span class="kw1248">std::<span class="me2">string_view</span></span></a> message<span class="br0">)</span> <span class="br0">{</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> message <span class="sy1"><<</span> <a href="cpp-io-manip-endl.html"><span class="kw1791">std::<span class="me2">endl</span></span></a><span class="sy4">;</span>
|
|
<span class="br0">}</span>
|
|
|
|
<span class="co1">/////// main.cpp (非模块单元)</span>
|
|
import A<span class="sy4">;</span>
|
|
|
|
<span class="kw4">int</span> main<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
|
|
<a href="cpp-string-basic_string_view.html"><span class="kw1248">std::<span class="me2">string_view</span></span></a> message <span class="sy1">=</span> <span class="st0">"Hello, world!"</span><span class="sy4">;</span>
|
|
print<span class="br0">(</span>message<span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<h3><span class="mw-headline" id=".E5.85.A8.E5.B1.80.E6.A8.A1.E5.9D.97.E7.89.87.E6.AE.B5">全局模块片段</span></h3>
|
|
<p>模块单元可以有<i>全局模块片段</i>前缀,它可以在无法导入头文件时(尤其是在头文件用预处理宏进行配置时)包含它们。</p>
|
|
<table class="t-sdsc-begin">
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td class="t-sdsc-nopad"><code><b>module;</b></code>
|
|
<p><span class="t-spar">预处理指令序列</span><span class="t-mark">(可选)</span></p>
|
|
<p><span class="t-spar">模块声明</span></p>
|
|
</td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
</table>
|
|
<p>如果一个模块单元有一个全局模块片段,那么它的首个声明必须是 <code><b>module;</b></code>。然后在全局模块片段中只能出现<a href="cpp-preprocessor.html#.E6.8C.87.E4.BB.A4">预处理指令</a>。然后用一个标准的模块声明结束这个全局模块片段,后面就是模块内容。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co1">/////// A.cpp ('A' 的主模块接口单元)</span>
|
|
module<span class="sy4">;</span>
|
|
|
|
<span class="co1">// 按照 POSIX 标准,定义 _POSIX_C_SOURCE 会向标准头中添加函数。</span>
|
|
<span class="co2">#define _POSIX_C_SOURCE 200809L</span>
|
|
<span class="co2">#include <stdlib.h></span>
|
|
|
|
export module A<span class="sy4">;</span>
|
|
|
|
import <span class="sy1"><</span>ctime<span class="sy1">></span><span class="sy4">;</span>
|
|
|
|
<span class="co1">// 仅用于演示(差的随机源)。应改为使用 C++ <random>。</span>
|
|
export <span class="kw4">double</span> weak_random<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
|
|
<a href="cpp-chrono-c-timespec.html"><span class="kw1026">std::<span class="me2">timespec</span></span></a> ts<span class="sy4">;</span>
|
|
<a href="cpp-chrono-c-timespec_get.html"><span class="kw1013">std::<span class="me2">timespec_get</span></span></a><span class="br0">(</span><span class="sy3">&</span>ts, <a href="cpp-chrono-c-timespec_get.html"><span class="kw1014">TIME_UTC</span></a><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 来自 <ctime></span>
|
|
<span class="co1">// 按照 POSIX 标准从 <stdlib.h> 提供。</span>
|
|
srand48<span class="br0">(</span>ts.<span class="me1">tv_nsec</span><span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="co1">// drand48() 返回 0 与 1 之间的一个随机数</span>
|
|
<span class="kw1">return</span> drand48<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="br0">}</span>
|
|
|
|
<span class="co1">/////// main.cpp (非模块单元)</span>
|
|
import <span class="sy1"><</span>iostream<span class="sy1">></span><span class="sy4">;</span>
|
|
import A<span class="sy4">;</span>
|
|
|
|
<span class="kw4">int</span> main<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"0 与 1 之间的随机值:"</span> <span class="sy1"><<</span> weak_random<span class="br0">(</span><span class="br0">)</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<h3><span class="mw-headline" id=".E6.A8.A1.E5.9D.97.E5.88.86.E5.8C.BA">模块分区</span></h3>
|
|
<p>一个模块可以有<i>模块分区单元</i>。它们是模块声明中包含了一个模块分区的模块单元,模块分区在模块名之后,以一个冒号 <code><b>:</b></code> 开头。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1">export module A<span class="sy4">:</span>B<span class="sy4">;</span> <span class="co1">// 为模块 'A' 分区 'B' 声明一个模块接口单元。</span></pre></div>
|
|
</div>
|
|
<p>一个模块分区表示恰好一个模块单元(两个模块单元不能指定同一个模块分区)。它们只在自己所在的具名模块内部可见(在该具名模块外的翻译单元不能直接导入这些模块分区)。</p>
|
|
<p>模块分区只能被相同具名模块的模块单元导入。</p>
|
|
<table class="t-sdsc-begin">
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td class="t-sdsc-nopad"><code><b>export</b></code><span class="t-mark">(可选)</span> <code><b>import</b></code> <span class="t-spar">模块分区</span> <span class="t-spar">属性</span><span class="t-mark">(可选)</span> <code><b>;</b></code></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
</table>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co1">/////// A-B.cpp </span>
|
|
export module A<span class="sy4">:</span>B<span class="sy4">;</span>
|
|
...
|
|
|
|
<span class="co1">/////// A-C.cpp</span>
|
|
module A<span class="sy4">:</span>C<span class="sy4">;</span>
|
|
...
|
|
|
|
<span class="co1">/////// A.cpp</span>
|
|
export module A<span class="sy4">;</span>
|
|
|
|
import <span class="sy4">:</span>C<span class="sy4">;</span>
|
|
export import <span class="sy4">:</span>B<span class="sy4">;</span>
|
|
|
|
...</pre></div>
|
|
</div>
|
|
<p>模块分区内的所有声明和定义在将其导入的模块单元中均可见,无论它们是否被导出。</p>
|
|
<p>模块分区可以是模块接口单元(如果模块声明中有 <code><b>export</b></code>)。它们必须被主模块接口单元在导入同时导出,并且它们导出的语句在模块被导入时均可见。</p>
|
|
<table class="t-sdsc-begin">
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td class="t-sdsc-nopad"><code><b>export</b></code><span class="t-mark">(可选)</span> <code><b>import</b></code> <span class="t-spar">模块分区</span> <span class="t-spar">属性</span><span class="t-mark">(可选)</span> <code><b>;</b></code></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
</table>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co1">/////// A.cpp </span>
|
|
export module A<span class="sy4">;</span> <span class="co1">// 主模块接口单元</span>
|
|
|
|
export import <span class="sy4">:</span>B<span class="sy4">;</span> <span class="co1">// Hello() 在导入 'A' 时可见</span>
|
|
import <span class="sy4">:</span>C<span class="sy4">;</span> <span class="co1">// 现在 WorldImpl() 只对 'A.cpp' 可见</span>
|
|
<span class="co1">// export import :C; // 错误:无法导出模块实现单元</span>
|
|
|
|
<span class="co1">// World() 对所有导入 'A' 的翻译单元均可见</span>
|
|
export <span class="kw4">char</span> <span class="kw4">const</span><span class="sy2">*</span> World<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
|
|
<span class="kw1">return</span> WorldImpl<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co1">/////// A-B.cpp </span>
|
|
export module A<span class="sy4">:</span>B<span class="sy4">;</span> <span class="co1">// 模块分区接口单元</span>
|
|
|
|
<span class="co1">// Hello() 对所有导入 'A' 的翻译单元均可见</span>
|
|
export <span class="kw4">char</span> <span class="kw4">const</span><span class="sy2">*</span> Hello<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span> <span class="kw1">return</span> <span class="st0">"Hello"</span><span class="sy4">;</span> <span class="br0">}</span></pre></div>
|
|
</div>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co1">/////// A-C.cpp </span>
|
|
module A<span class="sy4">:</span>C<span class="sy4">;</span> <span class="co1">// 模块分区实现单元</span>
|
|
|
|
<span class="co1">// WorldImpl() 对 'A' 中所有导入 ':C' 的翻译单元均可见</span>
|
|
<span class="kw4">char</span> <span class="kw4">const</span><span class="sy2">*</span> WorldImpl<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span> <span class="kw1">return</span> <span class="st0">"World"</span><span class="sy4">;</span> <span class="br0">}</span></pre></div>
|
|
</div>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co1">/////// main.cpp </span>
|
|
import A<span class="sy4">;</span>
|
|
import <span class="sy1"><</span>iostream<span class="sy1">></span><span class="sy4">;</span>
|
|
|
|
<span class="kw4">int</span> main<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> Hello<span class="br0">(</span><span class="br0">)</span> <span class="sy1"><<</span> <span class="st0">' '</span> <span class="sy1"><<</span> World<span class="br0">(</span><span class="br0">)</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
<span class="co1">// WorldImpl(); // 错误:WorldImpl() 不可见</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<h3><span class="mw-headline" id=".E5.85.B3.E9.94.AE.E8.AF.8D">关键词</span></h3>
|
|
<p><a href="cpp-keyword-export.html"><tt>export</tt></a>,<a href="cpp-keyword-import.html"><tt>import</tt></a>,<a href="https://zh.cppreference.com/mwiki/index.php?title=cpp/keyword/module&action=edit&redlink=1" class="new" title="cpp/keyword/module(页面不存在)"><tt>module</tt></a></p>
|
|
</div>
|
|
<div class="visualClear"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|