Skip to content

Commit a9fc30e

Browse files
committed
deploy: 07494f6
1 parent f24b61b commit a9fc30e

File tree

5 files changed

+23
-3
lines changed

5 files changed

+23
-3
lines changed

design_gamedev/index.html

+10
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,10 @@ <h3 id="_3">封装在类内部</h3>
349349

350350
Game::instance.updatePlayers();
351351
</code></pre>
352+
<blockquote>
353+
<p><img src="../img/warning.png" height="30px" width="auto" style="margin: 0; border: none"/> 警告:只定义在头文件中并使用 <code>inline</code> 这种写法,不适用于多 DLL 的情况!这会使 DLL 和 EXE 各自持有一份互不共通的 <code>instance</code>。如果需要在多 DLL 环境中使用这种饿汗模式单例,请乖乖<a href="../symbols/">分离声明和定义</a>,别用 <code>inline</code> 了。</p>
354+
<p><img src="../img/question.png" height="30px" width="auto" style="margin: 0; border: none"/> 这是因为 Windows 中的每个 DLL 和 EXE 都是一座孤岛,互相不知道对方有没有这个符号,所以 <code>inline</code> 的效果从“全局只保留一份定义”变成在每个“孤岛”内各自在内部只保留一份,从而 DLL 和 EXE 各自一份,总共有两份了,互相内容不互通,从而不是单例模式。而 Linux 没有这个问题,因为 SO 动态库是运行时才由 <code>ld-linux.so</code> 完成链接的,SO 内部仍保有编译时产生的函数符号信息,为的是被可执行 ELF 加载进来以后,<code>ld-linux.so</code> 可以自动根据把可执行 ELF 和 SO 内部的 <code>call</code> 指令后的地址更新为加载后的符号的动态地址。而 Windows 的 DLL 中所有符号在编译时就已经被 <code>ld</code> 已经焊死,无法修改,这就是为什么 Windows 的每个 DLL 都会自动额外生成一个同名 LIB 文件,这个 LIB 里面实际上是一个个“插桩”函数,这些函数名字和 DLL 中的相同,但是函数的内容,是会动态 <code>LoadLibrary</code> 加载同名 DLL,并通过 <code>GetProcAddress</code> 动态获取所有 <code>dllexport</code> 的函数,而链接时候指定的实际上是原 DLL 对应的这个插桩 LIB,DLL 本身是无法被链接器链接的。</p>
355+
</blockquote>
352356
<ol start="2">
353357
<li>作为函数内部的 static 变量(懒汗模式)</li>
354358
</ol>
@@ -369,6 +373,9 @@ <h3 id="_3">封装在类内部</h3>
369373

