📄 item_090.htm
字号:
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal><b style='mso-bidi-font-weight: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></b></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal><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><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
lang=EN-US>id_</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> </o:p></span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span class=GramE><span
lang=EN-US>class</span></span><span lang=EN-US> Shape { <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
style='mso-spacerun:yes'> </span><span
style='mso-spacerun:yes'> </span><span class=SpellE><span
class=GramE>enum</span></span> {RECTANGLE, TRIANGLE, CIRCLE }id_;</span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'> </span><span
style='mso-spacerun:yes'> </span><span class=GramE>void</span>
Draw() const {</span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'> </span><span
style='mso-spacerun:yes'> </span>switch( id_ )
{<span
style='mso-spacerun:yes'>
</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></i></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'> </span><span
style='mso-spacerun:yes'> </span><span
class=GramE>case</span> RECTANGLE:</span></p>
<p class=MsoNormal style='margin-left:36.0pt'><i style='mso-bidi-font-style:
normal'><span lang=EN-US><span
style='mso-spacerun:yes'> </span><span
style='mso-spacerun:yes'> </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> …<o:p></o:p></span></i></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'> </span><span
style='mso-spacerun:yes'> </span><span class=GramE>break</span>;</span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'> </span><span
style='mso-spacerun:yes'> </span><span class=GramE>case</span>
TRIANGLE:</span></p>
<p class=MsoNormal style='margin-left:36.0pt'><i style='mso-bidi-font-style:
normal'><span lang=EN-US><span
style='mso-spacerun:yes'> </span><span
style='mso-spacerun:yes'> </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>…<o:p></o:p></span></i></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'> </span><span
style='mso-spacerun:yes'> </span><span class=GramE>break</span>;</span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'> </span><span
style='mso-spacerun:yes'> </span><span class=GramE>case</span>
CIRCLE:</span></p>
<p class=MsoNormal style='margin-left:36.0pt'><i style='mso-bidi-font-style:
normal'><span lang=EN-US><span
style='mso-spacerun:yes'> </span><span
style='mso-spacerun:yes'> </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>…<o:p></o:p></span></i></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'> </span><span
style='mso-spacerun:yes'> </span><span class=GramE>break</span>;</span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'> </span><span
style='mso-spacerun:yes'> </span>default:<span
style='mso-spacerun:yes'>
</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></i></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'> </span><span
style='mso-spacerun:yes'> </span><span class=GramE>assert(</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>switch</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>语句了</span><span lang=EN-US>" ); </span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'> </span><span
style='mso-spacerun:yes'> </span><span class=GramE>break</span>;</span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'> </span><span
style='mso-spacerun:yes'> </span>}</span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'> </span><span
style='mso-spacerun:yes'> </span>}</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> </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>22</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>条提到的可怕而具传递性的循环依赖性。</span><span
lang=EN-US>default</span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>分支是“不知道如何处理该类型”综合症的症状。拿这个实现和可以从任何</span><span
lang=EN-US>OO</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> </o:p></span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span class=GramE><span
lang=EN-US>class</span></span><span lang=EN-US> Shape { <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
style='mso-spacerun:yes'> </span><span
style='mso-spacerun:yes'> </span>virtual void Draw() const = 0;<span
style='mso-tab-count:1'> </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></i></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US>};</span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </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>64</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> </o:p></span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span class=GramE><span
lang=EN-US>template<</span></span><span lang=EN-US>class S></span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span class=GramE><span
lang=EN-US>void</span></span><span lang=EN-US> Draw( const S& shape ) {</span></p>
<p class=MsoNormal style='margin-left:36.0pt;tab-stops:144.0pt'><span
lang=EN-US><span style='mso-spacerun:yes'> </span><span
style='mso-spacerun:yes'> </span><span class=SpellE>shape.Draw</span>();<span
style='mso-tab-count:1'> </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></i></p>
<p class=MsoNormal style='margin-left:36.0pt;tab-stops:144.0pt'><span
lang=EN-US>};<span style='mso-tab-count:1'> </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>64</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><span lang=EN-US><o:p> </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></p>
</div>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -