虚拟实验室-Unreal 版本

虚拟实验室的Unreal 版本,第一个版本主要是以《探究通电螺线管外部的磁场分布》颗粒为例,设计和开发一个正式版本。


类静态变量的声明和定义问题

<table> <thead> <tr> <th>作者</th> <th>范丽民(969618)</th> </tr> </thead> <tbody> <tr> <td>更新时间</td> <td>2024-7-25</td> </tr> <tr> <td>版本</td> <td>V0.0.1</td> </tr> </tbody> </table> <h1>类静态变量的声明和定义问题</h1> <h1>问题1:</h1> <p>静态变量声明未定义 , 编译报LNK2019和 LNK2001错误</p> <pre><code class="language-cpp">//Debugger.h 没有Debugger.cpp class VLABUE_GENERALABILITY_API FDebugger { protected: static bool bShowScreen; }</code></pre> <p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=8891b59156a8208cdbbdef56d4e80896&amp;amp;file=file.png" alt="" /></p> <h2>分析原因</h2> <p>当在类中声明一个静态变量时,只是告诉编译器这个变量存在,但没有为其分配内存。为了实际使用这个变量,需要对其进行定义,这样编译器才能为其分配内存并初始化它。</p> <h2>为什么会出现不同的链接器错误?</h2> <p>LNK2019 错误通常出现在尝试使用未定义的符号时,例如 SampleWidget.cpp 尝试使用 FDebugger::bShowScreen,但是找不到其定义。 LNK2001 错误通常出现在链接过程中发现有多个文件都引用了同一个未定义的符号,例如 ResourceManager.gen.cpp 和其他文件都引用了 FDebugger::bShowScreen,但找不到其定义。</p> <h1>问题2:</h1> <p>静态变量声明且在头文件中定义,window打包没问题,android打包报重复定义错误。</p> <pre><code class="language-cpp">//Debugger.h class VLABUE_GENERALABILITY_API FDebugger { protected: static bool bShowScreen; } //定义也在Debugger.h文件里 FDebugger::bShowScreen = false;</code></pre> <p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign cca57cd55f6f4d2f38c5b395a271f9&amp;amp;file=file.png" alt="" /></p> <h2>分析原因</h2> <p>Windows平台(使用的Microsoft Visual C++编译器)在处理静态同一文件里的成员变量定义时做了编译优化,避免了重复定义问题。 Android平台 (使用 Clang 作为编译器)严格遵循C++标准,不允许静态变量的定义和声明放到同一个文件中</p> <h1>解决方案:</h1> <p>这两个问题都属于静态变量的声明和定义问题,解决方案是相同的。</p> <h2>方案1 使用inline 在头文件中直接声明+定义</h2> <p>C++17 之后的版本支持用inline方式避免重复定义,而且可以简化代码,提高可读性 ```c++ class VLABUE_GENERALABILITY_API FDebugger { protected: inline static bool bShowScreen = false; }</p> <pre><code>## 方案2 在对应的cpp文件中定义 ```c++ //Debugger.cpp 文件 FDebugger::bShowScreen = false;</code></pre> <h1>注意点:模板类</h1> <p>模板类的静态成员变量需要在头文件中同时声明和定义。 因为模板类的实例化是在使用它们的编译单元中进行的,而不是在模板类本身的定义处进行的。 如果模板类的静态成员变量的定义不在头文件中,那么每个使用该模板的编译单元都不会知道这个静态成员变量的定义,从而导致链接错误。 ```c++ //Singleton.h //模板类的声明和定义必须在一个头文件中 template &lt;typename T&gt; class TSingleton { private: //声明 static T<em> Instance; }; //定义 template &lt;typename T&gt; T</em> TSingleton&lt;T&gt;::Instance = nullptr;</p> <pre><code></code></pre>

页面列表

ITEM_HTML