⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 item_095.htm

📁 C++程序编写规范,适合C++中级读者
💻 HTM
📖 第 1 页 / 共 2 页
字号:
"Times New Roman"'>能看到</span><span lang=EN-US>Derived</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>的定义(比如通过包含</span><span lang=EN-US>&quot;<span class=SpellE>derived.h</span>&quot;</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>),那么编译器就能得到所需的对象布局的信息,并在把</span><span lang=EN-US>Base</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>转型到</span><span lang=EN-US>Derived</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>时根据该信息对指针进行调整。但是如果</span><span lang=EN-US>Gun</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>的作者忘了</span><span lang=EN-US>#include</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>适当的定义文件,并且</span><span lang=EN-US>Gun</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>只看到一个前置声明</span><span lang=EN-US>class Derived;</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>,那么在这种情况下,编译器会假定</span><span lang=EN-US>Base</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>和</span><span lang=EN-US>Derived</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>是互不相关的类型,并把</span><span lang=EN-US>Base*</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>的位元表示重新解释为</span><span lang=EN-US>Derived*</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>,而不会根据对象的布局对指针进行必要的调整!</span></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>简而言之,如果你忘记了</span><span lang=EN-US>#include</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>定义,那么虽然代码能够顺利通过编译,但是却会奇怪地崩溃。可以这样避免此问题:</span></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal style='margin-left:36.0pt'><span class=GramE><span
lang=EN-US>extern</span></span><span lang=EN-US> void Fun( Derived* );</span></p>

<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal style='margin-left:36.0pt'><span class=GramE><span
lang=EN-US>void</span></span><span lang=EN-US> Gun( Base* <span class=SpellE>pb</span>
) {</span></p>

<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'>&nbsp;</span><span
style='mso-spacerun:yes'>&nbsp;&nbsp; </span><i style='mso-bidi-font-style:
normal'>// </i></span><i style='mso-bidi-font-style:normal'><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>如果我们清楚地知道</span><span class=SpellE><span lang=EN-US>pb</span></span></i><i
style='mso-bidi-font-style:normal'><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>实际指向</span><span
lang=EN-US>Derived</span></i><i style='mso-bidi-font-style:normal'><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>,那么可以用:</span><span lang=EN-US><o:p></o:p></span></i></p>

<p class=MsoNormal style='margin-left:36.0pt;tab-stops:288.0pt'><span
lang=EN-US><span style='mso-spacerun:yes'>&nbsp;</span><span
style='mso-spacerun:yes'>&nbsp;&nbsp; </span>Derived* pd = <span class=SpellE>static_cast</span>&lt;Derived*&gt;(<span
class=SpellE>pb</span>);<span style='mso-tab-count:1'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><i
style='mso-bidi-font-style:normal'>// </i></span><i style='mso-bidi-font-style:
normal'><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>较好:</span><span lang=EN-US>C++</span></i><i
style='mso-bidi-font-style:normal'><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>风格的转换</span></i></p>

<p class=MsoNormal style='margin-left:36.0pt;tab-stops:288.0pt'><span
lang=EN-US><span style='mso-spacerun:yes'>&nbsp;</span><span
style='mso-spacerun:yes'>&nbsp;&nbsp; </span><i style='mso-bidi-font-style:
normal'>// </i></span><i style='mso-bidi-font-style:normal'><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>或者:</span><span lang=EN-US> = <span class=SpellE>dynamic_cast</span>&lt;Derived*&gt;(<span
class=SpellE>pb</span>);<span style='mso-tab-count:1'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//
</span></i><i style='mso-bidi-font-style:normal'><span style='font-family:宋体;
mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:"Times New Roman"'>较好:</span><span
lang=EN-US>C++</span></i><i style='mso-bidi-font-style:normal'><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>风格的转换</span><span lang=EN-US><o:p></o:p></span></i></p>

<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'>&nbsp;</span><span
style='mso-spacerun:yes'>&nbsp;&nbsp; </span><span class=GramE>Fun(</span>pd);</span></p>

