]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
2 | ||
3 | <html> | |
4 | <head> | |
5 | <meta name="generator" content= | |
6 | "Microsoft FrontPage 5.0"> | |
7 | <meta http-equiv="Content-Type" content= | |
8 | "text/html; charset=windows-1252"> | |
9 | <meta name="GENERATOR" content="Microsoft FrontPage 4.0"> | |
10 | <meta name="ProgId" content="FrontPage.Editor.Document"> | |
11 | ||
12 | <title>Header boost/polymorphic_cast.hpp Documentation</title> | |
13 | <style> | |
14 | .copyright | |
15 | { | |
16 | color: #666666; | |
17 | font-size: small; | |
18 | } | |
19 | </style> | |
20 | </head> | |
21 | ||
22 | <body bgcolor="#FFFFFF" text="#000000"> | |
23 | <h1><img src="../../boost.png" alt="boost.png (6897 bytes)" align= | |
24 | "middle" width="277" height="86">Header <a href= | |
25 | "../../boost/polymorphic_cast.hpp">boost/polymorphic_cast.hpp</a></h1> | |
26 | ||
27 | <h2><a name="Cast Functions">Cast Functions</a></h2> | |
28 | ||
29 | <p>The header <a href="../../boost/polymorphic_cast.hpp">boost/polymorphic_cast.hpp</a> provides | |
30 | <code><a href="#Polymorphic_cast">polymorphic_cast</a></code> and | |
31 | <code><a href="#Polymorphic_cast">polymorphic_downcast</a></code> | |
32 | function templates designed to complement the C++ built-in casts.</p> <p>The header <a href="../../boost/polymorphic_pointer_cast.hpp">boost/polymorphic_pointer_cast.hpp</a> provides | |
33 | <code><a href="#Polymorphic_cast">polymorphic_pointer_cast</a></code> and | |
34 | <code><a href="#Polymorphic_cast">polymorphic_pointer_downcast</a></code> function templates. | |
35 | ||
36 | <p>The program <a href="test/cast_test.cpp">cast_test.cpp</a> can be used to | |
37 | verify these function templates work as expected.</p> | |
38 | ||
39 | <h3><a name="Polymorphic_cast">Polymorphic casts</a></h3> | |
40 | ||
41 | <p>Pointers to polymorphic objects (objects of classes which define at | |
42 | least one virtual function) are sometimes downcast or crosscast. | |
43 | Downcasting means casting from a base class to a derived class. | |
44 | Crosscasting means casting across an inheritance hierarchy diagram, such | |
45 | as from one base to the other in a <code>Y</code> diagram hierarchy.</p> | |
46 | ||
47 | <p>Such casts can be done with old-style casts, but this approach is | |
48 | never to be recommended. Old-style casts are sorely lacking in type | |
49 | safety, suffer poor readability, and are difficult to locate with search | |
50 | tools.</p> | |
51 | ||
52 | <p>The C++ built-in <code>static_cast</code> can be used for efficiently | |
53 | downcasting pointers to polymorphic objects, but provides no error | |
54 | detection for the case where the pointer being cast actually points to | |
55 | the wrong derived class. The <code>polymorphic_downcast</code> template retains | |
56 | the efficiency of <code>static_cast</code> for non-debug compilations, but for | |
57 | debug compilations adds safety via an assert() that a <code>dynamic_cast</code> | |
58 | succeeds.</p> | |
59 | ||
60 | <p>The C++ built-in <code>dynamic_cast</code> can be used for downcasts and | |
61 | crosscasts of pointers to polymorphic objects, but error notification in | |
62 | the form of a returned value of 0 is inconvenient to test, or worse yet, | |
63 | easy to forget to test. The throwing form of <code>dynamic_cast</code>, which | |
64 | works on references, can be used on pointers through the ugly expression | |
65 | &<code>dynamic_cast<T&>(*p)</code>, which causes undefined | |
66 | behavior if <code>p</code> is <code>0</code>. The <code>polymorphic_cast</code> | |
67 | template performs a <code>dynamic_cast</code> on a pointer, and throws an | |
68 | exception if the <code>dynamic_cast</code> returns 0.</p> | |
69 | ||
70 | <p>A <code>polymorphic_downcast</code> should be used for | |
71 | downcasts that you are certain should succeed. Error checking is | |
72 | only performed in translation units where <code>NDEBUG</code> is | |
73 | not defined, via | |
74 | <pre> assert( dynamic_cast<Derived>(x) == x ) | |
75 | </pre> where <code>x</code> is the source pointer. This approach | |
76 | ensures that not only is a non-zero pointer returned, but also | |
77 | that it is correct in the presence of multiple inheritance. | |
78 | Attempts to crosscast using <code>polymorphic_downcast</code> will | |
79 | fail to compile. | |
80 | <b>Warning:</b> Because <code>polymorphic_downcast</code> uses assert(), it | |
81 | violates the One Definition Rule (ODR) if NDEBUG is inconsistently | |
82 | defined across translation units. [See ISO Std 3.2] | |
83 | <p> | |
84 | For crosscasts, or when the success of a cast can only be known at | |
85 | runtime, or when efficiency is not important, | |
86 | <code>polymorphic_cast</code> is preferred. </p> | |
87 | ||
88 | <p>The C++ built-in <code>dynamic_cast</code> must be used to cast references | |
89 | rather than pointers. It is also the only cast that can be used to check | |
90 | whether a given interface is supported; in that case a return of 0 isn't | |
91 | an error condition.</p> | |
92 | ||
93 | <p>While <code>polymorphic_downcast</code> and <code>polymorphic_cast</code> work with built-in pointer types only, | |
94 | <code>polymorphic_pointer_downcast</code> and <code>polymorphic_pointer_cast</code> are more generic versions | |
95 | with support for any pointer type for which the following expressions would be valid:<br><br> | |
96 | ||
97 | <p> For <code>polymorphic_pointer_downcast</code>:</p> | |
98 | <code> static_pointer_cast<Derived>(p);<br> dynamic_pointer_cast<Derived>(p);</code><br><br> | |
99 | ||
100 | <p> For <code>polymorphic_pointer_cast</code>:</p> | |
101 | <code> dynamic_pointer_cast<Derived>(p);<br> !p; // conversion to bool with negation</code><br><br> | |
102 | <p>This includes C++ built-in pointers, <code>std::shared_ptr, boost::shared_ptr, boost::intrusive_ptr</code>, etc.</p> | |
103 | ||
104 | <h3>polymorphic_cast, polymorphic_downcast, polymorphic_pointer_cast and polymorphic_pointer_downcast synopsis</h3> | |
105 | ||
106 | <blockquote> | |
107 | <pre>namespace boost { | |
108 | ||
109 | template <class Derived, class Base> | |
110 | inline Derived polymorphic_cast(Base* x); | |
111 | // Throws: std::bad_cast if ( dynamic_cast<Derived>(x) == 0 ) | |
112 | // Returns: dynamic_cast<Derived>(x) | |
113 | ||
114 | template <class Derived, class Base> | |
115 | inline Derived polymorphic_downcast(Base* x); | |
116 | // Effects: assert( dynamic_cast<Derived>(x) == x ); | |
117 | // Returns: static_cast<Derived>(x) | |
118 | ||
119 | template <class Derived, class Base> | |
120 | inline auto polymorphic_pointer_cast(Base x); | |
121 | // Throws: std::bad_cast if ( dynamic_pointer_cast<Derived>(x) == 0 ) | |
122 | // Returns: dynamic_pointer_cast<Derived>(x) | |
123 | ||
124 | template <class Derived, class Base> | |
125 | inline auto polymorphic_pointer_downcast(Base x); | |
126 | // Effects: assert( dynamic_pointer_cast<Derived>(x) == x ); | |
127 | // Returns: static_pointer_cast<Derived>(x) | |
128 | ||
129 | } | |
130 | </pre> | |
131 | </blockquote> | |
132 | ||
133 | <h3>polymorphic_downcast example</h3> | |
134 | ||
135 | <blockquote> | |
136 | <pre>#include <boost/polymorphic_cast.hpp> | |
137 | ... | |
138 | class Fruit { public: virtual ~Fruit(){}; ... }; | |
139 | class Banana : public Fruit { ... }; | |
140 | ... | |
141 | void f( Fruit * fruit ) { | |
142 | // ... logic which leads us to believe it is a Banana | |
143 | Banana * banana = boost::polymorphic_downcast<Banana*>(fruit); | |
144 | ... | |
145 | </pre> | |
146 | </blockquote> | |
147 | ||
148 | <h3>polymorphic_pointer_downcast example</h3> | |
149 | ||
150 | <blockquote> | |
151 | <pre>#include <boost/polymorphic_pointer_cast.hpp> | |
152 | ||
153 | class Fruit { public: virtual ~Fruit(){} }; | |
154 | class Banana : public Fruit {}; | |
155 | ||
156 | // use one of these: | |
157 | ||
158 | typedef Fruit* FruitPtr; | |
159 | typedef std::shared_ptr<Fruit> FruitPtr; | |
160 | typedef boost::shared_ptr<Fruit> FruitPtr; | |
161 | typedef boost::intrusive_ptr<Fruit> FruitPtr; | |
162 | ||
163 | void f(FruitPtr fruit) | |
164 | { | |
165 | // ... logic which leads us to believe it is a banana | |
166 | auto banana = boost::polymorphic_pointer_downcast<Banana>(fruit); | |
167 | ... | |
168 | } | |
169 | </pre> | |
170 | </blockquote> | |
171 | ||
172 | <h3>History</h3> | |
173 | ||
174 | <p><code>polymorphic_cast</code> was suggested by Bjarne Stroustrup in "The C++ | |
175 | Programming Language".<br> | |
176 | <code>polymorphic_downcast</code> was contributed by <a href= | |
177 | "http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a>.<br> | |
178 | <code>polymorphic_pointer_downcast</code> was contributed by <a href= | |
179 | "http://www.boost.org/people/boris_rasin.htm">Boris Rasin</a> and | |
180 | <code>polymorphic_pointer_cast</code> by Antony Polukhin.<br> | |
181 | An old | |
182 | <code>numeric_cast</code> that was contributed by <a href= | |
183 | "http://www.boost.org/people/kevlin_henney.htm">Kevlin Henney</a> is now superseeded by the <a href="../numeric/conversion/doc/html/index.html">Boost Numeric Conversion Library</a></p> | |
184 | <hr> | |
185 | ||
186 | <p>Revised | |
187 | <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan | |
188 | -->June 23, 2005<!--webbot bot="Timestamp" endspan i-checksum="30348" | |
189 | --></p> | |
190 | ||
191 | <p class="copyright">© Copyright boost.org 1999. | |
192 | Distributed under the Boost Software License, Version 1.0. (See accompanying | |
193 | file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>) | |
194 | </p> | |
195 | </body> | |
196 | </html> |