    <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  :: Student Code Critique Competition 5</title>
        <link>https://members.accu.org/index.php/articles/1063</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">Student Code Critiques from CVu journal. + CVu Journal Vol 12, #5 - Sep 2000</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/c184/">Journal Columns</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c183/">Code Critique</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/c77/">CVu</a>

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

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

                    -                        <a href="https://members.accu.org/index.php/articles/c183+124/">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;Student Code Critique Competition 5</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 07 September 2000 13:15:40 +01:00 or Thu, 07 September 2000 13:15:40 +01:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e20" id="d0e20"></a></h2>
</div>
<p class="c2"><span class="remark">Prizes for this competition are
provided by Blackwells Bookshops in co-operation with
Addison-Wesley.</span></p>
<p class="c2"><span class="remark">I think you will entirely agree
with my choice of winning entry when you have read this item, but I
will not spoil it for you by saying more here.</span></p>
<p class="c2"><span class="remark">You will find the code for this
issue's competition at the end of this column. Why not make my job
harder (though more rewarding) by sending in an entry this
time.</span></p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e31" id="d0e31"></a>Code from last
issue</h2>
</div>
<pre class="programlisting">
class Book {
public:
  virtual void details();
  void details(char* , char *, float ); //Author, Title,Pages
  virtual void anzeigen();
  Book();     ~Book();
  Book(char*, char *, float);
  Book(const Book&amp;);
  Book&amp; operator=(const Book&amp;);
  bool operator== (const Book&amp; );
protected:
  struct book {
    char* title;
    char* author;
  float price; } b;
};
</pre>
<p>and the class:</p>
<pre class="programlisting">
class ChildBook: public Book {
public:
  int reading_age;
  virtual void details();
  void details(char* , char *, float ,int);
                        //author, title, pages
  virtual void anzeigen();
  ChildBook();
  ChildBook(char*, char *, float, int);
  ChildBook(const ChildBook&amp;);
  ~ChildBook();
  ChildBook&amp; operator=(const ChildBook&amp;);
  bool operator== (const ChildBook&amp;);
};
</pre>
<p>Furthermore, there is the class</p>
<pre class="programlisting">
class BookList: public Book {
public:
  Book b;
  ChildBook k;
  list&lt;Book&gt; Book;
  list&lt;ChildBook&gt; kiBook;
  void details();
  void anzeigen();
  ~BookList();
  BookList();
};
</pre>
<p>which also derives from <tt class="classname">Book</tt>. It
should represent a kind of Library. In the <tt class=
"function">main()</tt> function I make an instance of class
<tt class="classname">BookList</tt> and assign different values to
the components:</p>
<pre class="programlisting">
BookList bue;
//one component for Book
bue.Book.push_back(Book(&quot;Book&quot;,&quot;Title&quot;,20));
//one component for ChildBook
bue.kiBook.push_back(ChildBook(&quot;Author&quot;
      ,&quot;Title&quot;,35,5));
</pre>
<p>If I walk trough the program using the debugger, I can see that
the list-entry for <tt class="classname">Book</tt> is created
rightly, whereas the entry for <tt class="classname">ChildBook</tt>
is destroyed immediately after creation. Every time after creating,
the destructor is launched - why? At the component <tt class=
"classname">Book</tt> it is all correctly (in spite of launching
the destructor!). For the <tt class=
"classname">ChildBook</tt>-object it seems that the wrong entry is
deleted. There are some constructors of the classes</p>
<pre class="programlisting">
Book::Book() {
  b.author = new char[10];
  strcpy(b.author,&quot;Author&quot;);
  b.title = new char[10];
  strcpy(b.title,&quot;Title&quot;);
  b.price = 0.00f;
}
Book::Book(char * t, char * a, float p) {
  b.author = new char[strlen(a)+1];
  b.title = new char[strlen(t)+1];
  strcpy(b.author,a);
  strcpy(b.title,t);
  b.price = p;
}
Book::Book(const Book&amp; p)   {
  b.title = new char[strlen(p.b.title)+1];
  strcpy(b.title,p.b.title) ;
  b.author = new char[strlen(p.b.author)+1];
  strcpy(b.author,p.b.author) ;
  b.price = p.b.price;
}
Book::~Book () {
  delete b.title;
  delete b.author;
}
ChildBook::ChildBook() {reading_age=3;}
ChildBook::~ChildBook() {  }
ChildBook::ChildBook(char * t, char * a,
       float p, int la) : Book(t,a,p){
  reading_age=la;
}
ChildBook::ChildBook(const ChildBook&amp; k){   b=k.b;
  reading_age=k.reading_age;
}
BookList::BookList(){ }
BookList::~BookList(){ }
</pre></div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e73" id="d0e73"></a>The
Critiques</h2>
</div>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e76" id="d0e76"></a>Critique from
Colin Hersom <tt class="email">&lt;<a href=
"mailto:colin@hedgehog.cix.co.uk">colin@hedgehog.cix.co.uk</a>&gt;</tt></h3>
</div>
<p>I shall work through the example in the order printed. It is
clearly a fragment, since there is no inclusion of <tt class=
"filename">&lt;list&gt;</tt>, which is required for
compilation.</p>
<pre class="programlisting">
class Book
</pre>
<p>Well, OK. One could argue that the class is merely a means of
identifying a book, rather than representing a whole book. The name
&quot;Book&quot; might imply rather more, like the complete contents, layout,
page numbering etc.</p>
<pre class="programlisting">
virtual void details();
</pre>
<p>What does this function do? It is virtual, so derived classes
are expected to override it, but there being no description it is
difficult to know what ought to happen. Since the function takes no
parameters and returns nothing it probably does something to its
data members (well, it isn't const, so it is allowed to change its
own state). Maybe it uses some globals, like printing to standard
output. If so, passing in the data it needs would be far clearer
and allow it to write to other files, e.g.:</p>
<pre class="programlisting">
virtual void details(ostream&amp;);
void details(char*, char*, float);
</pre>
<p>Now one thing that strikes me is whether the author thought that
using the same name as the previous routine somehow endowed the
virtualness onto this routine, and the details routine does not
exist at all. This is not how C++ works, if two functions declared
in a class have different arguments, then they are different
functions, and virtualness does not transfer to similarly named
functions.</p>
<p>What about that comment? We can embed the names of parameters in
the prototype, which obviates the old C-style necessity of making
them comments, so the prototype ought to be:</p>
<pre class="programlisting">
void details(char *Author, char *Title, 
                      float Pages);
