    <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  :: Uses of Classes with only Private and Protected Constructors</title>
        <link>https://members.accu.org/index.php/articles/1390</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 #3 - Aug 1993</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/c225/">03</a>
<br />

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

                    -                        <a href="https://members.accu.org/index.php/articles/c65+225/">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;Uses of Classes with only Private and Protected Constructors</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 01 August 1993 11:51:00 +01:00 or Sun, 01 August 1993 11:51:00 +01:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;<p><b>A derivation of a paper originally presented to the European C++
Conference July 8th-9th 1993 at the Hilton Hotel, Munich.</b></p>
<p>The main aim of this paper is to present some ideas of ways in which
the use of the access control keywords applied to constructors (and
destructors) can be used to add constraints to the creation of objects.
The use of the 'friend' keyword is a valuable asset in a number of
idioms.</p>
<p>I make no claims that any of the following is original but in many
cases case I worked out the methods for myself and for most others I am
indebted to comments and contributions made be other delegates to the
Munich Conference. Some I have since come across in the writings of
others. Finally I am indebted to Robert Murray (a regular contributor
to C++ Report) for the idea of inhibiting the use of a class as a base
class.</p>
<p>I also make no claims that the methods I describe are either better
than more commonly known techniques or are always sound examples of
good programming. However good programming is made better when the
programmer is aware of the wide range of techniques available and can
exercise good judgement to select the most appropriate for a specific
problem.</p>
<p>Extensions to the language are another factor that should be taken
into account . Some proposed extensions add significantly to the
language, others merely make already available techniques more readable
and accessible to the average programmer. The former need to be
examined with great care because C++ is already a large language based
on sometimes tenuous historical foundations. The later, I believe,
should be encouraged as they make the already achievable, easier.</p>
<p>Many inexperienced programmers view the keywords 'private' and
'protected' in C++ as access constraints on the member functions and
data of an object belonging to a class. However C++, via one of the
applications of 'static', supports functions and data that are members
of the class rather than any individual object. Access control is also
useful in that context.</p>
<p>Constructors (and, to a lesser extent, destructors) though not
declared static are much more class functions than object functions.
There primary job is to manage the creation (and destruction) of
objects.</p>
<p>The access keywords are applicable to class members as well as to
object members. As such 'private' (and its companion, 'protected') can
be used to apply constraints on the use of class members. The
constraints that are applied to constructors can be classified as
follows:</p>
<p>1) Limit availability of class object to a particular scope, either
the class scope or another function or class scope granted access via
'friend'.</p>
<p>2) Prevent the declaration of global or auto variables of the class.</p>
<p>3) Inhibit copy construction of class objects.</p>
<p>4) Inhibit the creation of any objects of the class</p>
<p>5) Inhibit the use of the class as a base class</p>
<p>To some extent the familiarity of a programmer with each of these
constraints on constructors is a measure of their familiarity with the
potential of C++.</p>
<p>The novice finds any private constructor an eccentricity and is
initially mystified by it. In fact many seem to assume that 'private'
will not have an effect on a constructor. Their compiler quickly
corrects this mis-understanding.</p>
<p>Fairly early in the process of learning C++ a programmer will come
across the third item above. Good texts and well thought out training
courses include an item on inhibiting copy construction when the
default copy constructor will not do what is wanted and the programmer
is not yet ready to provide one themselves.</p>
<p>Actually this constraint on a copy constructor is pretty severe and
greatly limits the ways in which objects of the class can be used. It
would be a rare program that could manage with a private copy
constructor for a class with objects that include data items rather
than only member functions. The latter type of class probably shouldn't
be instantiated: how would you distinguish one instantiation from
another?</p>
<p>Though this inhibition of copy construction is probably the earliest
example of a private constructor that a programmer will meet, it is
also probably the least useful when used in isolation. There would seem
to be little more to be said about this type of private constructor.</p>
<p>I have not come across any useful instances of a fully defined
private copy constructor in classes with one or more public
constructors. If you come across any such instances I would be
delighted to add them to my menagerie of weird classes.</p>
<h2>Local and Nested classes</h2>
<p>Some authors make a great play of C++'s support of local and nested
classes. This is really odd because such facilities have existed almost
since the start of C++. Indeed, as we shall see, the current
specification of these in C++ actually applies constraints that the
following method does not.</p>
<p>If you want to restrict a class by constraining access to it to a
second class (nested class) or to a specific function (local class)
most of the appropriate functionality can be provided by the following
framework:</p>
<pre class="programlisting">class T {<br>friend @@@@@ /* replace @@@@@ with the required class or function name */<br>T(...){ // constructor definition<br>}<br><br>T(const T &amp; t); // private copy constructor declared<br>// the rest of the class declaration <br>}</pre>
<p>Note that this class cannot be used as a base class. ON the other
hand if you change the access to the constructor to protected you have
fatally damaged the constraint.</p>
<p>It is only fair to ask what extra facilities are provided by true
local and nested classes. Basically two extras are provided by these.
First is the avoidance of namespace pollution. Second you regain the
ability to use 'private' to constrain access to class T members from
the enclosing scope. The first of these is quite important in large
projects where the single global namespace is all too easily polluted.
This will become less important when 'namespace' is introduced into C++.</p>
<p>I am not convinced that the second item (constraining access) offers
any great advantage in the context of a local or nested class. On the
other hand the above technique allows a single specialist class to be a
'local' or 'nested' member of several functions and/or classes.</p>
<p>As there are some other constraints applied to local classes as
currently provided in the standards Working Paper. These include
prohibiting static members from local classes and requiring the entire
definition to be within the class declaration. In the case of nested
classes there are restrictions on the type names available. In view of
these constraints on the normal forms of local and nested classes the
above method of providing restricted access to a class may remain as a
viable technique even when all compilers support the normal forms.</p>
<p>One objection I have heard raised by traditionalists to both this
instance and a number of the following is that it produces a tight
binding between two separate program objects. I think that this is
symptomatic of an entirely false view of C++ and Abstract Data Types
and objects.</p>
<p>Abstract Data Types are not effectively encapsulated in a single
class. Generally an ADT is best represented by a tightly bound cluster
of classes and global functions. These form a de facto module which
could be encapsulated in a pair of source code files; a header file
providing the public interface and a file of code that implements the
interface. I would suggest that even here we may have to conceptually
separate parts of the interface information that enables the system to
link to the implementation from those parts that are intended for use
by the rest of the program world.</p>
<p>In general it is not sensible to implement an ADT without the use of
at least some friend functions. Those familiar with methods for
managing libraries designed to support more than one platform or
machine architecture will know that two or more closely coupled classes
are often the most effective way of providing a consistent interface
with alternative (system dependant) implementations.</p>
<p>Those with even more experience may be familiar with techniques for
supporting multiple interfaces to a single complex but well defined
data structure.</p>
<p>The above few paragraphs have little to do with the direct subject
of this paper (and have only been inserted in this derived version) but
experience shows that it is an area where many programmers need to
change their interface to C++.</p>
<h2>Nested Functions</h2>
<p>I hear programmers refer to nested function extensions provided by
some compilers (I believe GNU G++ is one such) with either awe or
horror. Many seem to think that such an extension is dangerous and
should not be encouraged. I find this attitude strange because all the
functionality of nested functions has been implicit in C++ since
'friend' was implemented.</p>
<p>Consider:</p>
<pre class="programlisting">class T {<br>  friend X();<br>  T();<br>  T(const T &amp; t);<br>  static void fn(){cout&lt;&lt;&quot;nested function&quot;&lt;&lt;endl;}<br>};</pre>
<p>This effectively provides T::fn() nested inside X(). Its nice to
have nested functions provided explicitly but this should demonstrate
that making it explicit is all that need be happening. As we can nest
functions when we want to, perhaps those involved with developing the
standard should add a suitable standard syntax for nested functions
immediately and thereby limit namespace pollution.</p>
<p>Note that one of the major purposes of nesting functions is to
increase the binding between two functions while ensuring that the
inner function cannot be used externally. One problem is that of
considering overload resolution. The method I have outlined ensures
that such an issue does not arise as the encapsulating class name will
specifically identify the scope where the function is located. I leave
it to the reader to explore the consequences of calling a member
function that does not exist. If you do not know the answer without
investigation then you still have much work to do if you expect your
programs to work the way you intend.</p>
<h2>Shared Data</h2>
<p>The first programming language I learnt was FORTRAN. It provided a
facility by which data could be declared COMMON to a number of modules
of a program. In those days it was an important facility for allowing
clear communication between overlays. Overlays were far more important
in the early days where memory was measured in kilobytes and having
more than 16K was a luxury. None-the-less the idea of providing a
common data block shared between specified parts of a program that had
little other communication still has its uses.</p>
<p>The following idiom may be useful in such circumstances.</p>
<p>In the ancestral language, C, identifiers were either local to a
block, local to a file or global. The arguments about global data will
continue to rage but most programmers want easy methods for restricted
sharing of data between functions. The classic student avoidance of
globals (put all your global variables in a struct in main and pass a
pointer to it to all your functions) entirely misses the real danger
lurking in global variables.</p>
<p>C++ provides a number of other ways of restricting access to data.
One that deserves to be better known is exemplified by:</p>
<pre class="programlisting">class T {<br>  friend ... // list all functions sharing data<br>  T();<br>  T(const T &amp;);&nbsp; // prevent use of inheritance and composition<br>  static ...&nbsp;&nbsp;&nbsp; // list of variables common to the functions <br>}</pre>
<p>This method has several advantages. For me, the friend list is one
of them. It provides specific and necessary documentation of all the
functions (and, possibly, classes) that have direct access to this data.</p>
<p>Another way of achieving this is to leave out the friend statements
and put the function prototypes in the class as static member
functions. The disadvantage of this is that all uses of such functions
have to be scoped to the class. The method above only requires the data
to be scoped within the friend functions and is transparent to the rest
of your code.</p>
<h2>Preventing global and auto objects</h2>
<p>Programmers who have only worked with single tasking operating
systems often look mystified when I talk about the need to prevent
construction of global or auto objects. Those with more experience and
those who have considered the problems of writing for products such as
MS Windows or X are aware of the problem but do not always know that a
solution exists.</p>
<p>I first became conscious of the problem when my phone rang one day
and I was asked &quot;Is 'delete this' legal.&quot; I had never considered the
problem before. On checking I found that libraries accompanying both
Borland C++ and Microsoft Visual C++ contained 'delete this'.</p>
<p>Clearly the statement is syntactically well formed so the question
came down to whether there was any reason to specifically ban that
construct. Put it another way, could a ban be enforced and if it was,
would that make a legitimate piece of source code illegal? The answers
are 'no' and 'yes'.</p>
<p>'delete this' is sometimes referred to as the 'suicide statement' (I
recently had a programmer talk about a Caligula function, one that
destroyed its siblings, parents and children. That is another issue and
I wonder if there is any legitimate use for such a function.) because
the object instigates its own destruction. 'delete this' is a statement
that should be used with great care because it has the potential for
seriously damaging your product. Auto and global objects cannot commit
suicide successfully because their 'ghosts' will hang around to haunt
you.</p>
<p>Consider:</p>
<pre class="programlisting">class T {<br>  char * c; public:<br>  T(char* x) : c(new char[strlen(x)+1]) {strcpy(c,x);}<br>  ~T(){delete[]&nbsp; c;}<br>  void suicide() {delete this}<br>};<br><br>int main()<br>{<br>  T ex(&quot;disaster&quot;); <br>  ex.suicide(); <br>  return 0;<br>}</pre>
<p>Now the destructor for 'ex' is called twice, once via suicide() and
once when 'ex' goes out of scope. You will probably get away with it in
such a simple case but you certainly will not in most situations where
the statement is used to handle a real problem.</p>
<p>This failure to properly destroy the object with 'delete this' is a
fundamental problem. It is impossible to stop the call of a destructor
for a variable that is going out of scope.</p>
<p>What we can do is to prevent auto, static local or global objects
capable of suicide from ever coming into existence.</p>
<p>The way to achieve this is to make all constructors for the class
private. You must be careful to remember that there are two
constructors provided by the compiler. Both must be constrained by
making them private or protected. The choice between these two is
governed by whether you want your class to be available as a base class
or not. Make the constructors private and your class cannot be a base
class because the derived class will not be able to construct the base
object (unless you grant the derived class friend status but see later
on for a development of this idea).</p>
<p>If you choose to make one of these classes available as a base class
it is essential that the suicide position is fully documented. If you
do not, a client's derived class may destroy your protective mechanisms
with the resulting risk of an auto, static local or global object
suiciding. This is because any public constructors for derived classes
will have access to the protected constructors of the base class. Auto,
static local and global objects of the derived type can then be
constructed. Any call to the suicide function then has all the
potential for a real disaster. The 'delete this' in the original
suicide function will refer to the base class object, not the derived
object.</p>
<p>Leaving these problems aside, there are several mechanisms for using
private constructors to create objects. The fundamental principle is to
use a pointer to handle an object that is created with new. Do not be
tempted to even consider references in this context, to do so will
almost certainly undo all that you had achieved.</p>
<p>The naive programmer does something like this:</p>
<pre class="programlisting">class T {<br>  friend T* make_T();<br>  int i[20];<br>  T(){};<br>  T(const T &amp; t) // inhibit copying<br>  ~T(){}; <br>public: <br>  // public interface<br>} <br><br>T * make_T() { return new T();}</pre>
<p>The problem with this is that we are (unnecessarily) trusting the
programmer to capture the returned pointer. We should ensure that there
is a pointer by passing it as a parameter so make_T() should be:</p>
<pre class="programlisting">boolean make_T(T * t){ <br>  t=new T;<br>  if (t) return TRUE; <br>  else return FALSE;<br>}</pre>
<p>The reason that the destructor has been made private (protected) is
that in the context of suicide classes it is almost always essential
that the object IS destroyed by suicide and not by some other mechanism.</p>
<p>To make this clear consider the common use of suicide classes to
handle window objects in an event driven environment such as MS Windows.</p>
<p>The problem is that there are two objects involved, the program
object created as a member of an appropriate class and the Windows
object. When the time comes to destroy a window both objects must be
destroyed by the same event.</p>
<p>If you first destroy the program object there is nothing left to
send a message to Windows. On the other hand if you first send a
message to Windows there is the danger that the programmer forgets to
destroy the program object.</p>
<p>The safe way to do this is to cause the same function to send a
message to Windows and suicide. The Windows experts can probably
elaborate with more sophisticated mechanisms via callback functions.</p>
<h2>Mustn't be a Base</h2>
<p>I am not at all certain that this mechanism has any real life
practical uses and I am indebted to Rob Murray for drawing my attention
to the idea. I would welcome examples of its practical use.</p>
<p>You design a class 'end_of_branch' that must not ever become a base
class. How do you ensure that no programmer manages to use it as a
base? The method is as follows (I have slightly amended Rob's solution
so that it will actually work despite the potential for using
pathological behaviour of copy constructors to self copy an object):</p>
<pre class="programlisting">class inhibit <br>{<br>  friend class end_of_branch; <br>// and any other similar classes that you wish to inhibit<br>  inhibit(){};<br>  inhibit( const inhibit &amp; i){}; <br>}; <br><br>class end_of_branch : virtual inhibit <br>{<br>  // the code for your class <br>}</pre>
<p>Now if you try to use end_of_branch as a base class for a derived
class D, for example:</p>
<pre class="programlisting">class D : end_of_branch<br>{<br>};</pre>
<p>Then the compiler will reject it because the rules for construction
require the constructors for virtual bases to be called directly and
not via the inheritance hierarchy. Actually it is not quite true as the
following shows:</p>
<pre class="programlisting">class DD : end_of_branch <br>{<br>  end_of_branch();<br>  end_of_branch(const end_of_branch &amp; e); <br>  // remaining code<br>};</pre>
<p>By declaring the constructors but not defining them you prevent the
compiler from detecting the problem and as long as you never call
either constructor there will not be a link time error. The result is
that you can have a derived class but you cannot have derived objects.
A number of items in this paper show that such a class can have its
uses.</p>
<p>In his original presentation, Rob forgot the copy constructor with
the result that a derived class could be sneaked past the compiler by
declaring an ordinary constructor but not defining it and then using
the copy constructor to construct objects.</p>
<p>This is all great fun and works on paper but before you actually
inhibit a class by this mechanism go away and do some research on the
cost of having a virtual base class. The most obvious candidates for
the method are what Bjarne Stroustrup calls concrete data types (things
like complex, string etc.) which the programmer wants to make as like a
built-in as possible. With the current methods of supporting virtual
base classes there is no way that a sane programmer would want to use
this method to protect a concrete data type.</p>
<p>And the final problem is that there is nothing you can do against
the determined programmer who insists on wanting to grab your class as
a base class. Consider the following:</p>
<pre class="programlisting">class wrapper <br>{<br>public: <br>  end_of_branch e;<br>};</pre>
<p>This&nbsp; new class&nbsp; has almost&nbsp; exactly the
functionality of end_of_branch without the inhibition. Using classes
derived from wrapper will be a little more awkward and some of the
overloading and hiding rules will be changed but that is about all.</p>
<p>If grey haired writers can come up with schemes like this what will
the young whiz-kids produce? If you work for a company that does not
use code inspections then I suggest that either they change their
policy or you find another employer. The job of trying to maintain code
that is the result of the creative programming from an under-supervised
programmer is a nightmare.</p>
<h2>Providing restricted mutual friendship</h2>
<p>This is not my idea but one that was passed on to me at Munich. The
problem is basically to provide mutual access between a pair of
functions in two different classes so that each function has access to
the other one but no more. All you can do by straightforward methods is
to allow each function access to the whole of the other class. This is
fine normally but if you want to ensure that the compiler will resist
any access other than that specifically required how can you do it?</p>
<p>Try this:</p>
<pre class="programlisting">class X <br>{<br>  friend LINK::xfn();<br>  fn();<br>  // rest of code <br>};<br><br>class Y <br>{<br>  friend LINK::yfn();<br>  fn(); <br>  // rest of code<br>};</pre>
<pre class="programlisting">class LINK <br>{<br>  static xfn(){X::fn();}<br>  static yfn(){Y::fn();} <br>  friend X::fn(); <br>  friend Y::fn(); <br>};</pre>
<p>Remember that friendship is not transitive so each of the two
original functions can only get at the wrapped version of the other in
LINK. Of course if you are being that careful to allow the compiler to
detect problems you do not want any LINK objects instantiated so you
better inhibit construction as well.</p>
<h2>class-as-object</h2>
<p>Writing a class with both default constructors declared as private
and not defined would seem to be about as useless a piece of source as
you could imagine. But we have already seen several uses of such
classes. In those, however, the constraint was desirable, not
necessary. In this final example it is essential that the class cannot
be instantiated.</p>
<p>Oddly, among all the types of class with private constructors this
is the first type that I actually had a use for.</p>
<p>One of the principles of object-oriented programming is to create
program objects to represent real world objects. The question arises as
how to represent an essentially unique object?</p>
<p>I first came across this when I was sitting in on a test run of a
course for C programmers converting to C++. One of the course exercises
was to develop a Screen class. The specification was that the
constructor should switch the VDU to graphics mode.</p>
<p>The destructor would revert the screen back to text mode.</p>
<p>The purpose of the exercise was to demonstrate that a class object
did not need data members. A secondary purpose was that students would
have to anticipate problems created by the instantiation of a second
object before the destruction of the first. The course designer
suggested that this should be done via a static data member that the
constructor could inspect. If an object already existed the constructor
would abort the program. Even with exception handling this approach
seems flawed.</p>
<p>What is needed is an object to keep track of the current display
mode. Even better it should maintain a record of prior states on a
stack (or other appropriate data structure). The constructor/destructor
approach does not meet the needs of the problem.</p>
<p>One solution would be to create a screen object at the start of the
program and destruct it at the end. I am unhappy with this approach
because, in the context, there is only one screen and it should not be
possible to create more than one program object to interact with a
unique real world object. I am also profoundly unhappy with simply
generating an abort if an attempt is made to instantiate a second
object. The constructor method does not leave much space for a graceful
exit.</p>
<p>In the context of a course this kind of exercise is useful because
it brings programmers face to face with some of the problems associated
with constructors. At the time I felt that a better solution to
representing unique objects must exist. I must admit that it was
several months before I recognised a potential solution; treat the
class-as-object.</p>
<p>Consider: <br>
</p>
<pre class="programlisting">class Screen <br>{<br>  static stack_of_int s;<br>  Screen();<br>  Screen(const Screen &amp; ss);<br>public:<br>  // static functions to handle desired functionality<br>}</pre>
<p>As the constructor is private (and undefined) it is impossible to
construct a Screen object. Therefore it may seem unnecessary to include
a copy constructor but this is not the case. Bizarrely, C++ allows you
to construct an object with a copy of itself. For example:</p>
<pre class="programlisting">Screen s(s);</pre>
<p>Would create a Screen object, s, unless the copy constructor has
been inhibited as well as the ordinary default constructor.
Alternatively you can declare a private destructor as all the compilers
I have tried recognise this and prevent any objects being constructed.
This would be sufficient to prevent compilation but it is a quality of
implementation issue for the compiler to recognise the problem at
construction time. Anyway take your choice but watch out for that
unexpected use of a copy constructor.</p>
<p>The key idea that has to be coupled with private constructors when
implementing a class-as-object is the use of static to make all members
class-members rather than object-members.</p>
<p>We can now add whatever other facilities and functionality that we
want for our Screen object in the secure knowledge that there is a
single program class-as-object connected to our single real world
screen.</p>
<p>This idea is fine as far as it goes but how do we handle objects
that are not unique but must be uniquely addressed. A good example in
the PC world is that of managing interfacing to serial ports. A design
that allowed two objects to try to use a serial port simultaneously is
almost certainly faulty. But to try to use object-oriented methods and
not provide an object to manage a serial port seems perverse.</p>
<p>There are certainly a number of alternative approaches including
having a unique monolithic serial port class. Another approach is to
have the serial port class maintain a static list of ports that are
currently assigned.</p>
<p>The problem with the latter approach is that it suffers from similar
problems to the putative Screen class, what does the constructor do
when it finds that the required port is already in use?</p>
<p>I think this is the wrong direction. Though there are often several
serial ports each one should be uniquely addressable and therefore have
a single program object associated with it. Once I phrased the problem
in these terms and started thinking of implementing an individual
class-as-object for each port an answer surfaced, templates. Consider: <br>
</p>
<pre class="programlisting">template &lt;int port&gt; class SerialPort<br>{<br>  SerialPort();<br>  // static member data to handle a port <br>public:<br>  // static member functions to handle a port <br>}</pre>
<p>Now it is impossible to have more than one handler per serial port
(well as long as you don't provide a handler via an alternative
method). There are no constructors to fail but we do still have some
things to consider.</p>
<p>We cannot pass a class-as-object to a function. We cannot have
arrays of them and all such items must be specifically identified at
compile time. For example if we want a program to initialise all
existing serial ports and create a list of those available we cannot
write code such as: <br>
</p>
<pre class="programlisting">for (int i=1;i&lt;5;i++) SerialPort&lt;i&gt;::init();</pre>
<p>Instead I must unroll such a loop. As there will only be a limited
number of serial ports I can live with that solution.</p>
<p>In fact every time we need to make run-time decisions about which
serial port to use we will have to provide switch statements or
something similar. In this case the problems caused by using a
class-as-object may be acceptable but it would be nice to have some
other method.</p>
<p>If you elect to implement serial port handling this way it is
probably a good idea to include all the functionality in a single
normal but data free class (with object instatiation inhibited) and use
the template class as a wrapper so that code duplication is minimised.</p>
<p>I think that the use of a class-as-object idiom is only appropriate
to handling real-world objects that you expect to be globally available
to your program. In such circumstances we can live with the handicaps
introduced because we cannot use pointers, references, nor directly
select an object at run&shy;time.</p>
<h2>Conclusion</h2>
<p>I hope you have enjoyed this ramble through some of the odd uses of
classes with only private copy constructors. Please do not stop here,
instead get out your favourite compiler and text editor and explore a
bit further. When you have done so report back via these pages. The
principle object of papers such as this one is to set programmers
thinking and to dig out some of the more obscure idioms that some are
already using.</p>
<p>I hope that your editor will be swamped with responses and will find
space to publish them. I give him my full consent to include the
vitriol from those that consider such procedures as the above have no
place in a well ordered programming environment.</p>
<p>Finally, as the Harpist would assure you, there are bound to be
errors in the above to catch the too casual reader.</p>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
