1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Polymorphic casts</title>
<link rel="stylesheet" href="../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset">
<link rel="up" href="../conversion.html" title="Chapter 10. The Conversion Library 1.6">
<link rel="prev" href="../conversion.html" title="Chapter 10. The Conversion Library 1.6">
<link rel="next" href="_polymorphic_cast____polymorphic_downcast____polymorphic_pointer_cast__and__polymorphic_pointer_downcast__synopsis.html" title="polymorphic_cast, polymorphic_downcast, polymorphic_pointer_cast and polymorphic_pointer_downcast synopsis">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../boost.png"></td>
<td align="center"><a href="../../../index.html">Home</a></td>
<td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../conversion.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../conversion.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="_polymorphic_cast____polymorphic_downcast____polymorphic_pointer_cast__and__polymorphic_pointer_downcast__synopsis.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="conversion.polymorphic_casts"></a><a class="link" href="polymorphic_casts.html" title="Polymorphic casts">Polymorphic casts</a>
</h2></div></div></div>
<p>
Pointers to polymorphic objects (objects of classes which define at least one
virtual function) are sometimes downcast or crosscast. Downcasting means casting
from a base class to a derived class. Crosscasting means casting across an
inheritance hierarchy diagram, such as from one base to the other in a <code class="literal">Y</code>
diagram hierarchy.
</p>
<p>
Such casts can be done with old-style casts, but this approach is never to
be recommended. Old-style casts are sorely lacking in type safety, suffer poor
readability, and are difficult to locate with search tools.
</p>
<p>
<a name="polymorphic_downcast"></a>The C++ built-in <code class="computeroutput">static_cast</code>
can be used for efficiently downcasting pointers to polymorphic objects, but
provides no error detection for the case where the pointer being cast actually
points to the wrong derived class. The <code class="computeroutput">polymorphic_downcast</code> template
retains the efficiency of <code class="computeroutput">static_cast</code> for non-debug compilations,
but for debug compilations adds safety via an <code class="computeroutput">assert()</code> that a
<code class="computeroutput">dynamic_cast</code> succeeds.
</p>
<p>
A <code class="computeroutput">polymorphic_downcast</code> should be used for downcasts that you are
certain should succeed. Error checking is only performed in translation units
where <code class="computeroutput">NDEBUG</code> is not defined, via
</p>
<pre class="programlisting">assert( dynamic_cast<Derived>(x) == x )
</pre>
<p>
where <code class="computeroutput">x</code> is the source pointer. This approach ensures that not
only is a non-zero pointer returned, but also that it is correct in the presence
of multiple inheritance. Attempts to crosscast using <code class="computeroutput">polymorphic_downcast</code>
will fail to compile.
</p>
<div class="warning"><table border="0" summary="Warning">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="../../../doc/src/images/warning.png"></td>
<th align="left">Warning</th>
</tr>
<tr><td align="left" valign="top"><p>
Because <code class="computeroutput">polymorphic_downcast</code> uses <code class="computeroutput">assert()</code>, it
violates the One Definition Rule (ODR) if NDEBUG is inconsistently defined
across translation units. See ISO Std 3.2
</p></td></tr>
</table></div>
<p>
<a name="polymorphic_cast"></a>The C++ built-in <code class="computeroutput">dynamic_cast</code> can
be used for downcasts and crosscasts of pointers to polymorphic objects, but
error notification in the form of a returned value of 0 is inconvenient to
test, or worse yet, easy to forget to test. The throwing form of <code class="computeroutput">dynamic_cast</code>,
which works on references, can be used on pointers through the ugly expression
<code class="computeroutput">&dynamic_cast<T&>(*p), which causes undefined behavior
if </code>p<code class="computeroutput"> is </code>0<code class="computeroutput">. The </code>polymorphic_cast<code class="computeroutput"> template
performs a </code>dynamic_cast<code class="computeroutput"> on a pointer, and throws an exception
if the </code>dynamic_cast` returns 0.
</p>
<p>
For crosscasts, or when the success of a cast can only be known at runtime,
or when efficiency is not important, <code class="computeroutput">polymorphic_cast</code> is preferred.
</p>
<p>
The C++ built-in dynamic_cast must be used to cast references rather than pointers.
It is also the only cast that can be used to check whether a given interface
is supported; in that case a return of 0 isn't an error condition.
</p>
<p>
<a name="polymorphic_pointer_cast"></a>While polymorphic_downcast and polymorphic_cast
work with built-in pointer types only, polymorphic_pointer_downcast and polymorphic_pointer_cast
are more generic versions with support for any pointer type for which the following
expressions would be valid:
</p>
<p>
For <code class="computeroutput">polymorphic_pointer_downcast</code>:
</p>
<pre class="programlisting">static_pointer_cast<Derived>(p);
dynamic_pointer_cast<Derived>(p);
</pre>
<p>
For <code class="computeroutput">polymorphic_pointer_cast</code>:
</p>
<pre class="programlisting">dynamic_pointer_cast<Derived>(p);
!p; // conversion to bool with negation
</pre>
<p>
This includes C++ built-in pointers, <code class="computeroutput">std::shared_ptr</code>, <code class="computeroutput">boost::shared_ptr</code>,
<code class="computeroutput">boost::intrusive_ptr</code>, etc.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright © 2001 Beman Dawes<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../conversion.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../conversion.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="_polymorphic_cast____polymorphic_downcast____polymorphic_pointer_cast__and__polymorphic_pointer_downcast__synopsis.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>
|