</pre>
<p class="c2"><span class="remark">[actually, those char*
parameters almost certainly should be of type <tt class="type">char
const*</tt> FG]</span></p>
<p>How many pages are we expecting? So many that the number won't
fit into 32 bits? I hardly think so. You would have a book several
kilometres wide with that number of pages. Peeking ahead, I see
that the data stored is &quot;price&quot; not &quot;pages&quot;, so is the comment
out-of-date? A very frequent occurrence, and the problem with
comments that aren't really part of the code. I would also be
worried that since the first two parameters are both the same type,
they may be the other way round from that stated, since this is the
way the data is stored in the class.</p>
<p>Why do we want to add the details of the book after it is
created? Surely the only thing that might change is the price, just
possibly the title, but unlikely all together. We probably need a
function:</p>
<pre class="programlisting">
void SetPrice(float price);
</pre>
<p>which would just change the price of the book.</p>
<pre class="programlisting">
virtual void anzeigen();
</pre>
<p>I am reliably informed that this could be translated as &quot;show&quot;.
So maybe this is the routine that displays the data. The same
comments apply to this as to details above.</p>
<pre class="programlisting">
Book();
</pre>
<p>Unless we are in the business of creating a book from scratch, I
cannot see the requirement for this constructor. It should probably
be private and not be implemented.</p>
<pre class="programlisting">
~Book();
</pre>
<p>Now we have already established that this class is to be used as
a base, by the existence of virtual functions, so the destructor
really ought to be virtual. It is extremely rare that you can
guarantee that the destructor will always be called at the right
level of hierarchy, and if a derived class is deleted though the
base type then problems will occur. If the compiler knows that it
can bypass the virtual table, then it will. Normally it will not,
so making the destructor virtual ensures that the correct function
is called.</p>
<pre class="programlisting">
Book(char*, char*, float);
</pre>
<p>Once again, there are no parameter names, so I cannot be sure
which way around the first two arguments are supposed to be
provided. Shouldn't the arguments be <tt class=
"literal">const</tt>?</p>
<pre class="programlisting">
Book(const Book&amp;);
Book &amp; operator= (const Book&amp;);
</pre>
<p>No problems with these</p>
<pre class="programlisting">
bool operator == (const Book&amp;);
</pre>
<p>Since I assume that this only compares two <tt class=
"classname">Book</tt> objects, why is it not a <tt class=
"literal">const</tt> function?</p>
<pre class="programlisting">
bool operator == (const Book &amp;book) const;
</pre>
<p>This would prevent the accidental writing of:</p>
<pre class="programlisting">
return price = book.price;
</pre>
<p>which, far from comparing the prices, would overwrite the
current price with that being compared.</p>
<pre class="programlisting">
protected:
  struct book {
  char *title;
  char *author;
  float price; } b;
</pre>
<p>Why is the data protected, not <tt class="literal">private</tt>?
Unless there is a very good reason, data should be <tt class=
"literal">private</tt>, and derived classes should use the
<tt class="literal">public</tt> or <tt class=
"literal">protected</tt> functional access to that data. This
ensures a very restricted set of routines that can alter the data;
making debugging easier.</p>
<p>Why is the data being hidden in a <tt class=
"literal">struct</tt>? The class itself is a structure, and there
is no reason to add a further level of hierarchy. In fact, adding
this level prevents constructor initialisers from being used,
unless this structure is given its own constructor, which starts to
look very silly.</p>
<p>Why are you using <tt class="type">char*</tt>? Use the STL type
string and you will produce far fewer errors in your code.</p>
<p>I do not think that the price should be a float (assuming that
it is the price, not the number of pages). Holding the price as a
fixed-point value (i.e. in whole pennies, pfennigs, cents, etc)
ensures that price comparisons can be made without regard to
strange floating-point effects. You might want to wrap a class
round it so that you can determine centrally how to print the
price, or provide currency conversions.</p>
<pre class="programlisting">
class ChildBook : public Book
</pre>
<p>Seems perfectly reasonable.</p>
<pre class="programlisting">
public:
   int reading_age;
</pre>
<p>Why is this piece of data <tt class="literal">public</tt>?</p>
<pre class="programlisting">
void details(char*, char*, float, int);
</pre>
<p>This looks like a copy-and-paste job from the base class. The
comment clearly does not match the function prototype, since there
are now four arguments but only three comments.</p>
<p>The rest of the functions in this class are the same as those in
the base, and so the comments for the base apply here too.</p>
<pre class="programlisting">
class BookList : public Book
</pre>
<p>Is the <tt class="classname">BookList</tt> a <tt class=
"classname">Book</tt> in its own right? Well, it could be, since
one's library might contain an index to all the books in it. I
shall leave this be for the moment.</p>
<pre class="programlisting">
  Book b;
  ChildBook k;
</pre>
<p>So this book contains two other books? It does not look right,
but given no example of its use, I cannot be certain that it is
wrong.</p>
<pre class="programlisting">
list&lt;Book&gt; Book;
</pre>
<p>Now my compiler warns me that I am reusing the identifier Book,
originally a class name, and now as a variable name. With the
implementation as it stands, the file will still compile, but
warnings should be heeded because it might indicate problems to
come. If you use an initialiser in the constructors of this class,
then the base class is called <tt class="classname">Book</tt>, and
so is this member, so the compiler will not be able to distinguish
between the two.</p>
<pre class="programlisting">
list&lt;ChildBook&gt; kiBook;
</pre>
<p>You have provided a separate list for <tt class=
"classname">ChildBook</tt>s. What happens when you want to derive
further types from <tt class="classname">Book</tt>? Do you need a
list for each derived type? That does not sound very useful. Would
it not be better to have a single list of pointer types (possibly
smart pointers) so that any book type could be added to the list?
At the moment you cannot add a BookList object to the list without
losing information, since the object stored would only be the base
<tt class="classname">Book</tt>, not the full <tt class=
"classname">BookList</tt> type.</p>
<p>If that does not make sense ask this question: Do you really
have a book (the <tt class="classname">BookList</tt>) that contains
many other books? I suspect that either the derivation from
<tt class="classname">Book</tt> is wrong (so <tt class=
"classname">BookList</tt> is not itself a <tt class=
"classname">Book</tt>), or your <tt class="classname">BookList</tt>
ought to contain a list of pointers to books.</p>
<pre class="programlisting">
  void details();
  void anzeigen();
</pre>
<p>No comment.</p>
<pre class="programlisting">
  ~BookList();
  BookList();
</pre>
<p>Where are the copy constructor and assignment operators? They
need to be provided in the class, but possibly not implemented.</p>
<pre class="programlisting">
bue.Book.push_back(Book(&quot;Book&quot;, &quot;Title&quot;, 20));
  bue.kiBook.push_back(ChildBook(&quot;Author&quot;,
         &quot;Title&quot;, 35, 5));
