    <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  :: Circles and Ellipses revisited: coding techniques - 2</title>
        <link>https://members.accu.org/index.php/articles/1454</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>




<div class="xar-mod-head"><span class="xar-mod-title">Programming Topics + Overload Journal #17/18 - Jan 1997</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/articles/">All</a>

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

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

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

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

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

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

                                            <a href="https://members.accu.org/index.php/articles/c65-228/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c65+228/">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;Circles and Ellipses revisited: coding techniques - 2</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 31 January 1997 08:55:00 +00:00 or Fri, 31 January 1997 08:55:00 +00:00</p>
<p><strong>Summary:</strong>&nbsp;A second approach: In-store changes</p>
<p><strong>Body:</strong>&nbsp;<p>As noted by Francis, it is possible to overlay objects in
store with others of different types.[<a href="#1">1</a>] There are
several options
available to implement the overlays, such as the use of placement new,
and memcpy(), some of which are illustrated here.</p>
<h2>Classes used in illustration of in- store object change</h2>
<p>The techniques illustrated below show how a given object
constructed on the stack or in free store might be overwritten by one
of a different type, and some of the effects involved. The
examples use a base class B, with two publicly derived classes Dl and
D2. They also use a morphing type U which is, roughly speaking, the
union of Dl and D2. Variations to support morphing between Dl and D2
objects directly will be obvious. The effects are illustrated by use of
a single function f(), implemented for all the above classes, and whose
observed be-haviour depends on the state of the U object.</p>
<p> The object of type U can have its data area (members), and
most importantly its pointer to its virtual function table
(vtable) overlaid by a Dl or D2 at will, thus changing its observed
data and functions. The overlay can be achieved by:<br>
</p>
<ol>
  <li>overloading assignment for the U class (supplying a version
which assigns from a reference to a B, returning a reference to a U.)</li>
  <li>providing a change() member function in U</li>
  <li>providing a placement new: globally, in the base class B, or in
the derived classes as well as:</li>
  <li>creating a U in an initial Dl or D2 state by an appropriate
constructor.<br>
  </li>
