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

📄 c++的多态性实现机制剖析.htm

📁 c++/vc++ 精华文章
💻 HTM
📖 第 1 页 / 共 5 页
字号:
"Times New Roman"'>类的</span><span lang=EN-US>breathe</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>方法。这个时候,就该轮到虚函数登场了。</span></p>

<p class=MsoNormal style='text-indent:21.0pt;line-height:150%'><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>前面输出的结果是因为编译器在编译的时候,就已经确定了对象调用的函数的地址,要解决这个问题就要使用迟绑定(</span><span
lang=EN-US>late binding</span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>)技术。当编译器使用迟绑定时,就会在运行时再去确定对象的类型以及正确的调用函数。而要让编译器采用迟绑定,就要在基类中声明函数时使用</span><span
lang=EN-US>virtual</span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>关键字(注意,这是必须的,很多学员就是因为没有使用虚函数而写出很多错误的例子),这样的函数我们称为虚函数。一旦某个函数在基类中声明为</span><span
lang=EN-US>virtual</span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>,那么在所有的派生类中该函数都是</span><span
lang=EN-US>virtual</span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>,而不需要再显式地声明为</span><span
lang=EN-US>virtual</span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>。</span></p>

<p class=MsoNormal style='text-indent:21.0pt;line-height:150%'><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>下面修改例</span><span lang=EN-US>1-1</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>的代码,将</span><span lang=EN-US>animal</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>类中的</span><span lang=EN-US>breathe()</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>函数声明为</span><span lang=EN-US>virtual</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>,如下:</span></p>

<div style='mso-element:para-border-div;border:none;border-bottom:solid windowtext 1.5pt;
padding:0cm 0cm 1.0pt 0cm'>

<p class=MsoCaption align=center style='text-align:center;border:none;
mso-border-bottom-alt:solid windowtext 1.5pt;padding:0cm;mso-padding-alt:0cm 0cm 1.0pt 0cm'><span
style='font-family:黑体;mso-ascii-font-family:Arial'>例</span><span lang=EN-US>1- </span><!--[if supportFields]><span
lang=EN-US><span style='mso-element:field-begin'></span><span
style='mso-spacerun:yes'>&nbsp;</span>SEQ </span><span style='font-family:黑体;
mso-ascii-font-family:Arial'>例</span><span lang=EN-US>1- \* ARABIC <span
style='mso-element:field-separator'></span></span><![endif]--><span lang=EN-US><span
style='mso-no-proof:yes'>2</span></span><!--[if supportFields]><span
lang=EN-US><span style='mso-element:field-end'></span></span><![endif]--></p>

</div>

<p class=MsoNormal><span lang=EN-US>#include &lt;<span class=SpellE>iostream.h</span>&gt;</span></p>

<p class=MsoNormal><span class=GramE><span lang=EN-US>class</span></span><span
lang=EN-US> animal</span></p>

<p class=MsoNormal><span lang=EN-US>{</span></p>

<p class=MsoNormal><span class=GramE><span lang=EN-US>public</span></span><span
lang=EN-US>:</span></p>

<p class=MsoNormal><span lang=EN-US><span style='mso-tab-count:1'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
class=GramE>void</span> sleep()</span></p>

<p class=MsoNormal><span lang=EN-US><span style='mso-tab-count:1'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>

<p class=MsoNormal><span lang=EN-US><span style='mso-tab-count:2'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
class=SpellE><span class=GramE>cout</span></span>&lt;&lt;&quot;animal
sleep&quot;&lt;&lt;<span class=SpellE>endl</span>;</span></p>

<p class=MsoNormal><span lang=EN-US><span style='mso-tab-count:1'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>

<p class=MsoNormal><span lang=EN-US><span style='mso-tab-count:1'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
class=GramE><b style='mso-bidi-font-weight:normal'>virtual</b></span><b
style='mso-bidi-font-weight:normal'> </b>void breathe()</span></p>

<p class=MsoNormal><span lang=EN-US><span style='mso-tab-count:1'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>

<p class=MsoNormal><span lang=EN-US><span style='mso-tab-count:2'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
class=SpellE><span class=GramE>cout</span></span>&lt;&lt;&quot;animal
breathe&quot;&lt;&lt;<span class=SpellE>endl</span>;</span></p>

<p class=MsoNormal><span lang=EN-US><span style='mso-tab-count:1'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>

<p class=MsoNormal><span lang=EN-US>};</span></p>

