From: kanze@us-es.sel.de (James Kanze)
Newsgroups: alt.amateur-comp,comp.lang.c,comp.lang.c++,comp.misc
Subject: Re: What is Object Oriented Programming? Is C doomed?
Date: 18 Dec 92 04:09:28 GMT
	<1992Dec15.172057.6793@borland.com> <1992Dec16.145444.2130@nastar.uucp>
Organization: SEL

In article <1992Dec16.145444.2130@nastar.uucp> phardie@nastar.uucp
(Pete Hardie) writes:

|> In article <1992Dec15.172057.6793@borland.com> pete@borland.com (Pete Becker) writes:
|> >	That's certainly true, but I don't think it's a good thing.  It seems
|> >to me that the important factor in using a container is understanding its
|> >behavior.  A Queue and a Stack differ significantly, in that a Queue is
|> >FIFO and a Stack is LIFO. You pick which one to use based on what your
|> >current program requires.  Replacing a Queue with a Stack will change the
|> >behavior of the program.  So I don't want them to have the same interface.

|> By coincidence, I am working on a list-management module, that includes
|> Lists, Queues, Stacks, and several other types.

|> I am using a linked-list as the base structure, with auxiliary pointers to
|> allow circular access, size limits, etc.  To make the list a Stack, I
|> simply do this:

|> #define Push(list,element) AddElementToEnd(list,element)
|> #define Pop(list) RemoveElementFromEnd(list)

|> where AddElement... and RemoveElement... are generic linked-list functions.

|> For a Queue, I do this:

|> #define Enqueue(list,element) AddElementToEnd(list,element)
|> #define Dequeue(list) RemoveElementFromFront(list)

Don't do this.

I think the basic idea of using the same underlying mechanism for
Stacks and Queues, for example, is good.  This is code re-use.  But
you should either derive from this underlying mechanism, or create a
class which contains it.

This will prevent you from accidently pushing something into a Queue,
or enqueuing something on a stack.

And if you later find out that this generalized implementation has too
much overhead, you can rewrite the class with a more specialized
algorithm, without any of the user code having to change.

|> Thus, they have the 'same' interface, in the generic functions, using the same
|> data structure(s), and if I decide that the program need a queue instead of
|> a stack, all I need to do is change the Push() calls to Enqueue() calls, and
|> so on.

I don't think that this is a realistic example.  If you have to change
from a stack to a queue, it means that something was wrong in the
initial analysis, and I'd be very surprised that this was the only
thing that had to be changed.

|> If I need a fixed-size container, mimicking an array, I have functions to
|> treat a linked-list as a fixed length container, with all the same data
|> structures, and minimal changes need to be made to the surrounding code
|> to dal with the possible error conditions that a fixed size container will
|> cause over a dynamic one.

Again, if this is done by derivation, fine.  Although I think
implementing a general array class is probably simple enough to go for
right off.  (The difference in access times for random access into a
large array will very quickly become noticeable.)
--
James Kanze                             email: kanze@us-es.sel.de
GABI Software, Sarl., 8 rue du Faisan, F-67000 Strasbourg, France
Conseils en informatique industrielle --
                   -- Beratung in industrieller Datenverarbeitung
Newsgroups: alt.amateur-comp,comp.lang.c,comp.lang.c++,comp.misc