</pre>
<p>So the order of arguments for the constructor is author, title
is it?</p>
<p>What do these lines do? Firstly, create a <tt class=
"classname">Book</tt>/<tt class="classname">ChildBook</tt> object
with the appropriate constructor. This is a temporary on the stack.
Then it copies that object into the appropriate list. Note that the
created object is not put into the list. Why not? Because if it
were, at the end of the statement the temporary is deleted and the
list becomes inconsistent. All STL containers take possession of
their contents by copying them to ensure that users cannot produce
inconsistencies in this way (although it cannot guarantee safety if
you use raw pointers).</p>
<p>Why is there no &quot;add book to list&quot; function in <tt class=
"classname">BookList</tt>? Why are all the members <tt class=
"literal">public</tt>? Surely to save work when you (inevitably)
decide to change things, you should have a function to conceal the
implementation of the <tt class="classname">BookList</tt>:</p>
<pre class="programlisting">
void addBook(const Book&amp;);
</pre>
<p>If you follow my advice earlier, then you need to pass a pointer
to the <tt class="classname">Book</tt>, so this would become:</p>
<pre class="programlisting">
void addBook(const Book*);
</pre>
<p>and your function calls above would be:</p>
<pre class="programlisting">
bue.addBook(new Book(&quot;Book&quot;, &quot;Title&quot;, 20));
  bue.addBook(new ChildBook(&quot;Author&quot;,
                        &quot;Title&quot;, 35, 5));
</pre>
<p>whether the addition of <tt class="classname">ChildBook</tt> and
<tt class="classname">Book</tt> do different things can be decided
inside <tt class="classname">BookList</tt>, rather than hard-wiring
it externally.</p>
<pre class="programlisting">
Book::Book()
</pre>
<p>I have already stated that this function is probably redundant.
It certainly should not fill in arbitrary data.</p>
<pre class="programlisting">
Book::Book(char *t, char *a, float p)
</pre>
<p>Aha! So the parameter order is title, author. We could be in for
some surprises here.</p>
<pre class="programlisting">
b.author = new char[strlen(a) + 1];
   strcpy(b.author, a);
</pre>
<p>Now there is a library function to do this:</p>
<pre class="programlisting">
b.author = strdup(a);
</pre>
<p class="c2"><span class="remark">[Colin is mistaken here, many
unix systems provide such a function for C, but it is not a
standard function, not least because who is going to do the
cleanup. FG]</span></p>
<p>That saves the potential problem of allocating the incorrect
amount of space, by forgetting the +1 in strlen, for example. This
means that you should be able to do all the work in the
initialisers, e.g.:</p>
<pre class="programlisting">
  Book::Book(char *t, char *a, float p)
      : title(strdup(t)), author(strdup(a))
                      , price(p)
  {}
</pre>
<p>However, with your nested struct, this cannot be done, since
title etc. are not in the direct scope of <tt class=
"classname">Book</tt>.</p>
<p>Had you used strings, then the constructor would be even
simpler:</p>
<pre class="programlisting">
Book::Book(const string &amp;t, 
          const string &amp;a, float p)
  : title(t), author(a), price(p)
  Book::Book(const Book &amp;p)
</pre>
<p>The same comments apply to this function as to the previous one.
There is no reason to have anything the in the body of the
constructor.</p>
<pre class="programlisting">
Book::~Book(){
  delete b.title;
  delete b.author;
}
</pre>
<p>I am glad you knew to <tt class="literal">delete</tt> these data
members. Had you used string types, then the destructor would be
empty - mush simpler to write.</p>
<p class="c2"><span class="remark">[and he would have avoided the
trap of using the wrong form of delete. FG]</span></p>
<pre class="programlisting">
  ChildBook::ChildBook(char *t, char *a, 
                  float p, int la)
  : Book(t,a,p)
</pre>
<p>Why haven't you used the initialiser notation for <tt class=
"varname">reading_age</tt>? I know it does little for you while
<tt class="varname">reading_age</tt> is an integer, but suppose it
is changed at some stage to be some other type that looks like an
integer but does more? For example a type that checks that the
value is within reasonable bounds? Use the initialisers and then
you are likely to have less to change when you improve the
types.</p>
<pre class="programlisting">
  ChildBook::ChildBook(const ChildBook &amp;k){
    b = k.b;
    reading_age = k.reading_age;
  }
</pre>
<p>Now here is the crunch. There is no excuse for not using the
parent class's constructor from the child's. In fact, it is rarely
right to omit the parent class's constructors. As it stands, the
<tt class="classname">Book</tt>'s default constructor is used,
creating useless space and wasting time, and then you are trying to
copy the <tt class="classname">ChildBook</tt>'s data into it. What
does the line <tt class="literal">b = k.b</tt> do? It copies the
bit pattern of <tt class="varname">k.b</tt> into <tt class=
"varname">b</tt>. It does not duplicate any strings and you lose
the space allocated in the <tt class="classname">Book</tt>
constructor. When the argument <tt class="varname">k</tt> is
deleted, the pointers in the newly-copied <tt class=
"classname">ChildBook</tt> will continue to point to those in k and
will thus be pointing to freed space - and there is your original
problem. Had you made the data in <tt class="classname">Book</tt>
<tt class="literal">private</tt>, or removed the default <tt class=
"classname">Book</tt> constructor, then you would have been forced
to use the <tt class="classname">Book</tt>'s copy constructor and
these mistakes would never have occurred.</p>
<p>However you implemented <tt class="classname">Book</tt>, the
<tt class="classname">ChildBook</tt> copy constructor ought to
be:</p>
<pre class="programlisting">
ChildBook::ChildBook(const ChildBook &amp;k)
  : Book(k), reading_age(k.reading_age) {}
