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

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

📁 c++/vc++ 精华文章
💻 HTM
📖 第 1 页 / 共 5 页
字号:
"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>pAn</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>fh</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>pAn</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>pAn</span></span><span
lang=EN-US>-&gt;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>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>fh</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>fish</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
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>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='margin-left:18.0pt;text-indent:-18.0pt;line-height:
150%;mso-list:l2 level1 lfo2;tab-stops:list 18.0pt'><![if !supportLists]><span
lang=EN-US style='mso-fareast-font-family:"Times New Roman"'><span
style='mso-list:Ignore'>1、<span style='font:7.0pt "Times New Roman"'>&nbsp; </span></span></span><![endif]><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>编译的角度</span></p>

<p class=MsoNormal style='margin-left:17.85pt;line-height:150%'><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>early 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>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>fh</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>pAn</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 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>pAn</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>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>main()</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>pAn</span></span><span
lang=EN-US>-&gt;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>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></p>

<p class=MsoNormal style='margin-left:18.0pt;text-indent:-18.0pt;line-height:
150%;mso-list:l2 level1 lfo2;tab-stops:list 18.0pt'><![if !supportLists]><span
lang=EN-US style='mso-fareast-font-family:"Times New Roman"'><span
style='mso-list:Ignore'>2、<span style='font:7.0pt "Times New Roman"'>&nbsp; </span></span></span><![endif]><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:17.85pt;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</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='line-height:150%'><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

<p class=MsoNormal style='line-height:150%'><!--[if gte vml 1]><v:rect id="_x0000_s1069"
 style='position:absolute;left:0;text-align:left;margin-left:99pt;margin-top:7.8pt;
 width:108pt;height:124.8pt;z-index:1'/><v:line id="_x0000_s1070" style='position:absolute;
 left:0;text-align:left;z-index:2' from="99pt,70.2pt" to="207pt,70.2pt"/><v:shapetype
 id="_x0000_t202" coordsize="21600,21600" o:spt="202" path="m,l,21600r21600,l21600,xe">
 <v:stroke joinstyle="miter"/>
 <v:path gradientshapeok="t" o:connecttype="rect"/>
</v:shapetype><v:shape id="_x0000_s1071" type="#_x0000_t202" style='position:absolute;
 left:0;text-align:left;margin-left:117pt;margin-top:30.3pt;width:1in;height:39pt;
 z-index:3' filled="f" stroked="f">
 <v:textbox style='mso-next-textbox:#_x0000_s1071'>
  <![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></p>
    </div>
    <![if !mso]></td>
   </tr>
  </table>
  <![endif]></v:textbox>
</v:shape><v:shape id="_x0000_s1072" type="#_x0000_t202" style='position:absolute;
 left:0;text-align:left;margin-left:108pt;margin-top:90.3pt;width:90pt;
 height:39pt;z-index:4' filled="f" stroked="f">
 <v:textbox style='mso-next-textbox:#_x0000_s1072'>
  <![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></p>
    </div>
    <![if !mso]></td>
   </tr>
  </table>
  <![endif]></v:textbox>
</v:shape><v:shapetype id="_x0000_t88" coordsize="21600,21600" o:spt="88"
 adj="1800,10800" path="m,qx10800@0l10800@2qy21600@11,10800@3l10800@1qy,21600e"
 filled="f">
 <v:formulas>
  <v:f eqn="val #0"/>
  <v:f eqn="sum 21600 0 #0"/>
  <v:f eqn="sum #1 0 #0"/>
  <v:f eqn="sum #1 #0 0"/>
  <v:f eqn="prod #0 9598 32768"/>
  <v:f eqn="sum 21600 0 @4"/>
  <v:f eqn="sum 21600 0 #1"/>
  <v:f eqn="min #1 @6"/>
  <v:f eqn="prod @7 1 2"/>
  <v:f eqn="prod #0 2 1"/>
  <v:f eqn="sum 21600 0 @9"/>
  <v:f eqn="val #1"/>
 </v:formulas>
 <v:path arrowok="t" o:connecttype="custom" o:connectlocs="0,0;21600,@11;0,21600"
  textboxrect="0,@4,7637,@5"/>
 <v:handles>
  <v:h position="center,#0" yrange="0,@8"/>
  <v:h position="bottomRight,#1" yrange="@9,@10"/>
 </v:handles>
</v:shapetype><v:shape id="_x0000_s1075" type="#_x0000_t88" style='position:absolute;
 left:0;text-align:left;margin-left:3in;margin-top:7.8pt;width:27pt;height:124.8pt;
 z-index:5'/><v:shape id="_x0000_s1076" type="#_x0000_t202" style='position:absolute;
 left:0;text-align:left;margin-left:243pt;margin-top:52.5pt;width:81pt;
 height:39pt;z-index:6' filled="f" stroked="f">
 <v:textbox>
  <![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></p>
    </div>
    <![if !mso]></td>
   </tr>
  </table>
  <![endif]></v:textbox>
</v:shape><![endif]--><![if !vml]><span style='mso-ignore:vglayout'>

<table cellpadding=0 cellspacing=0 align=left>
 <tr>
  <td width=131 height=9></td>
  <td width=146></td>
  <td width=10></td>
  <td width=147></td>
 </tr>
 <tr>
  <td height=169></td>
  <td align=left valign=top><img width=146 height=169
  src="004/image001.gif" v:shapes="_x0000_s1069 _x0000_s1070 _x0000_s1071 _x0000_s1072"></td>
  <td></td>
  <td align=left valign=top><img width=147 height=169
  src="004/image002.gif" v:shapes="_x0000_s1075 _x0000_s1076"></td>
 </tr>
</table>

</span><![endif]><span lang=EN-US><o:p>&nbsp;</o:p></span></p>

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

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

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

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

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

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

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

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

<br style='mso-ignore:vglayout' clear=ALL>

<p class=MsoCaption align=center style='text-align:center'><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'>1</span></span><!--[if supportFields]><span
lang=EN-US><span style='mso-element:field-end'></span></span><![endif]--><span
lang=EN-US> fish</span><span class=GramE><span style='font-family:黑体;
mso-ascii-font-family:Arial'>类对象</span></span><span style='font-family:黑体;
mso-ascii-font-family:Arial'>的内存模型</span></p>

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

<p class=MsoNormal style='text-indent:21.15pt;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</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>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
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
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
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>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>animal 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 class=GramE>在例</span></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 class=SpellE><span lang=EN-US>pAn</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>fish</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
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:

⌨️ 快捷键说明

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