<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US>}</span></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>现在,如果编译器没有足够的静态信息来确定</span><span
lang=EN-US>Base</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>和</span><span lang=EN-US>Derived</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>之间的相互关系,那么它会报告一个错误,而不会自动地执行基于位元的(也是潜在的致命因素)</span><span
class=SpellE><span lang=EN-US>reinterpret_cast</span></span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>(参见第</span><span lang=EN-US>92</span><span style='font-family:
宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:"Times New Roman"'>条)。</span></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal><span lang=EN-US>C++</span><span style='font-family:宋体;
mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:"Times New Roman"'>风格的强制类型转换还可以在系统演化的过程中保护你的代码。比如你有一个以</span><span
lang=EN-US>Employee</span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>为基类的继承体系,需要给每个</span><span
lang=EN-US>Employee</span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>定义一个唯一的</span><span
lang=EN-US>employee ID</span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>。可以将</span><span
lang=EN-US>ID</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>定义为指向</span><span lang=EN-US>Employee</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>自己的指针。指针唯一地标识了它所指向的对象,同时可以用来比较是否相同,这恰好是你需要的。所以你编写了下面的代码:</span></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal style='margin-left:36.0pt'><span class=SpellE><span
class=GramE><span lang=EN-US>typedef</span></span></span><span lang=EN-US>
Employee* <span class=SpellE>EmployeeID</span>;</span></p>

<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US>Employee&amp; <span
class=GramE>Fetch(</span> <span class=SpellE>EmployeeID</span> id ) {</span></p>

<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'>&nbsp;</span><span
style='mso-spacerun:yes'>&nbsp;&nbsp; </span><span class=GramE>return</span>
*id;</span></p>

<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US>}</span></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>假设你只编写了这整个设计中的一小部分代码。稍后,你发现需要把记录保存到一个关系型数据库中。很明显你不想保存指针,所以你修改了设计,用唯一的整数值来标识每个</span><span
lang=EN-US>employee</span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>。这样这些整数</span><span
lang=EN-US>ID</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>就可以被保存到数据库中,并用一个哈希表把</span><span
lang=EN-US>ID</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>映射到</span><span lang=EN-US>Employee</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>对象。现在的</span><span class=SpellE><span lang=EN-US>typedef</span></span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>就变成了:</span></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal style='margin-left:36.0pt'><span class=SpellE><span
class=GramE><span lang=EN-US>typedef</span></span></span><span lang=EN-US> <span
class=SpellE>int</span> <span class=SpellE>EmployeeID</span>;</span></p>

<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US>Employee&amp; <span
class=GramE>Fetch(</span> <span class=SpellE>EmployeeID</span> id ) {</span></p>

<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'>&nbsp;</span><span
style='mso-spacerun:yes'>&nbsp;&nbsp; </span><span class=GramE>return</span> <span
class=SpellE>employeeTable_.lookup</span>(id);</span></p>

<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US>}</span></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>这是个正确的设计,你也认为所有对</span><span
class=SpellE><span lang=EN-US>EmployeeID</span></span><span style='font-family:
宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:"Times New Roman"'>的误用应该会引起编译错误。的确是这样,除了下面这段有点晦涩的代码:</span></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal style='margin-left:36.0pt'><span class=GramE><span
lang=EN-US>void</span></span><span lang=EN-US> <span class=SpellE>TooCoolToUseNewCasts</span>(
<span class=SpellE>EmployeeID</span> id ) {</span></p>

<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'>&nbsp;</span><span
style='mso-spacerun:yes'>&nbsp;&nbsp; </span>Secretary* <span class=SpellE>pSecretary</span>
= (Secretary*)id; <span style='mso-spacerun:yes'>&nbsp;&nbsp;&nbsp;</span><i
style='mso-bidi-font-style:normal'>// </i></span><i style='mso-bidi-font-style:
normal'><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>糟糕:</span><span lang=EN-US>C</span></i><i
style='mso-bidi-font-style:normal'><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>风格的强制类型转换</span></i></p>

<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'>&nbsp;</span><span
style='mso-spacerun:yes'>&nbsp;&nbsp; </span><i style='mso-bidi-font-style:
normal'>// …<o:p></o:p></i></span></p>

<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US>}</span></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>用老的</span><span class=SpellE><span
lang=EN-US>typedef</span></span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>时,</span><span
lang=EN-US>C</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>风格的强制类型转换会执行一个</span><span
class=SpellE><span lang=EN-US>static_cast</span></span><span style='font-family:
宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:"Times New Roman"'>,而用新的</span><span
class=SpellE><span lang=EN-US>typedef</span></span><span style='font-family:
宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:"Times New Roman"'>时,它会对一个整数值执行一个</span><span
class=SpellE><span lang=EN-US>reinterpret_cast</span></span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>,其结果毫无疑问是未定义的行为(参见第</span><span lang=EN-US>92</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>条)。</span></p>

<p class=MsoNormal><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>用一些自动化的工具如</span><span class=SpellE><span
lang=EN-US>grep</span></span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>,可以很容易地搜寻</span><span
lang=EN-US>C++</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>风格的强制类型转换(没有哪个</span><span
class=SpellE><span lang=EN-US>grep</span></span><span style='font-family:宋体;
mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:"Times New Roman"'>正则表达式可以找到</span><span
lang=EN-US>C</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>风格的强制类型转换)。因为强制类型转换是危险的(尤其是</span><span
class=SpellE><span lang=EN-US>reinterpret_cast</span></span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>和对指针使用</span><span class=SpellE><span lang=EN-US>static_cast</span></span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>,参见第</span><span lang=EN-US>92</span><span style='font-family:
宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:"Times New Roman"'>条),所以用自动化的工具来留意它们是个不错的办法。</span></p>

</div>

</body>

</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -