| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
| |
| <html> |
| <head> |
| <meta name="generator" content= |
| "Microsoft FrontPage 5.0"> |
| <meta http-equiv="Content-Type" content= |
| "text/html; charset=windows-1252"> |
| <meta name="GENERATOR" content="Microsoft FrontPage 4.0"> |
| <meta name="ProgId" content="FrontPage.Editor.Document"> |
| |
| <title>Header boost/polymorphic_cast.hpp Documentation</title> |
| <style> |
| .copyright |
| { |
| color: #666666; |
| font-size: small; |
| } |
| </style> |
| </head> |
| |
| <body bgcolor="#FFFFFF" text="#000000"> |
| <h1><img src="../../boost.png" alt="boost.png (6897 bytes)" align= |
| "middle" width="277" height="86">Header <a href= |
| "../../boost/polymorphic_cast.hpp">boost/polymorphic_cast.hpp</a></h1> |
| |
| <h2><a name="Cast Functions">Cast Functions</a></h2> |
| |
| <p>The header <a href="../../boost/polymorphic_cast.hpp">boost/polymorphic_cast.hpp</a> provides |
| <code><a href="#Polymorphic_cast">polymorphic_cast</a></code> and |
| <code><a href="#Polymorphic_cast">polymorphic_downcast</a></code> |
| 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 |
| <code><a href="#Polymorphic_cast">polymorphic_pointer_cast</a></code> and |
| <code><a href="#Polymorphic_cast">polymorphic_pointer_downcast</a></code> function templates. |
| |
| <p>The program <a href="test/cast_test.cpp">cast_test.cpp</a> can be used to |
| verify these function templates work as expected.</p> |
| |
| <h3><a name="Polymorphic_cast">Polymorphic casts</a></h3> |
| |
| <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>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>The C++ built-in <code>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>polymorphic_downcast</code> template retains |
| the efficiency of <code>static_cast</code> for non-debug compilations, but for |
| debug compilations adds safety via an assert() that a <code>dynamic_cast</code> |
| succeeds.</p> |
| |
| <p>The C++ built-in <code>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>dynamic_cast</code>, which |
| works on references, can be used on pointers through the ugly expression |
| &<code>dynamic_cast<T&>(*p)</code>, which causes undefined |
| behavior if <code>p</code> is <code>0</code>. The <code>polymorphic_cast</code> |
| template performs a <code>dynamic_cast</code> on a pointer, and throws an |
| exception if the <code>dynamic_cast</code> returns 0.</p> |
| |
| <p>A <code>polymorphic_downcast</code> should be used for |
| downcasts that you are certain should succeed. Error checking is |
| only performed in translation units where <code>NDEBUG</code> is |
| not defined, via |
| <pre> assert( dynamic_cast<Derived>(x) == x ) |
| </pre> where <code>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>polymorphic_downcast</code> will |
| fail to compile. |
| <b>Warning:</b> Because <code>polymorphic_downcast</code> uses assert(), it |
| violates the One Definition Rule (ODR) if NDEBUG is inconsistently |
| defined across translation units. [See ISO Std 3.2] |
| <p> |
| For crosscasts, or when the success of a cast can only be known at |
| runtime, or when efficiency is not important, |
| <code>polymorphic_cast</code> is preferred. </p> |
| |
| <p>The C++ built-in <code>dynamic_cast</code> 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>While <code>polymorphic_downcast</code> and <code>polymorphic_cast</code> work with built-in pointer types only, |
| <code>polymorphic_pointer_downcast</code> and <code>polymorphic_pointer_cast</code> are more generic versions |
| with support for any pointer type for which the following expressions would be valid:<br><br> |
| |
| <p> For <code>polymorphic_pointer_downcast</code>:</p> |
| <code> static_pointer_cast<Derived>(p);<br> dynamic_pointer_cast<Derived>(p);</code><br><br> |
| |
| <p> For <code>polymorphic_pointer_cast</code>:</p> |
| <code> dynamic_pointer_cast<Derived>(p);<br> !p; // conversion to bool with negation</code><br><br> |
| <p>This includes C++ built-in pointers, <code>std::shared_ptr, boost::shared_ptr, boost::intrusive_ptr</code>, etc.</p> |
| |
| <h3>polymorphic_cast, polymorphic_downcast, polymorphic_pointer_cast and polymorphic_pointer_downcast synopsis</h3> |
| |
| <blockquote> |
| <pre>namespace boost { |
| |
| template <class Derived, class Base> |
| inline Derived polymorphic_cast(Base* x); |
| // Throws: std::bad_cast if ( dynamic_cast<Derived>(x) == 0 ) |
| // Returns: dynamic_cast<Derived>(x) |
| |
| template <class Derived, class Base> |
| inline Derived polymorphic_downcast(Base* x); |
| // Effects: assert( dynamic_cast<Derived>(x) == x ); |
| // Returns: static_cast<Derived>(x) |
| |
| template <class Derived, class Base> |
| inline auto polymorphic_pointer_cast(Base x); |
| // Throws: std::bad_cast if ( dynamic_pointer_cast<Derived>(x) == 0 ) |
| // Returns: dynamic_pointer_cast<Derived>(x) |
| |
| template <class Derived, class Base> |
| inline auto polymorphic_pointer_downcast(Base x); |
| // Effects: assert( dynamic_pointer_cast<Derived>(x) == x ); |
| // Returns: static_pointer_cast<Derived>(x) |
| |
| } |
| </pre> |
| </blockquote> |
| |
| <h3>polymorphic_downcast example</h3> |
| |
| <blockquote> |
| <pre>#include <boost/polymorphic_cast.hpp> |
| ... |
| class Fruit { public: virtual ~Fruit(){}; ... }; |
| class Banana : public Fruit { ... }; |
| ... |
| void f( Fruit * fruit ) { |
| // ... logic which leads us to believe it is a Banana |
| Banana * banana = boost::polymorphic_downcast<Banana*>(fruit); |
| ... |
| </pre> |
| </blockquote> |
| |
| <h3>polymorphic_pointer_downcast example</h3> |
| |
| <blockquote> |
| <pre>#include <boost/polymorphic_pointer_cast.hpp> |
| |
| class Fruit { public: virtual ~Fruit(){} }; |
| class Banana : public Fruit {}; |
| |
| // use one of these: |
| |
| typedef Fruit* FruitPtr; |
| typedef std::shared_ptr<Fruit> FruitPtr; |
| typedef boost::shared_ptr<Fruit> FruitPtr; |
| typedef boost::intrusive_ptr<Fruit> FruitPtr; |
| |
| void f(FruitPtr fruit) |
| { |
| // ... logic which leads us to believe it is a banana |
| auto banana = boost::polymorphic_pointer_downcast<Banana>(fruit); |
| ... |
| } |
| </pre> |
| </blockquote> |
| |
| <h3>History</h3> |
| |
| <p><code>polymorphic_cast</code> was suggested by Bjarne Stroustrup in "The C++ |
| Programming Language".<br> |
| <code>polymorphic_downcast</code> was contributed by <a href= |
| "http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a>.<br> |
| <code>polymorphic_pointer_downcast</code> was contributed by <a href= |
| "http://www.boost.org/people/boris_rasin.htm">Boris Rasin</a> and |
| <code>polymorphic_pointer_cast</code> by Antony Polukhin.<br> |
| An old |
| <code>numeric_cast</code> that was contributed by <a href= |
| "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> |
| <hr> |
| |
| <p>Revised |
| <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan |
| -->June 23, 2005<!--webbot bot="Timestamp" endspan i-checksum="30348" |
| --></p> |
| |
| <p class="copyright">© Copyright boost.org 1999. |
| 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">http://www.boost.org/LICENSE_1_0.txt</a>) |
| </p> |
| </body> |
| </html> |