    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Standard containers for polymorphic types</title>
        <link>https://members.accu.org/index.php/journals/1455</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>


        <h2>Journal Articles</h2>


<div class="xar-mod-head"><span class="xar-mod-title">Overload Journal #17/18 - Jan 1997 + Programming Topics</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c78/">Overload</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c228/">1718</a>
                    (9)
<br />

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c65/">Programming</a>
                    (877)
<br />

                                            <a href="https://members.accu.org/index.php/journals/c228-65/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/journals/c228+65/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Standard containers for polymorphic types</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 31 January 1997 08:54:00 +00:00 or Fri, 31 January 1997 08:54:00 +00:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;<p> I think that the terminology that is adopted by programmers
is often the cause of many of the problems even relatively experienced
pro&shy;grammers have. What is a container? Well common sense says that
it something into which you can put things. In an object-oriented world
surely that means a container is an object into which you can put other
objects. Well if you think that you are totally wrong in so far as
C++'s standard containers are con&shy;cerned.</p>
<p> What about a collection? Ordinary experience might lead us
to suppose that this too was some sort of assemblage of objects. We
have stamp collections, art collections and so on. Once again in an OO
world we have every right to think that it is somehow related to
objects.</p>
<p> Now in C++ we have two mechanisms for han&shy; dling objects,
references and pointers. Both these mechanisms support polymorphism. We
also have the concept of copying which is somehow related to the idea
of a value.</p>
<p> The pointer mechanism is a low level technique with
pointers being a kind of object whose 'value' is the 'address' of
another object. There are problems when the later object moves or
disappears because the pointer will provide a kind of ghostly existence
for the original object. If we are being sensible we should try to
avoid long distance pointers. By that I mean we should avoid using a
pointer as more than a very temporary handle for an ob&shy;ject that is
not immediately visible. We also need some mechanism for marking a
pointer as being out of use. C provides that via its null pointer, but
for efficiency purposes all use of this facility is left to the user.
C++ allows skilled programmers to produce their own pointer like
objects which can have many kinds of enhancement including more robust
mechanisms for handling non-addresses. Of course there is a price for
using these which you have to consider but until you can develop
suitable 'smart pointers' you are no more than an apprentice C++
programmer.</p>
<p> The C++ reference mechanism is designed to allow alternative
(often local scope) identifiers to be attached to existing
objects. The problem is that these identifiers are bound to a specific
object either statically or dynamically. The dy&shy;namic version is
via a reference parameter or return type. To understand this consider
how you can bind an auto identifier to a dynami&shy;cally selected
instance. Given:</p>
<pre>#include &lt;iostream&gt;<br>struct Base {<br>  int i;<br>  virtual void fn()<br>  { cout&lt;&lt; &quot;I'm a Base&quot; &lt;&lt; endl;}  <br>}; <br>struct Derived: public Base {<br>  void fn()<br>  { cout &lt;&lt; &quot;I am Derived&quot; &lt;&lt; endl; }<br>};<br></pre>
<p>I cannot write something like:</p>
<pre>main() { <br>  for (int i=0; i&lt;3 ;i++) {<br>    switch(i) {<br>    case 0:<br>      Base &amp; item = *new Base; break;<br>    case 1:<br>      Base &amp;item = *new Derived; break;<br>    default:<br>      Base &amp;item= *new Base;<br>    }<br>    item.fn();<br>  }<br>}<br></pre>
<p>Instead I must write:</p>
<pre>
Base &amp; fx(int i) {<br>  switch(i) {<br>    case 0: return *new Base; break;  <br>    case 1: return *new Derived; break; <br>    default: return *new Base;<br>  }<br>  return item;<br>}<br><br>main(){<br>  for (int i=0; i&lt;3; i++){<br>    Base &amp; item = fx(i);  <br>    item.fn();<br>  }<br>  return 0;<br>}<br></pre>
<p> Of course I could use a pointer, but the point I wish to make is
that dynamic binding of a ref&shy; erence is not simple. This results
in a further problem, you cannot have standard containers of
references. Without these there is no way to implement the concept of
putting an object into a standard container. The standard C++
containers work by copying. When I mentally put an object into a
vector, the actual process is to copy its value into an object already
in, or created for the purpose in the container. As I can only have a
container of <span style="font-family: monospace;">Base</span>s I
cannot have a mixture of <span style="font-family: monospace;">Base</span>
and <span style="font-family: monospace;">Derived</span>
ob&shy;jects. Think hard about the implications of that. C++ standard
containers are collections of homogeneous objects that can be
manipulated by copying. If you sort a vector you do not move the
objects you move the values they contain. This is not a design error,
it is a result of wanting to design efficient code in the ab&shy; sence
of any
form of rebinding for references.</p>
<p> Now clearly we are going to be constantly irri&shy; tated by the
lack of containers for mixed types so we must have some way to handle
these. That is the subject of the rest of this article.</p>
<h2>Use a pointer</h2>
<p> The obvious step is to use a container of point&shy;ers to hold
the objects that I create, or that al&shy; ready exist elsewhere. While
this lacks a certain elegance it might be a solution were it not for
two dangerous aspects of using such contain&shy;ers.</p>
<p> The first is that I must worry about what is go&shy; ing to be
responsible for destroying a dynamic object held by a pointer in a
container. If the object is 'owned' by the container I must
de&shy;stroy it before the container is destroyed (or transfer its
ownership elsewhere). If it is not owned by the container then I must
not destroy it via the pointer in the container. That means that either
my container must only contain pointers to 'owned' objects, or it must
contain only pointers to non-owned ones, or it must somehow track which
are which. Simple point&shy;ers cannot do the latter, applying
constraints on programmers that the compiler cannot enforce is a recipe
for disaster.</p>
<p> We could use a simple class to track pointer and ownership.
If we do this we might as well generalise it for all types. That
indicates that it should be a template class. Possibly something along
the lines:</p>
<pre>template &lt;typename T&gt; class Owned_ptr {<br>  T * handle;<br>  bool owned;<br>public:<br>  // constructors, destructor, access<br>  // functions etc.  <br>};<br></pre>
<p>It would probably be worth adding functional&shy; ity to make
this a smart pointer, but not yet as we have first to consider if it
can do the job.</p>
<p> The second problem is that the STL algorithms for
containers are also value based. It may not be obvious but the result
of this is that any al&shy;gorithm that 'moves' objects actually only
copies values. Where the algorithm is one that essentially preserves
all items in a container this is not a problem in this context.</p>
<p> (It is a problem in other contexts, you have to be
especially careful of pointers (and their more generalised cousins,
iterators) into con&shy;tainers. Applying algorithms to containers
pro&shy;vide a whole new potential for invalid pointers for the unwary.
Indeed even adding an item to a vector can invalidate all current
pointers to items in it. Why? An insertion could require the vector to
expand, that would require more memory, that almost certainly results
in mov&shy; ing the whole
vector to a new location with suf&shy;ficient contiguous memory to hold
the resized vector. Break the habit of using raw addresses. Funny how
often that theme comes up in C++.)</p>
<p> But some STL algorithms do not preserve all the items. In
such cases values may be copied from one to another. If the values
happen to be addresses then the copying can overwrite the only pointer
to a dynamic object and hence cause a resource leak (probably memory,
but it could be other things. C programmers get very blas6 about
closing files because <span style="font-family: monospace;">exit()</span>
will close them anyway, as far as I know
that is not necessarily the case in C++. It is the job of the
destructor of an <span style="font-family: monospace;">fstream</span>
object to close the file, if that destructor
is never called ...)</p>
<p> The result of this is that you will need to be careful with
your use of a container of pointers because some algorithms will break
them. Once again we have a constraint placed on the programmer. That
should always be a court of last appeal.</p>
<p> The simplest protective measure we can take is to inhibit
copy assignment in our 'smart pointer.' Then if we try to do something
silly we will get objections from the compiler. Note that this does not
prevent us providing a copying facility for our own use, it just won't
be called <span style="font-family: monospace;">operator=()</span>.
Stick the latter declaration in the private
interface of our class and declare a <span
 style="font-family: monospace;">T &amp; copy(T &amp;) const</span> in
the
public interface. Of course that may inhibit more of the STL algorithms
than you would ideally wish for but sometimes convenience must give way
to safety.</p>
<h2>Surrogates</h2>
<p> This is not the time for me to explain how you write a
surrogate class, I'll do that another time. However you should know
what one of these is and then you will understand how they can assist
with our problem of a container of sub-types.</p>
<p> Basically a surrogate is a way of encapsulating the
behaviour of a polymorphic hierarchy so that the many low level details
are hidden from the client programmer. Consider all the be&shy;haviour
you have to provide when handling instances of a polymorphic hierarchy
via pointers. You have to remember to construct instances, destroy
them, manage copying and so forth. You also have to handle the
interface provided by the (probably abstract) base class of the
hierarchy. In an ideal world you proba&shy;bly wish that you could have
instances of your abstract base class that behaved temporarily like a
specific concrete derived class. The mechanism of writing a surrogate
almost meets that wish.</p>
<p> Using a surrogate allows you to have a con&shy; tainer of
polymorphic objects. The copying and cloning problems will be handled
by the surrogates member functions. As far as the user is concerned
they will be handling a single type that happens to have variable
behaviour determined initially by the constructor, and then by its
subsequent history. If you do not know about this idiom, I strongly
advise you to go and master it, every journeyman C++ pro&shy;grammer
should have it in her toolkit.</p>
<h2>Summary</h2>
<p> If you want a container with a mixture of owned and
non-owned objects you will need to use a container of a handle type
that can track ownership. You may well enhance this into a smart
pointer. You certainly will need to con&shy;sider how to manage the STL
containers value based behaviour by somehow restricting the algorithms
that can be applied to your con&shy;tainer.</p>
<p> If you want a container of objects from a po&shy; lymorphic
hierarchy and you need to recover the type information (because you
need to use sub-type specific interface extensions for ex&shy;ample)
via<span style="font-family: monospace;"> dynamic_cast&lt;</span>&gt;
then you will need to work rather harder. In
such cases you should seriously consider a sufficiently power&shy;ful
smart pointer. Indeed you need positive reasons for not using one. And
as in the previ&shy;ous case you must handle the consequences of
containers being managed by value copying.</p>
<p> If you have the case of objects with a uniform interface
but polymorphic behaviour they should be handled via a surrogate class.
If you are not already writing surrogates for such type hierarchies you
should examine your reasons because this is the natural idiom for such
types.</p>
<p> Note that in all cases raw pointers are wrapped up and
hidden from the high level program&shy;mer. On second thoughts, perhaps
we might even reconsider smart pointers. Are they really that valuable?
What do you think? Anyone for the prosecution? What about the defence?
How and when should we use smart pointers? To be honest, I do not know.
I think it is time that some of the rest of you added your thoughts. If
I can stand our esteemed editor's criticisms, I am sure you can.</p>
<p> Finally, some of you may wonder why I have not suggested
using <span style="font-family: monospace;">auto_ptr&lt;&gt;</span>.
It is part of the Draft Standard C++ Library
and you know how keen I am on using libraries rather than rolling your
own (probably inferior) product. The Standards Committees broke it in
one of their recent revisions. I have no idea why, and as far as I can
find out, all they did in Hawaii was to mend it with sticking plaster.
The result is too dangerous for use by non-experts, and experts can do
better anyway. I think this is C++'s equivalent of C's <span
 style="font-family: monospace;">gets()</span>, good idea but
dangerously flawed.</p>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