370374
Game::instance().updatePlayers();
371375
</code></pre>
376+
<blockquote>
377+
<p><img src="../img/warning.png" height="30px" width="auto" style="margin: 0; border: none"/> 警告:这种写法同样不适用于多 DLL 的情况!如果需要在多 DLL 环境中使用,请乖乖<a href="../symbols/">分离声明和定义</a></p>
378+
</blockquote>
372379
<h3 id="_4">通用的单例模式模板</h3>
373380
<pre><code class="language-cpp">template &lt;class T&gt;
374381
inline T &amp;singleton() { // 这里的 inline 可以省略,因为就地实现的模板函数自带 inline 效果
@@ -382,6 +389,9 @@ <h3 id="_4">通用的单例模式模板</h3>
382389
singleton&lt;Other&gt;().someMethod();
383390
</code></pre>
384391
<p>任何类型 T,只要以 <code>singleton&lt;T&gt;()</code> 形式获取,都能保证每个 T 都只有一份对象。(前提是你不要再 <code>T()</code> 创建对象)</p>
392+
<blockquote>
393+
<p><img src="../img/warning.png" height="30px" width="auto" style="margin: 0; border: none"/> 警告:这种写法同样不适用于多 DLL 的情况!如果需要在多 DLL 环境中使用,请乖乖<a href="../symbols/">分离模板的声明和定义</a></p>
394+
</blockquote>
385395
<h2 id="_5">模板模式</h2>
386396
<blockquote>
387397
<p>注意:模板模式和 C++ 的模板并没有必然关系!模板模式只是一种思想,可以用模板实现,也可以用虚函数实现(大多反而是用虚函数实现的)</p>

index.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ <h2 id="_1">前言</h2>
292292
<blockquote>
293293
<p><img src="./img/bulb.png" height="30px" width="auto" style="margin: 0; border: none"/> 本书还在持续更新中……要追番的话,可以在 <a href="https://github.com/parallel101/cppguidebook">GitHub</a> 点一下右上角的 “Watch” 按钮,每当小彭老师提交新 commit,GitHub 会向你发送一封电子邮件,提醒你小彭老师更新了。</p>
294294
</blockquote>
295-
<p>更新时间:2024年10月31日 18:07:26 (UTC+08:00)</p>
295+
<p>更新时间:2024年11月01日 12:54:16 (UTC+08:00)</p>
296296
<p><a href="https://parallel101.github.io/cppguidebook">在 GitHub Pages 浏览本书</a> | <a href="https://142857.red/book">在小彭老师自己维护的镜像上浏览本书</a></p>
297297
<h2 id="_2">格式约定</h2>
298298
<blockquote>

print_page/index.html

+11-1
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ <h2 id="index-_1">前言</h2>
421421
<blockquote>
422422
<p><img src="../img/bulb.png" height="30px" width="auto" style="margin: 0; border: none"/> 本书还在持续更新中……要追番的话,可以在 <a href="https://github.com/parallel101/cppguidebook">GitHub</a> 点一下右上角的 “Watch” 按钮,每当小彭老师提交新 commit,GitHub 会向你发送一封电子邮件,提醒你小彭老师更新了。</p>
423423
</blockquote>
424-
<p>更新时间:2024年10月31日 18:07:26 (UTC+08:00)</p>
424+
<p>更新时间:2024年11月01日 12:54:16 (UTC+08:00)</p>
425425
<p><a href="https://parallel101.github.io/cppguidebook">在 GitHub Pages 浏览本书</a> | <a href="https://142857.red/book">在小彭老师自己维护的镜像上浏览本书</a></p>
426426
<h2 id="index-_2">格式约定</h2>
427427
<blockquote>
@@ -13181,6 +13181,10 @@ <h3 id="design_gamedev-_3">封装在类内部</h3>
1318113181

1318213182
Game::instance.updatePlayers();
1318313183
</code></pre>
13184+
<blockquote>
13185+
<p><img src="../img/warning.png" height="30px" width="auto" style="margin: 0; border: none"/> 警告:只定义在头文件中并使用 <code>inline</code> 这种写法,不适用于多 DLL 的情况!这会使 DLL 和 EXE 各自持有一份互不共通的 <code>instance</code>。如果需要在多 DLL 环境中使用这种饿汗模式单例,请乖乖<a href="#symbols">分离声明和定义</a>,别用 <code>inline</code> 了。</p>
13186+
<p><img src="../img/question.png" height="30px" width="auto" style="margin: 0; border: none"/> 这是因为 Windows 中的每个 DLL 和 EXE 都是一座孤岛,互相不知道对方有没有这个符号,所以 <code>inline</code> 的效果从“全局只保留一份定义”变成在每个“孤岛”内各自在内部只保留一份,从而 DLL 和 EXE 各自一份,总共有两份了,互相内容不互通,从而不是单例模式。而 Linux 没有这个问题,因为 SO 动态库是运行时才由 <code>ld-linux.so</code> 完成链接的,SO 内部仍保有编译时产生的函数符号信息,为的是被可执行 ELF 加载进来以后,<code>ld-linux.so</code> 可以自动根据把可执行 ELF 和 SO 内部的 <code>call</code> 指令后的地址更新为加载后的符号的动态地址。而 Windows 的 DLL 中所有符号在编译时就已经被 <code>ld</code> 已经焊死,无法修改,这就是为什么 Windows 的每个 DLL 都会自动额外生成一个同名 LIB 文件,这个 LIB 里面实际上是一个个“插桩”函数,这些函数名字和 DLL 中的相同,但是函数的内容,是会动态 <code>LoadLibrary</code> 加载同名 DLL,并通过 <code>GetProcAddress</code> 动态获取所有 <code>dllexport</code> 的函数,而链接时候指定的实际上是原 DLL 对应的这个插桩 LIB,DLL 本身是无法被链接器链接的。</p>
13187+
</blockquote>
1318413188
<ol start="2">
1318513189
<li>作为函数内部的 static 变量(懒汗模式)</li>
1318613190
</ol>
@@ -13201,6 +13205,9 @@ <h3 id="design_gamedev-_3">封装在类内部</h3>
1320113205

1320213206
Game::instance().updatePlayers();
1320313207
</code></pre>
13208+
<blockquote>
13209+
<p><img src="../img/warning.png" height="30px" width="auto" style="margin: 0; border: none"/> 警告:这种写法同样不适用于多 DLL 的情况!如果需要在多 DLL 环境中使用,请乖乖<a href="#symbols">分离声明和定义</a>。</p>
13210+
</blockquote>
1320413211
<h3 id="design_gamedev-_4">通用的单例模式模板</h3>
1320513212
<pre><code class="language-cpp">template &lt;class T&gt;
1320613213
inline T &amp;singleton() { // 这里的 inline 可以省略,因为就地实现的模板函数自带 inline 效果
@@ -13214,6 +13221,9 @@ <h3 id="design_gamedev-_4">通用的单例模式模板</h3>
1321413221
singleton&lt;Other&gt;().someMethod();
1321513222
</code></pre>
1321613223
<p>任何类型 T,只要以 <code>singleton&lt;T&gt;()</code> 形式获取,都能保证每个 T 都只有一份对象。(前提是你不要再 <code>T()</code> 创建对象)</p>
13224+
<blockquote>
13225+
<p><img src="../img/warning.png" height="30px" width="auto" style="margin: 0; border: none"/> 警告:这种写法同样不适用于多 DLL 的情况!如果需要在多 DLL 环境中使用,请乖乖<a href="#symbols">分离模板的声明和定义</a>。</p>
13226+
</blockquote>
1321713227
<h2 id="design_gamedev-_5">模板模式</h2>
1321813228
<blockquote>
1321913229
<p>注意:模板模式和 C++ 的模板并没有必然关系!模板模式只是一种思想,可以用模板实现,也可以用虚函数实现(大多反而是用虚函数实现的)</p>

search/search_index.json

+1-1
Large diffs are not rendered by default.

sitemap.xml.gz

0 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)