</ol>
<p>These options are illustrated in listings below. The
semantics of the overlay are very simple in all these cases, such as
bitwise copy using memcpy(); but copy constructors and/or
addi-tional processing could also be used.</p>
<p>For example:</p>
<ol>
  <li><br>
  </li>
  <ol style="list-style-type: lower-alpha;">
    <li>Use of overloaded assignment operator in &quot;union&quot; class<br>
      <pre>class B <br>{ <br>public:<br>  virtual void f()<br>  { cout &lt;&lt; &quot;B's f()\n&quot;; }<br>};<br><br>class D1 : public B<br>{<br>public:<br>  void f() { cout &lt;&lt; &quot;Dl's f()\n&quot;; }<br>};<br><br>class D2 : public B<br>{<br>public:<br>  void f() { cout &lt;&lt; &quot;D2's f()\n&quot;; }<br>};<br><br>// define a union,<br>// just to get max of sizeof(Dl),<br>// sizeof(D2), ...<br>union Usz<br>{ unsigned char a[sizeof(D1)];<br>  unsigned char b[sizeof(D2)];<br>  // ... and any other derived types<br>};<br><br>class U <br>{ <br>public:<br>  virtual void f()<br>  { cout &lt;&lt; &quot;U's f()\n&quot;; }<br>  U &amp;operator=(B&amp; b)<br>  { memcpy(this, &amp;b, sizeof(U));<br>    return *this; } <br>private:<br>    size_t a[ sizeof(Usz) ]; // filler<br>};<br></pre>
    </li>
    <li>As above, making a more refined size calculation, and
exercising the code <br>
      <pre>// B, D1, D2 etc as above<br>class U <br>{<br>public:<br>  virtual void f()<br>  { cout &lt;&lt; &quot;U's f()\n&quot;; )<br>  U &amp;operator=(B&amp; b)<br>  { memcpy( this, &amp;b, sizeof(U) );<br>    return *this; } <br>private:<br>  typedef union USZ // union is used to <br>                    // get a filler size, to allow a U to <br>                    // be overlaid by any D, ie max of <br>                    // sizes of: Dl, D2, ... . <br>  {<br>    char a[sizeof(Dl)]; <br>    char b[sizeof(D2)]; <br>    // ... and any other derived types <br>  } Usz;<br>  class C { // for size adjustment only <br>    virtual void vf() { return; }<br>  }; <br>  char a[sizeof(Usz) - sizeof(C)]; // filler<br>};<br><br>int main()<br>{<br>  U u; <br>  u.f();     // calls U's f()<br><br>  D1 d1; D2 d2; <br>  u = d1; <br>  u.f();     // calls U's f()<br>  U* up = &amp;u; <br>  up-&gt;f();   // call d1's f()<br>             // - iff U's f() virtual<br>  u = d2; <br>  up-&gt;f();   // call D2's f()<br>             // - iff U's f() virtual<br>  ...<br>}<br></pre>
      <p>(Note: the method of calculation of the size of the filler
in class U above is intended to mini-mise the size of the &quot;union&quot;
objects - but it is less portable than the previous method shown.)</p>
    </li>
  </ol>
  <li>
    <p>Change of U's effective type by a change() function:<br>
    </p>
    <pre>// classes B ... U as above, with <br>// additional U member, a change() <br>// function: <br>  U &amp;change(int i) <br>  {<br>    D1 d1; D2 d2; <br>    if (i == 1)<br>      memcpy(this, &amp;d1, sizeof(U)); <br>    else if (i == 2)<br>      memcpy(this, &amp;d2, sizeof(U));<br>    return *this;<br>  }</pre>
  </li>
  <li><br>
  </li>
  <ol style="list-style-type: lower-alpha;">
    <li>
      <p>Create U as different types, by use of a global
overload of <span style="font-family: monospace;">operator new</span><br>
      </p>
      <pre>// Global overload of operator new<br>void *operator new(size_t, void *p)<br>{<br>  return p;<br>}<br><br>// B, Dl, D2 as before<br>class U<br>{<br>public:<br>  U(double e = 0.0)<br>  {<br>    if ( e == 0 ) new (this) D1;<br>    else<br>    if ( e &lt; 1 ) new (this) D2;<br>  }<br>  ...<br>};<br></pre>
      <p></p>
    </li>
    <li>
      <p>As above, but with <span style="font-family: monospace;">operator
new</span> overloaded in B,
rather than globally<br>
      </p>
      <pre>class B<br>{<br>public:<br>  void *operator new(size_t, void *p )<br>  {<br>    return p;<br>  }<br>  virtual void f()<br>  { cout &lt;&lt; &quot;B's f()\n&quot;; }<br>};<br></pre>
      <p></p>
    </li>
    <li>
      <p>The identical effect could be accom- plished by
overloading operator new in each of the derived classes, Dl, D2, using
identical code to the above overload in B.<br>
      </p>
    </li>
  </ol>
</ol>
<h2><span style="text-decoration: line-through;">Problem</span>
Opportunity pages</h2>
<p>There are several problems with such ap- proaches which
overlay instances of one type with another. These can be summarised:<span
 style="font-weight: bold;"><br>
</span></p>
<ul>
  <li>typeid() can report a misleading (wrong) type&nbsp;</li>
  <li>results can differ between Object.foo(), and
(&amp;Object)-&gt;foo()</li>
  <li>in particular, due to the above, results can differ between
creating an object on the stack, accessing it by its name, and an
identical object in free store, accessed by a pointer</li>
  <li>assumptions on the implementation of polymorphism limit
portability</li>
  <li>sizeof() could report a misleading (wrong) size</li>
  <li>use of (non-morphing) raw pointers could cause problems</li>
  <li>arrays of morphing types need special consideration</li>
</ul>
<p>Some of these problems are discussed in more detail below.</p>
<h3>The typeid() problem</h3>
<p>In the discussion of the circle/ellipse problem, The
Harpist pointed out a problem with this kind of (store overlay)
approach, which in this &quot;Man&quot; example could be represented:</p>
<pre>
Schoolboy S;<br>S.setAge(40) ;<br>if ( typeid(S) == typeid(MiddleAge)<br>{<br>  cout &lt;&lt; &quot;Type changed&quot; &lt;&lt; endl;<br>}<br></pre>
<p>That is, given a setAge() function which could act on S, would
the compiler/optimiser system be expected to respect possible
changes to the type of object which we are overlaying onto the storage
area originally set up for S as a Schoolboy? The Harpist points out
that the system might reasonably assume that it could identify the type
needed for the typeid call on the basis that an S was created, with no
poly-morphic behaviour being invoked by use of a reference or
pointer. [<a href="#2">2</a>] (This is true even if the type is
declared <span style="font-family: monospace;">volatile</span>, as in:</p>
<pre>
volatile Schoolboy S;</pre>
<h3>Different behaviour between Object.foo(). and
(&amp;Obiect)-&gt;foo()</h3>
<p>Closely related to the above problem, and per-haps of more
general concern, is that the com- piler will be inclined to make
this kind of optimisation for any function invoked with the syntax
Object.foo() ignoring the fact that the object has
changed beneath its feet; and that execution via a pointer syntax will
give a dif-ferent result. That is:</p>
<pre>
T Object, *p;<br>p = &amp;Object;<br>Object.foo();  // gives different<br>               // result from<br>p-&gt;foo();      // pointer invocation<br></pre>
<p>Nevertheless, where this could cause problems, they could
be overcome by writing the code so that foo() always invoked the same
function, irrespective of how it was invoked. (This could be done by
rolling one's own virtual function mechanism, with foo() defined in a
base class as forwarding its function call by dereferenc-ing a
pointer to function, this pointer being set up appropriately by the
derived class constructors.)</p>
<h3>Aside (casting)</h3>
<p>The examples could have implemented casting in the form of
overloads for operator type(). Some related points can be noted:</p>
<ul>
  <li>It is possible to suppress such casts by declaring them protected
or private, just as it is possible to similarly prevent copying by
assignment or construction</li>
  <li>However casting is treated, it will be incomplete, as one might
like to be able to implement or restrict pointer casts as well as casts
of class types; in particular it would be desirable to change the type
of a raw pointer in synchronism with the effective type of the object
that it pointed to. &nbsp;
Also, it is not possible to overload the new-style casts.<br>
    <br>
    <span style="font-style: italic;">Perhaps template&lt;typename
T&gt; operator T(); would help
here as a member conver-sion operator? - Ed.</span><br>
  </li>
</ul>
<h3>Problems with arrays</h3>
<p>Arrays of such morphing types need special consideration in
respect of space efficiency. (If implemented as a simple array of
&quot;U&quot;s), and element access using a pointer to an element of a sub-type
(eg a &quot;D1 *&quot;).</p>
<h3>Assumptions about implementation of polymorphism</h3>
<p>Where virtual functions are used, these tech- niques would
typically assume an implementa-tion mechanism with a pointer to the
virtual function table being at a fixed offset in all ob-jects.
This is a reasonable working assumption, but code which made it would
fail if, for in-stance, various sized classes were used and the
compiler placed the pointer at the end of each object.</p>
<p><span style="font-style: italic;">Several implementations do
precisely that Ed.
</span><br>
</p>
<h3>Differences between stack and freestore behaviour<br>
</h3>
<p>Many of the problems noted above arise when a morphable
object is created on the stack (and accessed by its name), but not when
it is created on free store (and accessed via a pointer).</p>
<h2>Continue (y/n)?</h2>
<p>One might be inclined to reject techniques which overlay
store, particularly on the stack, where the corresponding object name
can be assumed by the compiler to have a fixed type. But where the
potential problems above are recognised and are accepted, they can be
avoided by careful coding.</p>
<h2>Conclusion</h2>
<p>Several approaches to the problem of morphing objects are
possible. By building different behaviours into a given type, the
de-sired effects can largely be achieved. Many such approaches are
possible, but they suffer from the limitations mentioned above.</p>
<p>The approach suggested here is that the appli- cation model
should assume that there is a con-stant type for the mutable object
involved -Man or Conic in the above examples - even if states in the
life history are modelled by other classes. These other classes would
typically be related to the superclass by derivation and/or use of the
handle-body idiom. One option here is to use Coplien's Envelope-Letter
idiom, as will be described in the next article in this se-ries.
With this kind of approach, the system provided typeid() will always
return the same type irrespective of the state of the handle
ob-ject involved; user-provided additions can re-port on
sub-state information if required. Merits of the technique include the
fact that the model is simple, flexible, and can map state transitons
directly in code.</p>
<h2>References</h2>
<p>
[<a name="1"></a>1] Francis Glassborow, &quot;Circle &amp; Ellipse -
Creating Polymorphic Ob- jects&quot;, Overload, Issue 8, pp 26 -
28<br>
[<a name="2"></a>2] The Harpist, &quot;Joy Unconfined - reflections on three
issues&quot;, Overload, Issue 9, pp 11 - 13
</p></p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