<p class=MsoNormal><span class=GramE><span lang=EN-US>class</span></span><span
lang=EN-US> <span class=SpellE>fish:public</span> animal</span></p>

<p class=MsoNormal><span lang=EN-US>{</span></p>

<p class=MsoNormal><span class=GramE><span lang=EN-US>public</span></span><span
lang=EN-US>:</span></p>

<p class=MsoNormal><span lang=EN-US><span style='mso-tab-count:1'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
class=GramE>void</span> breathe()</span></p>

<p class=MsoNormal><span lang=EN-US><span style='mso-tab-count:1'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></p>

<p class=MsoNormal><span lang=EN-US><span style='mso-tab-count:2'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
class=SpellE><span class=GramE>cout</span></span>&lt;&lt;&quot;fish
bubble&quot;&lt;&lt;<span class=SpellE>endl</span>;</span></p>

<p class=MsoNormal><span lang=EN-US><span style='mso-tab-count:1'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>

<p class=MsoNormal><span lang=EN-US>};</span></p>

<p class=MsoNormal><span class=GramE><span lang=EN-US>void</span></span><span
lang=EN-US> main()</span></p>

<p class=MsoNormal><span lang=EN-US>{</span></p>

<p class=MsoNormal><span lang=EN-US><span style='mso-tab-count:1'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
class=GramE>fish</span> <span class=SpellE>fh</span>;</span></p>

<p class=MsoNormal><span lang=EN-US><span style='mso-tab-count:1'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
class=GramE>animal</span> *<span class=SpellE>pAn</span>=&amp;<span
class=SpellE>fh</span>;</span></p>

<p class=MsoNormal><span lang=EN-US><span style='mso-tab-count:1'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
class=SpellE><span class=GramE>pAn</span></span>-&gt;breathe();</span></p>

<div style='mso-element:para-border-div;border:none;border-bottom:solid windowtext 1.5pt;
padding:0cm 0cm 1.0pt 0cm'>

<p class=MsoNormal style='border:none;mso-border-bottom-alt:solid windowtext 1.5pt;
padding:0cm;mso-padding-alt:0cm 0cm 1.0pt 0cm'><span lang=EN-US>}</span></p>

</div>

<p class=MsoNormal style='text-indent:21.0pt;line-height:150%'><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>大家可以再次运行这个程序,你会发现结果是“</span><span lang=EN-US>fish bubble</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>”,也就是根据对象的类型调用了正确的函数。</span></p>

<p class=MsoNormal style='text-indent:21.0pt;line-height:150%'><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>那么当我们将</span><span lang=EN-US>breathe()</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>声明为</span><span lang=EN-US>virtual</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>时,在背后发生了什么呢?</span></p>

<p class=MsoNormal style='text-indent:21.0pt;line-height:150%'><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>编译器在编译的时候,发现</span><span lang=EN-US>animal</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>vtable</span></span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>),该表是一个一维数组,在这个数组中存放每个虚函数的地址。<span
class=GramE>对于例</span></span><span lang=EN-US>1-2</span><span style='font-family:
宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:"Times New Roman"'>的程序,</span><span
lang=EN-US>animal</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>和</span><span lang=EN-US>fish</span><span
class=GramE><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>类都包含</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>breathe()</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>,因此编译器会为这<span class=GramE>两个类都建立</span>一个虚表,如下图所示:</span></p>