</pre>
<p>Finally:</p>
<pre class="programlisting">
BookList::BookList(){}
</pre>
<p>Why are none of the data members initialised? You have a
base-class <tt class="classname">Book</tt> that needs a
constructor, and those members <tt class="varname">b</tt> &amp;
<tt class="varname">k</tt>.</p>
<p class="c2"><span class="remark">Thanks, Colin, for a
comprehensive critique. Curiously, while you have identified many
of the faults with the code, you have missed the cause of the
destructor call that was puzzling the student. FG</span></p>
</div>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e431" id="d0e431"></a>The Case Of The
Unsafe Shallows by Steve Love <tt class="email">&lt;<a href=
"mailto:steve.love@tnt.co.uk">steve.love@tnt.co.uk</a>&gt;</tt></h3>
</div>
<p>&quot;What do you make of this, Holmes?&quot; On our return from the
Diogenes Club where we had dined with Mycroft Holmes, brother of my
esteemed companion, Sherlock, I discovered upon our doorstep an
envelope addressed to &quot;Mr. S. Holmes And Dr. J. H. Watson&quot;.</p>
<p>&quot;Open it, then Watson! Let us hear it!&quot; he cried with vigour.
&quot;After such a dull week as this, I shall be happy to look into any
small problem our mystery correspondent is troubled with.&quot;</p>
<p>I sat at the bureau, and slit open the envelope. Without being
asked, I passed the envelope to Holmes, and quickly read through
the letter it had contained.</p>
<p>&quot;There is nothing of interest on the envelope. What of the
contents?&quot; Holmes asked.</p>
<p>&quot;It appears to be some kind of code,&quot; I replied, passing the
letter over. &quot;I'm afraid I can make neither head nor tail of
it.&quot;</p>
<p>Holmes peered at me mischievously through his eyebrows. &quot;Very
well, then. We'll see if I can do any better.&quot;</p>
<p>As soon as he looked at the page, his eyes lit up. &quot;Ah hah! A
real rarity. It has been a long time since some poor soul has
looked to me for their programming problems. C++ code, I see.&quot;</p>
<p>&quot;You've heard of this code, then Holmes?&quot;</p>
<p>&quot;Hmm. I wrote one or two short monographs on the subject when I
was younger. You might care to look them up, if the subject is to
your interest.&quot; He returned his concentration to the page, while I
retreived the papers he mentioned, and quickly scanned through the
text for clues as to how my companion might continue.</p>
<p>The facts appear to be these. We have three classes, <tt class=
"classname">Book</tt>, <tt class="classname">ChildBook</tt> and
<tt class="classname">BookList</tt>. A book represents an entity
with a title, author and price. A <tt class=
"classname">ChildBook</tt>, now what is that? Ah, I see now. It is
a book for children! In addition to the main data for <tt class=
"classname">Book</tt>, we have a reading age entry. <tt class=
"classname">ChildBook</tt> is derived from <tt class=
"classname">Book</tt>, but unsafely, I perceive. Ah well, we'll
return to the details momentarily.</p>
<p>&quot;<tt class="classname">BookList</tt> is also publicly derived
from <tt class="classname">Book</tt>, and yet has both a <tt class=
"classname">Book</tt> and a <tt class="classname">ChildBook</tt>
data member, and a list of each. Well, definitely a rather serious
error in design for us to consider in our diagnosis, Watson.&quot;</p>
<p>I'm afraid I was left a little bemused by Holmes' apparent
knowledge of the subject, and so asked for an elaboration.</p>
<p>&quot;It is a small matter, but an important one. When publicly
deriving a class from another, one must ensure that the derived
class satisfies the <span class="emphasis"><em>identity</em></span>
of the base class; one must ensure the derived class <span class=
"emphasis"><em>IS A</em></span> base class, in the sense that they
can be interchanged. In this case, a <tt class=
"classname">ChildBook</tt> clearly <span class="emphasis"><em>IS
A</em></span> <tt class="classname">Book</tt>, and so satisfies
this condition, but a <tt class="classname">BookList</tt> is not.
On the other hand, when privately deriving a class, the derived
class is said to be <span class="emphasis"><em>IMPLEMENTED IN
TERMS</em></span> OF the base class, which can often be achieved
through aggregation: including a data member of the base class type
in the derived class itself. Unfortunately, <tt class=
"classname">BookList</tt> doesn't exhibit an <span class=
"emphasis"><em>IS A</em></span> relationship with <tt class=
"classname">Book</tt>, but it is <span class=
"emphasis"><em>IMPLEMENTED IN TERMS OF</em></span> <tt class=
"classname">Book</tt>. From what I can see, it is merely a
collection of <tt class="classname">Book</tt>s and <tt class=
"classname">ChildBook</tt>s, and thus needs no inheritance
relationship.&quot;</p>
<p>My frantic cribbing of Holmes' notes gave me a basic
understanding of the terminology. I nodded for him to continue.</p>
<p>&quot;Now we get to the crux of the matter. Our friend is having
difficulty populating his <tt class="classname">BookList</tt>
entries with new <tt class="classname">Book</tt>s and <tt class=
"classname">ChildBook</tt>s. Well, no surprise so far. What is
puzzling is the apparent execution of the <tt class=
"classname">ChildBook</tt> destructor immediately after insertion
into the list. Perhaps these function bodies will throw some light
on the subject.</p>
<p>&quot;Firstly, the creation of a <tt class="classname">Book</tt>. We
allocate memory space for the author, and then initialise it. Then,
we allocate more memory for the title, and initialise that.
Finally, we set the price. Well, there is one serious problem here,
but it probably has no bearing on the immediate problem.&quot;</p>
<p>&quot;How is that, Holmes?&quot; As ever, my companion's insight
astonished me.</p>
<p>&quot;Well, if the second memory allocation fails, probably throwing
a <tt class="exceptionname">bad_alloc</tt> exception, then the
memory allocated for author is leaked. I notice exactly the same
problem in the converting constructor and copy constructor.&quot;</p>
<p>&quot;Good heavens, Holmes! Brilliant!&quot;</p>
<p>&quot;Elementary, my good friend. And yet, there is more. Do you
notice that the memory is allocated for an <span class=
"emphasis"><em>array</em></span> of characters, using the
<tt class="literal">new[]</tt> construct? Our friend has correctly
deduced that the memory allocated in the constructor needs to be
de-allocated in the destructor for the class, but has used only the
basic, single object version of <tt class="literal">delete</tt>.
For de-allocation to be performed successfully, the array version
of <tt class="literal">delete</tt> is required (for example,
<tt class="literal">delete[] b.title</tt>). This I perceive to be
at the heart of the problem. Still, there is yet a better solution
to this, which doesn't require <tt class="literal">delete</tt> at
all. Would you care to speculate on that, Watson?&quot;</p>
<p>&quot;Well, I think that we could replace the character arrays with
<tt class="classname">std::string</tt>, thereby instilling
intrinsic data type semantics to the data members, precluding the
need for a destructor altogether.&quot;</p>
<p>&quot;Excellent, Watson! I see you've been studying my methods more
closely than I give you credit for. As a matter of style, I would
put the initialisation of the data members in the initialisation
list of the class. In its current state, this cannot be done, since
initialising the members requires a function call. Replacing the
<tt class="type">char</tt> arrays with <tt class=
"classname">std::string</tt>, however, means that the copy
constructor, for example, can become:</p>
<pre class="programlisting">
Book::Book (const Book &amp; p)
  : author (p.author),  title (p.title), 
    price (p.price) { }
