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

📄 1is_a.html

📁 Visual C++ has been one of most effective tool for the large industrial applications. This book is t
💻 HTML
字号:
<html>
<head>
	<title>Polymorphism</title>
    <meta  name="description" content="Polymorphism in C++">
    <meta name="keywords" content="polymorphism, inheritance, class, virtual">
	<link rel="stylesheet" href="rs.css" tppabs="http://www.relisoft.com/book/rs.css">
</head>

<body background="margin.gif" tppabs="http://www.relisoft.com/book/images/margin.gif" bgcolor="#FFFFDC">

<!-- Main Table -->
<table cellpadding="6">
    <tr>
    <td width="78">
	&nbsp;
    
	<td>

<h2>Polymorphism</h2>

<h3>The Meaning of is-a</h3>

<p>The fact that a <var>Star</var> is a <var>CelestialBody</var> means not only that a <var>Star</var> has all the member variables and methods of a <var>CelestialBody</var> (and more). After all that would be just syntactic sugar over straight embedding. One could embed a <var>CelestialBody</var> as a public member of <var>Star</var> and, apart from awkward semantics of the has-a relationship, one could imitate inheritance. (As a matter of fact, this is probably how your compiler implements inheritance.)
 
<p>There is however one big difference. Due to inheritance, a <var>Star</var> can pass as a <var>CelestialBody</var>. What does it mean? It means that a function that expects a reference or a pointer to a <var>CelestialBody</var> will happily accept a reference or a pointer to a <var>Star</var>. Here抯 an example: The class <var>BlackHole</var> has a method <var>Gobble</var> that accepts any <var>CelestialBody</var>

<!-- Code --><table width="100%" cellspacing=10><tr>	<td class=codetable>
<pre>void BlackHole::Gobble (CelestialBody * pBody);</pre>
</table><!-- End Code --><p>

<p>Since a <var>Star</var> is a <var>CelestialBody</var>, it can be <var>Gobbled</var> by a <var>BlackHole</var>:
<!-- Code --><table width="100%" cellspacing=10><tr>	<td class=codetable>

<pre>Star* pStar = new Star (1, 2);
TheBlackHole.Gobble (pStar);  // Yumm</pre>
</table><!-- End Code -->

<p>How is the <var>CelestialBody</var> treated inside a <var>BlackHole</var>?
<!-- Code --><table width="100%" cellspacing=10><tr>	<td class=codetable>

<pre>void BlackHole::Gobble (CelestialBody* pBody)
{
    delete pBody;
}</pre>
</table><!-- End Code -->

<p>It is destroyed. Now the big question is: whose destructor is called? On the one hand, we know that we sent a <var>Star</var> to its fiery death, so we should hear  &quot;Destroying a star ...&quot; On the other hand, the <var>BlackHole</var> has no idea that it is swallowing a <var>Star</var>. It will expect to hear &quot;Destroying celestial body...&quot; What抯 more, at compile time, the compiler has no idea what will be sent into the <var>BlackHole</var>. Imagine a situation like this:

<!-- Code --><table width="100%" cellspacing=10><tr>	<td class=codetable>

<pre>Star * pStar = new Star (1, 2);
Planet * pPlanet = new Planet (3, 4);

TheBlackHole.Gobble (pStar);  // Yumm
TheBlackHole.Gobble (pPlanet);  // Yumm, yumm</pre>
</table><!-- End Code -->

<p>In both cases the same method <var>Gobble</var> is called, the same code is executed, therefore it is obvious that inside <var>Gobble</var> the compiler may only put the call to (or expand inline) <var>CelestialBody</var>抯 destructor. The compiler dispatches the call based on the <b><i>type of the pointer</i></b>. Notice that the same would apply to any other method of <var>CelestialBody</var>  overridden by <var>Star</var> or <var>Planet</var>. If <var>Gobble</var> called any of these, the compiler would call the <var>CelestialBody</var>抯 implementation and not the one provided by <var>Star</var> or <var>Planet</var>.

<p>This solution is cheap and in many cases adequate. However, for a small additional fee, C++ can offer a very powerful feature called <b><i>polymorphism</i></b>. If you want to hear different final cries from the insides of a <var>BlackHole</var> depending on what has fallen into it, you must declare the <var>CelestialBody</var>抯 destructor <b><i>virtual</i></b>. When a virtual function is overridden in a derived class, the dispatching of calls to that function is done by <b><i>actual type</i></b> of the object pointed to, rather than by the <b><i>type of the pointer</i></b>.

<!-- Sidebar -->
<table width="100%" border=0 cellpadding=5><tr>
<td width=10>
<td bgcolor="#cccccc" class=sidebar>
If you are curious about how virtual functions are implemented and what kind of runtime overhead they incur, go on a little <a href="javascript:if(confirm('http://www.relisoft.com/book/lang/poly/2implem.html  \n\nThis file was not retrieved by Teleport Pro, because it is linked too far away from its Starting Address. If you increase the in-domain depth setting for the Starting Address, this file will be queued for retrieval.  \n\nDo you want to open it from the server?'))window.location='http://www.relisoft.com/book/lang/poly/2implem.html'" tppabs="http://www.relisoft.com/book/lang/poly/2implem.html">implementation sidetrip</a>.
</table>
<!-- End Sidebar -->



</table>
<!-- End Main Table -->
</body>
</html>

⌨️ 快捷键说明

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