<p class=MsoNormal style='text-indent:21.0pt;line-height:150%'><span
lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal style='text-indent:21.0pt;line-height:150%'><!--[if gte vml 1]><v:rect
 id="_x0000_s1081" style='position:absolute;left:0;text-align:left;
 margin-left:147.6pt;margin-top:19.1pt;width:108pt;height:23.4pt;text-indent:0;
 z-index:7'>
 <v:textbox style='mso-next-textbox:#_x0000_s1081'>
  <![if !mso]>
  <table cellpadding=0 cellspacing=0 width="100%">
   <tr>
    <td><![endif]>
    <div>
    <p class=MsoNormal><span lang=EN-US>&amp;<span class=SpellE>animal:<span
    class=GramE>:breathe</span></span>()</span></p>
    </div>
    <![if !mso]></td>
   </tr>
  </table>
  <![endif]></v:textbox>
</v:rect><v:shape id="_x0000_s1086" type="#_x0000_t202" style='position:absolute;
 left:0;text-align:left;margin-left:57.6pt;margin-top:3.5pt;width:99pt;
 height:23.4pt;text-indent:0;z-index:8' filled="f" stroked="f">
 <v:textbox style='mso-next-textbox:#_x0000_s1086'>
  <![if !mso]>
  <table cellpadding=0 cellspacing=0 width="100%">
   <tr>
    <td><![endif]>
    <div>
    <p class=MsoNormal><span lang=EN-US>animal</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>vtable</span></span></p>
    </div>
    <![if !mso]></td>
   </tr>
  </table>
  <![endif]></v:textbox>
</v:shape><v:rect id="_x0000_s1087" style='position:absolute;left:0;
 text-align:left;margin-left:309.6pt;margin-top:19.1pt;width:90pt;height:23.4pt;
 text-indent:0;z-index:9'>
 <v:textbox style='mso-next-textbox:#_x0000_s1087'>
  <![if !mso]>
  <table cellpadding=0 cellspacing=0 width="100%">
   <tr>
    <td><![endif]>
    <div>
    <p class=MsoNormal><span class=SpellE><span lang=EN-US>animal::<span
    class=GramE>breathe</span></span></span><span class=GramE><span lang=EN-US>()</span></span></p>
    </div>
    <![if !mso]></td>
   </tr>
  </table>
  <![endif]></v:textbox>
</v:rect><v:line id="_x0000_s1090" style='position:absolute;left:0;
 text-align:left;z-index:10' from="255.6pt,29.75pt" to="309.6pt,29.75pt">
 <v:stroke endarrow="block"/>
</v:line><v:rect id="_x0000_s1091" style='position:absolute;left:0;
 text-align:left;margin-left:147.6pt;margin-top:79.7pt;width:108pt;height:23.4pt;
 text-indent:0;z-index:11'>
 <v:textbox style='mso-next-textbox:#_x0000_s1091'>
  <![if !mso]>
  <table cellpadding=0 cellspacing=0 width="100%">
   <tr>
    <td><![endif]>
    <div>
    <p class=MsoNormal><span lang=EN-US>&amp;<span class=SpellE>fish:<span
    class=GramE>:breathe</span></span>()</span></p>
    </div>
    <![if !mso]></td>
   </tr>
  </table>
  <![endif]></v:textbox>
</v:rect><v:shape id="_x0000_s1092" type="#_x0000_t202" style='position:absolute;
 left:0;text-align:left;margin-left:66.6pt;margin-top:64.1pt;width:90pt;
 height:23.4pt;text-indent:0;z-index:12' filled="f" stroked="f">
 <v:textbox style='mso-next-textbox:#_x0000_s1092'>
  <![if !mso]>
  <table cellpadding=0 cellspacing=0 width="100%">
   <tr>
    <td><![endif]>
    <div>
    <p class=MsoNormal><span lang=EN-US>fish</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>vtable</span></span></p>
    </div>

⌨️ 快捷键说明

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