</pre>
<p>As I recall, only constructors are invoked for non-intrinsic
items in an initialisation list, and the compiler can often elide
the requirement for a function call in these cases. Thus, we have
introduced efficiency as well as style. You will notice that he has
used this method for invoking the base class constructor in the
converting constructor of <tt class="classname">ChildBook</tt>, but
still neglected to take advantage of it for <tt class=
"varname">reading_age</tt>.&quot;</p>
<p>&quot;I am still puzzled by your earlier reference to unsafe
inheritance, Holmes. I understood your reasoning completely about
<tt class="classname">BookList</tt> not deriving from <tt class=
"classname">Book</tt>, but the reasons for <tt class=
"classname">ChildBook</tt>'s derivation being unsafe eludes
me.&quot;</p>
<p>&quot;It is more than the inheritance which is unsafe, Watson. A
closer look at the code reveals some rather nasty surprises, which
lead me to conclude that my earlier assertion at a simple solution
was in grave error!&quot; He reached up to the mantelshelf for his
tobacco slipper, filled the largest of his pipes, and lay back,
eyes closed, in a brown study. Presently, his eyes snapped open,
and he looked straight at me, pronouncing &quot;You might care to get
some rest, old friend. This is fully a three pipe problem, but rest
assured I will wake you if there are any interesting
developments.&quot;</p>
<p>I arose at my usual late hour, to find Holmes at the table by
the window, with tea and toast laid out before him. &quot;I've opened
the window for your comfort, Watson. I must say it did get rather
stuffy in here during the night!&quot;</p>
<p>Indeed I could still detect the lingering odour of Holmes'
rather pungent tobacco, and was rather glad he had let some fresh
air into the room.</p>
<p>&quot;We have tea, juice and some toast is left. I'm sure Mrs Hudson
will oblige if you require anything further.&quot;</p>
<p>&quot;But what of the problem with which you spent the night? Have
you solved it?&quot;</p>
<p>&quot;Ah, yes. Well, calm yourself, dear Watson. You'll not be
needing your trusty service revolver for the conclusion to this
little mystery! I know I promised to wake you, but I'm afraid I
couldn't find the courage to do so.</p>
<p>&quot;So, the facts as we know them are these: we have a class
<tt class="classname">Book</tt>, which suffers from exception
unsafety in its memory allocation, and undefined behaviour in its
use of the incorrect version of <tt class="literal">delete</tt> in
its destructor. We have a class <tt class=
"classname">BookList</tt>, which inherits incorrectly from
<tt class="classname">Book</tt>, and a class <tt class=
"classname">ChildBook</tt> which inherits, apparently correctly,
from <tt class="classname">Book</tt>.</p>
<p>&quot;We have already theorised on a solution to both the exception
safety issue, and the incorrect use of delete, by replacing
character arrays with <tt class="classname">std::string</tt>.</p>
<p>&quot;In the course of the night, I discovered several more serious
issues with our code, which I will list now:</p>
<p>&quot;No. 1. Class <tt class="classname">Book</tt> is evidently used
as a base class (as indicated by its having virtual functions) yet
the destructor is not virtual. It was to this I alluded when I made
the comment about unsafe inheritance. Note here that a destructor
needs to be virtual only when a base class pointer will be used to
delete a derived class object. In this case, an example of this
might be:</p>
<pre class="programlisting">
Book * b = new ChildBook ();
delete b;
</pre>
<p>If the destructor for <tt class="classname">Book</tt> is not
virtual, then <tt class="varname">b</tt> will probably not be
destructed properly. In our case, I see it is not too serious, as
<tt class="classname">ChildBook</tt> has no defined destructor, and
only one data member which is of an intrinsic type.</p>
<p>&quot;No. 2. The arguments to the <tt class="function">details()</tt>
function and converting constructor for both <tt class=
"classname">Book</tt> and <tt class="classname">ChildBook</tt>
should be const. Under the circumstances, this could arguably be
described as a style issue, but it would prevent the following:</p>
<pre class="programlisting">
std::string name (&quot;...&quot;);
std::string title (&quot;...&quot;);
Book (name.c_str(), title.c_str(), 10);
</pre>
<p>This is because the <tt class="methodname">c_str()</tt> member
of <tt class="classname">std::string</tt> returns a <tt class=
"type">const char</tt> array, and a <tt class="literal">const</tt>
object cannot be converted to a non-<tt class="literal">const</tt>
one. You will notice that where references are used, our friend
correctly makes them <tt class="literal">const</tt>. So, at best he
is inconsistent in his use of <tt class="literal">const</tt>.</p>
<p>&quot;No. 3. This is the most serious error of logic in the code. In
the constructor and copy constructor for class <tt class=
"classname">Book</tt>, our friend is careful to allocate memory for
the data items in the book structure (I'll come to naming
conventions shortly), and perform a proper deep copy of the
pointers therein. However, he neglects to do this for the copy
constructor of class <tt class="classname">ChildBook</tt>. It is
important to remember that, for non-simple types such as classes or
structs, the default copy constructor, as provided by your compiler
if you do not, performs only a shallow copy; in the case of
pointers, only the addresses are copied, not the content of those
addresses. The copy constructor for <tt class=
"classname">ChildBook</tt> contains the following line:</p>
<pre class="programlisting">
b=k.b;
</pre>
<p>Where, in both cases, <tt class="varname">b</tt> is of type
<span class="structname">Book::book</span>, a <tt class=
"literal">struct</tt> containing two <tt class="type">char</tt>
pointers. Since <span class="structname">Book::book</span> does not
declare, in this case, an assignment operator, the default is used
which performs a shallow copy of the pointers.</p>
<p>Now consider this line of code:</p>
<pre class="programlisting">
bue.kiBook.push_back (ChildBook(&quot;Author&quot;,&quot;Title&quot;,35,5));
</pre>
<p><tt class="varname">kiBook</tt> is a <tt class=
"classname">std::list</tt> of <tt class=
"classname">ChildBook</tt>s. A temporary <tt class=
"classname">ChildBook</tt> object is created as a parameter to
<tt class="methodname">push_back()</tt>. In its constructor, memory
is allocated for copies of the text items, <tt class=
"literal">&quot;Author&quot;</tt> and <tt class="literal">&quot;Title&quot;</tt>. This
object is then copied to a new object in the list (remember that
list stores copies of objects, not references to them), but only a
shallow copy of the <span class="structname">ChildBook::book</span>
members (which it inherits from <tt class="classname">Book</tt>
because they are protected data - more on that in a moment). When
the temporary object goes out of scope, its destructor is invoked,
as experienced by our friend here. This has the effect of deleting
the memory for those data items. So now, the object stored in the
list points to deleted data. This, coupled with the fact that the
incorrect version of delete was used on those members anyway,
causes undefined behaviour in the program, and is the reason why
our friend is experiencing problems.&quot;</p>
<p>During this discourse we had retired to the sitting room, and
the comfort of the lounge chairs. As Mrs Hudson cleared away the
remains of our breakfast, my illustrious companion completed his
analysis of the C++ Code Problem.</p>
<p>&quot;So there you have it Watson. In resolving the problems, we can
return to our earlier hypothesis regarding exception safety in the
<tt class="classname">Book</tt> class. I recall it was you who
suggested using <tt class="classname">std::string</tt> to alleviate
exception safety issues. If we look at the issues we have since
uncovered, we discover that replacing our <tt class=
"type">char</tt> arrays with <tt class="classname">std::string</tt>
also removes the need for <tt class="literal">delete</tt>-ing the
memory in the destructor for class <tt class="classname">Book</tt>
(and, by the way, removing the use of the incorrect version of it),
and more importantly, though related, removes the need for deep
copying in the constructors of each class, most important of course
in the copy constructor of <tt class=
"classname">ChildBook</tt>.</p>
<p>&quot;It is this last point which will cause all of our friend's
problems to vanish!&quot;</p>
<p>&quot;That's wonderful, Holmes! My word, it seemed to me to be such
an impenetrable problem, and yet is solved in such a simple
fashion!&quot;</p>
<p>&quot;Quite so, Watson. It is often the case that when looking into
some difficulty, one overlooks the most obvious solutions. As you
know, my methods are a useful discipline against such errors, yet I
still make them from time to time.</p>
<p>&quot;Still, there are one or two points on which I would like to
alight if I may. Firstly, the issue of inheritance. The destructor
for class <tt class="classname">Book</tt> should be <tt class=
"literal">virtual</tt>, since it makes sense that <tt class=
"classname">ChildBook</tt> inherits from <tt class=
"classname">Book</tt>, it should do so safely. It seems to me that
having the data members for <tt class="classname">Book</tt> in
their own <tt class="literal">struct</tt> is pointless, and so see
no reason not to make them simple data members, and make them
<tt class="literal">private</tt>. In addition, of course, we make
the <tt class="type">char</tt> arrays into <tt class=
"classname">std::string</tt>s.</p>
<p>This brings up the issue of the <tt class="function">details
(...)</tt> function. This is not virtual, evidently because the
function signatures differ; were the <tt class=
"function">Book::details (...)</tt> function to be virtual, the
<tt class="function">ChildBook::details(...)</tt> function would
hide it, not override it anyway. However, it is enough that
<tt class="function">ChildBook::details (...)</tt> <span class=
"emphasis"><em>calls</em></span> <tt class="function">Book::details
(...)</tt> as the first call in its body:</p>
<pre class="programlisting">
ChildBook::details (const string &amp; t, 
                const string &amp; a, 
                float p, int r)
{
  details (t, a, p);
  reading_age = r;
}
</pre>
<p>&quot;So the declaration for <tt class="classname">ChildBook</tt>
should contain the line:</p>
<pre class="programlisting">
using Book::details;
</pre>
<p>&quot;and <tt class="function">Book::details (...)</tt> should
<span class="emphasis"><em>not</em></span> be <tt class=
"literal">virtual</tt>. Note that the line <tt class=
"literal">using Book::details</tt>; brings the name <tt class=
"function">details</tt> into the scope of <tt class=
"classname">ChildBook</tt>; it allows the function to be overloaded
in the usual sense. Base class public members are still accessible
in the usual way. Since the function signatures differ, we could
not use a pointer to <tt class="classname">Book</tt> to access
<tt class="function">ChildBook::details (...)</tt> anyway.</p>
<p>&quot;From this it is easy to see that the <tt class=
"literal">virtual</tt>-ness of <tt class=
"function">Book::details()</tt> (with no arguments) is still valid.
The name has been brought into the scope of <tt class=
"classname">ChildBook</tt>, so no hiding takes place where
arguments differ, thus allowing overloading in the usual sense.
However, <tt class="function">details()</tt> itself still has a
place in the virtual function table, and so <tt class=
"function">ChildBook::details()</tt> can be called via a <tt class=
"classname">Book</tt> pointer. So, <tt class=
"function">details()</tt> should be virtual in the base class, but
<tt class="function">details (...)</tt> should be virtual in
neither class, since <tt class="classname">ChildBook</tt> overloads
it. It seems obvious to me that <tt class="function">details()</tt>
is a function which restores the default values, but that is pure
conjecture on my part, as no function bodies are provided.</p>
<p>&quot;As already mentioned, <tt class="classname">BookList</tt>
should not inherit at all from <tt class="classname">Book</tt>. I
also do not see the need for specific data members of type
<tt class="classname">Book</tt> and <tt class=
"classname">ChildBook</tt>; since <tt class=
"classname">BookList</tt> is a collection of these, the list
containers are sufficient.</p>
<p>&quot;As data members, they should also be private, with suitable
accessor functions. Our friend has correctly separated the
container of <tt class="classname">Book</tt>s from the container of
<tt class="classname">ChildBook</tt>s. I mentioned before that a
<tt class="classname">ChildBook</tt> IS A <tt class=
"classname">Book</tt>, as indicated by the inheritance
relationship. It does not follow, however, that a collection of
<tt class="classname">Book</tt>s IS A collection of <tt class=
"classname">ChildBook</tt>s. A secondary issue here is that
concrete types (those which may instantiate objects) do not make
good base classes; a better solution may have been an interface
class, from which both <tt class="classname">Book</tt> and
<tt class="classname">ChildBook</tt> inherit.</p>
<p>&quot;Finally, a point upon which I stumbled at first, the use of the
identifier <tt class="classname">Book</tt> in the following
line:</p>
<pre class="programlisting">
list&lt;Book&gt; Book;
</pre>
<p>It is used as both a type and an object identifier. This seems
valid, but questionable. The compiler is under no constraints to
preserve object names, and so may be able to distinguish easily
between which is a type and which an object. Human readers on the
other hand may be less fortunate, and confusion can easily arise
from such naming conventions. Similarly, before our proposed
alterations to the <tt class="classname">Book</tt> class, it
contained a struct member, book. Since C++ is a case-sensitive
language, <span class="structname">Book::book</span> is a valid
type, although <tt class="methodname">Book::Book</tt> is not (it
denotes a constructor for <tt class="classname">Book</tt>). I do
not consider this a suitable name for this member, but the point is
moot, as we have already removed it.</p>
<p>&quot;And I believe that is all we can deduce from this code
fragment.&quot;</p>
<p>With that he lit his pipe and leaned back in his chair, puffing
smoke rings at the ceiling. Presently he looked up at me from his
reverie, intoning: &quot;It means 'display', Watson.&quot;</p>
<p>&quot;I beg your pardon, Holmes?&quot; I asked, incredulous.</p>
<p>&quot;Anzeigen, Watson. The German word over which you were
struggling,&quot; he replied, smiling happily.</p>
<p>&quot;By the deuce, Holmes! How did you know...&quot;</p>
<p>&quot;If I've told you once, Watson, I've told you a hundred times:
when you have eliminated the impossible, whatever remains, however
unlikely, must be the truth!&quot;</p>
<p>I must still have looked completely dumbfounded, as he then
added &quot;Besides, I could hear you whispering it to yourself.&quot;</p>
<p>Here is a plausible solution:</p>
<pre class="programlisting">
class Book {
public:
  Book();
  virtual ~Book();
  Book (const char *, const char *, float);
  Book (const Book &amp;);
  virtual void details();
  void details (const char *, const char *, float);
  Book&amp; operator=(const Book&amp;);
  bool operator== (const Book&amp;);
  virtual string Title()const{ return title; }
  virtual string Author()const{return author;}
  virtual float Price()const{ return price; }
private:
  string title;
  string author;
  float price;
};
class ChildBook : public Book {
public:
  ChildBook();
  ChildBook(const char*, const char*, 
                      float, int);
  ChildBook (const ChildBook&amp;);
  virtual ~ChildBook();
  using Book::details;
  void details (const char *, const char *,
                       float, int);
  virtual void details();
  virtual int ReadingAge() const 
                { return reading_age; }
  ChildBook&amp; operator= (const ChildBook &amp;);
  bool operator== (const ChildBook &amp;);
private:
  int reading_age;
};
// for the purposes of the task at hand,
// I've left the data members public
class BookList {
public:
  list&lt;Book&gt; book_library;
  list&lt;ChildBook&gt; childbook_library;
};

Book::Book() : 
author(&quot;Author&quot;),title(&quot;Title&quot;),price(0.0f){}

Book::Book(const char*t,const char*a,float p)
: author(a),title(t),price(p) { }

Book::Book(const Book&amp; p) : author(p.author),
       title(p.title), price(p.price) { }
Book::~Book() { }

void Book::details (const char*t, const char*a,float p) {
  author = a;
  title = t;
  price = p;
}

void Book::details() {
  author = &quot;Author&quot;;
  title = &quot;Title&quot;;
  price = 0.0f;
}

ChildBook::ChildBook() : reading_age(3) { }
ChildBook::~ChildBook() { }

ChildBook::ChildBook(const char* t, 
      const char* a, float p, int la) 
: Book (t, a, p) { reading_age = la; }

void ChildBook::details(const char* t, 
      const char* a, float p, int la) {
  details (t, a, p);
  reading_age = la;
}

// pure speculation here
void ChildBook::details () {
  Book::details();
  reading_age = 0;
}
ChildBook::ChildBook (const ChildBook &amp; k)
  : Book (k), reading_age (k.reading_age) { }

#pragma argsused
int main(int argc, char* argv[]) {
  BookList bue;
  bue.book_library.push_back 
              (Book(&quot;Book&quot;,&quot;Title&quot;,20));
  bue.childbook_library.push_back
       (ChildBook(&quot;Author&quot;,&quot;Title&quot;,35, 5));
  for(list&lt;Book&gt;::const_iterator 
        i=bue.book_library.begin(); 
      i!=bue.book_library.end();++i) {
    cout   &lt;&lt; i-&gt;Title() &lt;&lt; i-&gt;Author() 
        &lt;&lt; i-&gt;Price() &lt;&lt; endl;
  }
  for(list&lt;ChildBook&gt;::const_iterator
        i=bue.childbook_library.begin();
      i!=bue.childbook_library.end();++i){
    cout &lt;&lt; i-&gt;Title() &lt;&lt; i-&gt;Author()
        &lt;&lt; i-&gt;Price() &lt;&lt; i-&gt;ReadingAge() 
        &lt;&lt; endl;
  }
  cin.get();
  return 0;
}
</pre></div>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e1005" id="d0e1005"></a>Critique by
Nathan Briggs <tt class="email">&lt;<a href=
"mailto:nathan@ukgateway.net">nathan@ukgateway.net</a>&gt;</tt></h3>
</div>
<p>I cannot find the problem the student specifies, my step through
shows construction/destruction in the right order, as far as I know
(Is this not the compilers job to decide when to dump things?).
However I do see major problems with this code, speaking as a self
taught student who will be studying for a degree in Computer
Systems Engineering by the time this is published I can hardly be
considered to have great knowledge of idiom, however I do recognise
poor practise. The choice of the student (I presume the design is
the student's - if it is the lecturers, I am horrified) to
encapsulate the <tt class="classname">Book</tt> class's private
data in a struct seems very strange - what possible bonus could
this be?</p>
<p>The derived class <tt class="classname">ChildBook</tt> is a
logical extension, but why is <tt class="varname">reading_age</tt>
a public member? Surely, an access function would be much more
secure. I will assume access functions for other members were cut
for space reasons, if they were not available the classes public
interface is severely lacking, you cannot assume output will only
be required in one form and that the data will never change.</p>
<p>Something the student has not addressed is the variable names
chosen (or not), in the header file a comment has to be used to
explain the parameters passed to the constructor where none is
necessary, the identifiers could always be changed to <tt class=
"varname">your_title</tt> to avoid ambiguity in the definition of
the function, alternatively this could be utilised.</p>
<p>The 'library' class is, in my opinion, ridiculous. I do not know
much about patterns or how a class hierarchy should be stored in an
encapsulating class but I do not believe <tt class=
"classname">BookList</tt> should be derived from <tt class=
"classname">Book</tt>, it makes for confusing reading. If it is a
requirment to be able to pass a <tt class="classname">Book</tt> or
a <tt class="classname">BookList</tt> equally easily then another
class, say <tt class="classname">BookBase</tt> should be defined as
a common base.</p>
<p>I believe I have addressed most of these concerns in my own
version, which uses four classes: <tt class=
"classname">BookBase</tt>, <tt class="classname">Book</tt>,
<tt class="classname">ChildBook</tt> and <tt class=
"classname">BookList</tt>. <tt class="classname">BookBase</tt>
serves as a featureless base class, but has the advantage you can
store a <tt class="classname">BookList</tt> in a <tt class=
"classname">BookList</tt> in a <tt class=
"classname">BookList</tt>... ad infinitum should you want to do
that. My own classes have member functions for both reading and
writing the class state as well as overridden operators for
assignment, equality checks and output to a stream. I think my code
is of a reasonable quality; however two things I feel are
lacking</p>
<div class="orderedlist">
<ol type="1">
<li>
<p>string to hold the text - my compiler does not support this type
so I do not know how to use it.</p>
</li>
<li>
<p>error checking - there is no framework for error throwing so I
chose not to provide for it.</p>
</li>
</ol>
</div>
<p>Any comments on my solution will be greatly appreciated.
[<i><span class="remark">see below for Nathan's
code</span></i>]</p>
<p class="c2"><span class="remark">Editorial Comment</span></p>
<p class="c2"><span class="remark">Compilers actually have very
little choice over where a destructor is to be called. I might have
written none, but there is a tiny amount of room for variance in
that a compiler can sometimes optimize away a construction and
obviate the need for calling a destructor.</span></p>
<p class="c2"><span class="remark">If you are using a compiler that
does not know about <tt class="classname">string</tt>, then you
have a very poor library. String has been a standard library
provided type for almost as long as C++ has existed. There have
been considerable changes to the way it is provided, but that is a
different issue entirely.</span></p>
<p class="c2"><span class="remark">I think your idea of having
<tt class="classname">BookBase</tt> so that types of books and
collections of books can be treated together is interesting.
Perhaps some expert on design would write an article on this,
highlighting both the strengths and weaknesses of such an
idea.</span></p>
<p class="c2"><span class="remark">Finally, best wishes on the
degree course.</span></p>
</div>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e1104" id="d0e1104"></a>The Prize
Winner</h2>
</div>
<p class="c2"><span class="remark">I hope that you will all agree
that Steve's parody deserves recognition. I have no hesitation in
declaring him the winner. Colin's excellent critique would
certainly greatly benefit the student, and I hope that Nathan has
got much from a noble effort, and that he will get much more from
the critique you are about to write on his code.</span></p>
<p class="c2"><span class="remark">If Steve would give me a call I
can discuss his prize with him.</span></p>
<p class="c2"><span class="remark">I hope that we will be seeing
more creative writing. Bridge players may know what I mean when I
say that we need something akin to the writings of David Bird.
Humour, a story, memorable characters can all contribute to
technical instruction.</span></p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e1116" id="d0e1116"></a>Competition
No 6</h2>
</div>
<p>I <i><span class="remark">would not normally invite you critique
code written by a named person. However, Nathan has asked for your
comments, and is a student. I think his code makes a good starting
point for a critique. It has a number of interesting points to it
as well as a flawed design. Please look carefully at this code,
there are numerous points that need highlighting and correcting. At
least part of his problems is that he is using an old, pre-standard
C++ compiler.</span></i></p>
<p class="c2"><span class="remark">As always there will be a prize
provided by Blackwell's Bookshops in collaboration with
Addison-Wesley. If other booksellers and/or publishers would like
to sponsor one of our columns, I would be very happy to discuss it
with them.</span></p>
<p>Entries by October 21st.</p>
<pre class="programlisting">
// &copy; Nathan Briggs 2000 &lt;nathan@ukgateway.net&gt;
// this header dedicated to Paul Heaton of The Beautiful South - &quot;Let love speak up itself&quot;
#ifndef BOOK_H
#define BOOK_H
class ostream; // save including the whole of &lt;iostream&gt; here
class BookBase { };
class Book : public BookBase {
  public:
    Book(char* your_title, char* your_author, double your_price=0.00f);
    Book(void) : my_title('\0'), my_author('\0'), my_price(0) { }
    ~Book(void);
    Book(const Book&amp; your_book);
// operators
    Book&amp; operator=(const Book&amp; your_book) { deleteStuff(); copyStuff(your_book); }
    bool operator==(const Book&amp; your_book);
    friend ostream&amp; operator&lt;&lt;(ostream&amp;, Book&amp;);
// access fn's
    const char const* title(void) { return (const char const*)my_title; }
    const char const* author(void) { return (const char const*)my_author; }
    const double price(void) { return (const double)my_price; }
// modification fn's
    void title(char* new_title);  void author(char* new_author);  void price(double new_price);
  protected:
// data manip fn's
    virtual void deleteStuff(void);
    virtual void copyStuff(Book&amp; your_book);
// data
    char* my_title; char* my_author; double my_price;
};
class ChildBook : public Book {
   public:
// constructors
    ChildBook(char* your_title=&quot;\0&quot;, char* your_author=&quot;\0&quot;, double your_price=0.00f, 
          double your_reading_age=3.0) : Book(your_title, your_author, your_price) {
      my_reading_age = your_reading_age;
    }
    ChildBook(void);
    ChildBook(const ChildBook&amp; your_book);
// operators
    bool operator==(const ChildBook&amp; your_book){
      return(!strcmp(my_title,your_book.my_title) and !strcmp(my_author,your_book.my_author) 
        and (my_price == your_book.my_price) and my_reading_age==your_book.my_reading_age);
    }
    ChildBook&amp; operator=(const ChildBook&amp; your_book){ deleteStuff(); copyStuff(your_book); }
    friend ostream&amp; operator&lt;&lt;(ostream&amp;, ChildBook&amp;);
// access fn's
    const double reading_age(void) { return my_reading_age; }
// modification fn's
    void reading_age(double new_reading_age);
  protected:
// data manip fn's
    virtual void deleteStuff(void);
    virtual void copyStuff(ChildBook&amp; your_book);
// data
    double my_reading_age;
};
class BookList : public BookBase {
  public:
    list&lt;BookBase&gt; books; 
// I have left this public because the overhead in giving access function for list&lt;&gt; 
// is too great and offers little real benefit
    friend ostream&amp; operator&lt;&lt;(ostream&amp;, BookList&amp;);
};
#endif
// Implementation file
// &copy; Nathan Briggs 2000 nathan@ukgateway.net, 
#include &quot;mybook.h&quot;
#include &lt;iostream.h&gt;
#include &lt;string.h&gt; // for C-style string ops
// Note - I use C-style strings here because my compiler doesn't support &lt;string&gt;, 
// the template code is too complicated or something. I'll get an upgrade soon - I promise 
Book::Book(char const * your_title, char const * your_author, double your_price) {
  my_title = new char[strlen(your_title)+1];
    if(my_title) strcpy(my_title, your_title);
  my_author = new char[strlen(your_author)+1];
    if(my_author) strcpy(my_author, your_author);
  my_price = your_price;
}
Book::~Book(void) { deleteStuff(); }
Book::Book(const Book&amp; your_book) { copyStuff(your_book); }
void Book::deleteStuff(void) {  delete[] my_title; delete[] my_author; }
void Book::copyStuff(Book&amp; your_book) {
  my_title = new char[strlen(your_book.my_title)+1];  
  if(my_title) strcpy(my_title, your_book.my_title);
  my_author = new char[strlen(your_book.my_author)+1];
  if(my_author) strcpy(my_author, your_book.my_author);
  my_price = your_book.my_price;
}
bool Book::operator==(const Book&amp; your_book){
  return(!strcmp(my_title,your_book.my_title) and !strcmp(my_author,your_book.my_author) 
          and (my_price == your_book.my_price) );
}
void Book::title(char* new_title) {
  delete[] my_title;  my_title = new char[strlen(new_title)+1];
  strcpy(my_title,new_title);
}
void Book::author(char* new_author) {
  delete[] my_author; my_author = new char[strlen(new_author)+1];
  strcpy(my_author,new_author);
}
void Book::price(double new_price) { my_price = new_price; }
ostream&amp; operator&lt;&lt;(ostream&amp; o, Book&amp; b) {
  o &lt;&lt; b.title() &lt;&lt; &quot;, &quot; &lt;&lt; b.author() &lt;&lt; &quot;, &pound;&quot; &lt;&lt; b.price() &lt;&lt; endl; 
  return o;
}
ChildBook::~ChildBook(void) { deleteStuff(); }
ChildBook::ChildBook(const ChildBook&amp; your_book) { copyStuff(your_book); }
void ChildBook::reading_age(double new_reading_age){ my_reading_age=new_reading_age;}
void ChildBook::deleteStuff(void) { delete[] my_title;  delete[] my_author; }
void ChildBook::copyStuff(ChildBook&amp; your_book){
  my_title = new char[strlen(your_book.my_title)+1];
  if(my_title) strcpy(my_title, your_book.my_title);
  my_author = new char[strlen(your_book.my_author)+1];
  if(my_author) strcpy(my_author, your_book.my_author);
  my_price = your_book.my_price;
  my_reading_age = your_book.my_reading_age;
}
ostream&amp; operator&lt;&lt;(ostream&amp; o, ChildBook&amp; b) {
  o   &lt;&lt; b.title() &lt;&lt; &quot;, &quot; &lt;&lt; b.author() &lt;&lt; &quot;, &pound;&quot; &lt;&lt; b.price() &lt;&lt; &quot; for people aged &quot;
    &lt;&lt; b.reading_age() &lt;&lt; &quot; years.&quot; &lt;&lt; endl;
  return o;
}
ostream&amp; operator&lt;&lt;(ostream&amp; o, BookList&amp; b){
// print details of each book in list&lt;BookBase&gt; books using for_each type thingy 
// (I know it exists but don't know how to use it!)
}
</pre></div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
