[comp.lang.c++] Object-oriented techniques in C

friedl@vsi.UUCP (Stephen J. Friedl) (05/22/88)

Hi.ho net.folks,

     I have never used C++ or any other object-oriented language,
but have read enough about them to know they are a direction I
wish to go.  Our understanding of these techniques do not
necessarily require an OO language; we are doing some of them in
C.  Are there any references to object-oriented techniques in C?

     Related to this, what is the best way to use C++ on the 3B
family of machines?  Any native code compilers?  Translators?

     Thanks,
     Steve

-- 
Steve Friedl    V-Systems, Inc. (714) 545-6442    3B2-kind-of-guy
friedl@vsi.com    {backbones}!vsi.com!friedl   attmail!vsi!friedl

djones@megatest.UUCP (Dave Jones) (05/24/88)

in article <684@vsi.UUCP>, friedl@vsi.UUCP (Stephen J. Friedl) says:
> 
> Hi.ho net.folks,
> 
>      I have never used C++ or any other object-oriented language,
> but have read enough about them to know they are a direction I
> wish to go.  Our understanding of these techniques do not
> necessarily require an OO language; we are doing some of them in
> C.  Are there any references to object-oriented techniques in C?
> 
>      Related to this, what is the best way to use C++ on the 3B
> family of machines?  Any native code compilers?  Translators?
> 
>      Thanks,
>      Steve
> 
> -- 
> Steve Friedl    V-Systems, Inc. (714) 545-6442    3B2-kind-of-guy
> friedl@vsi.com    {backbones}!vsi.com!friedl   attmail!vsi!friedl


C++ is a big win.  Especially if your C compiler, like the one I use,
does not have function prototypes.

The biggest wins that C++ give you are

  1.  convenience.. It's much easier, and less error-prone to let
      cfront write all that code, rather than writing it "by hand";

  2.  inspiration.. You're more likely to write good (object-oriented)
      code if the language inspires you to do so.

Still, almost anything you can do in C++, you can do in C.  (Proof: cfront
generates C-code.)  It's true that there is no automatic procedural 
initialization of static variables in C.  But that doesn't work too well in 
the current implementation of C++ either.  And macros aren't as good as 
inline procedures.  Etc., etc...  But for the most part, if cfront can 
write it, you can write it.

Here is a document which I, aided and abetted by my cohorts, have prepared 
for a project which is just getting started.  I had already evolved
approximately this style over the years, before I had ever heard the
expression "object-oriented".  When C++ came out, I shamelessly stole
some ideas and modified the style somewhat to be more analagous to C++. 
(Thanks, Bjourne.)




C CODING CONVENTIONS:

Many functions update only one kind of object.  Other functions
serve only to inspect one kind of object and return appropriate results.
Such functions -- those closely related to one kind of object -- are called 
"methods" of that type of object.  A familiar example is the
stdio package in the C library.  Those functions all deal with
a data structure called a "FILE".  

As far as is practical, we will access the contents of an object only by
means of the object's methods.  The large majority of our functions will 
be methods of some type of object.

There are two typical kinds of .h files.  One defines a type of
object, by giving structure-declarations for the object, and
extern-declarations for the methods of that type of
object.  The other defines a procedure-table ("vtable") which
abstracts the procedures for a class of types of objects which
have similarly parameterized methods.

Notice that an object is defined as a structure, not as a pointer to a 
structure.

Include-files protect themselves against multiple inclusion, 
with an #ifndef, and should include all (protected) include-files which 
their declarations require.

All methods should have extern declarations in the .h file.
Instance variables should be marked "read-only" or "private" when
appropriate, to warn users against setting or inspecting them.

Declarations which are only to be used for private instance-variables
should be marked "private".

#ifndef C_FOO_H
#define C_FOO_H

#include "Gar.h"
	
	/* private */
	typedef struct
	{
	  char* bar;
	}Bar;

	/* public */
	typedef struct
	{ 
	  /* public */
	    int fleeble;

	  /* read-only */
	    int var;

	  /* private */
	    Bar fly;
	    Gar gar;

	} Foo;

	extern Foo* Foo_init();
	extern void Foo_put();

#endif C_FOO_H


Method names are conventionally prefixed by the name of the class,
as in Foo_next() and Foo_put(), etc..  The prefix should be spelled 
exactly the same and have the same case as the type-name (capitalized).  
This will prove useful in doing global searches and replaces, in
writing macros, etc..

All methods of Foo have as a first parameter a variable of type Foo*,
conventionally called 'obj'.  The preceding applies to initializers, 
which conventionally are named Foo_init(), and to cleanup-routines, 
conventionally named Foo_clean().  Initializers and cleaners return a 
pointer to the object they operated on (obj).  Cleanup routines are 
intended to deallocate memory referenced by the object, but not 
referenced by any other object.

To allocate an object from heap, use the NEW() macro from generic.h
as follows:

   Foo* obj = Foo_init(NEW(Foo), arg1, arg2, argn);

#define NEW(type) ((type*)smalloc(sizeof(type)))

smalloc is a "safe" malloc, which calls an exception-handler when
it cannot allocate memory. The handler can be dynamically re-bound
to other procedures, but the default one writes an error message
to file-descriptor 2, and terminates the program.  If you set the 
handler to NULL, smalloc will behave like malloc().  See smalloc.h.

To dispose of an object obtained by smalloc, you can do this:

  sfree((Ptr)Foo_clean(obj));


A class named Foo_iter is an iterator-class for class Foo.

Aside from the name "obj", "init", and other standard abbreviations which
we may agree upon and register, all variable-names will be spelled out
completely, with underscores separating words.  Macros will be all 
caps.  Exception: Methods which, for speed, are coded as macros will
be spelled as though they were proper functions.  Variable names and
general functions will be lower case.  Method names will be capitalized, 
as are object-type names.


Some objects need to contain pointers to functions.  For example,
the hash-table package, "Assoc", uses functions "hash", "equiv", etc.,
which vary depending upon the type of object being stored in the
hash-tables.  We will package related functions together into
structures called "vtable"'s.  That stands for "virtual function
table".  "Virtual" seems like a misnomer to me, but that's the
keyword that C++ uses, so I figure that it will come to have
some recognition value.

For example, class Assoc uses a vtable, which is defined in keys.h as
follows:


#ifndef _KEYS_H_
#define _KEYS_H_

#include "generic.h"

/* These are the operations which one needs to do on objects in
** order to use them as "keys" in lookup tables, etc.
*/
typedef struct
{
  /* Assert: for all (obj1,obj2), 
  **
  **  !equiv(obj1,obj2) ||  (hash(obj1) == hash(obj2))
  **
  **  and for all obj,
  **
  **  equiv( obj, copy(obj))
  */

  int   (*hash)(/*Ref*/);      

  Ptr   (*copy)(/*Ref*/);  /* Given a Ptr to one, returns a Ptr.
		            * For some classes, copy() will simply return
			    * the Ptr which is given to it, and
			    * then delete() will do nothing.
			    * For other classes it will be a "deep copy"
			    */

  void  (*delete)(/*Ptr*/);       /* Deletes a key built by copy() */

  Bool  (*equiv)(/*Ptr, Ptr*/);   /* Tells is two are equivalent */


}Key_functions;

#endif  _KEYS_H_

winnie@pyr1.cs.ucl.ac.uk (05/24/88)

> Our understanding of these techniques do not
> necessarily require an OO language; we are doing some of them in
> C.  Are there any references to object-oriented techniques in C?

I always believe in `right tools for right tasks'. I don't think one
can ever attain the essence of object-oriented paradigm without
using a proper object-oriented programming language.

Winnie

mikem@otc.oz (Mike Mowbray) (05/26/88)

In article <552@goofy.megatest.UUCP>, djones@megatest.UUCP (Dave Jones) says:

> Still, almost anything you can do in C++, you can do in C.  (Proof: cfront
> generates C-code.)

Yes.

I think I will probably strangle the next person around here who tells me
that they can do what C++ does in C, (or some other language of similar
level). I could do what C++ does even in assembler; [Proof: C++ gets turned
into C which gets turned into assembly code]. Extrapolating that argument one
step further implies that we make do with binary machine code(!)

"There is none so blind as he who ...."

			Mike Mowbray
		    Systems Development
			|||| OTC ||

PHONE	(02) 287-4104			  ACSnet:  mikem@otc.oz
FAX	(02) 287-4990			    UUCP:  {uunet,mcvax}!otc.oz!mikem 
SNAIL	OTC, GPO Box 7000		   CSNET:  mikem@otc.oz.au
	Sydney 2001, Australia		    ARPA:  mikem@otc.oz.au

djones@megatest.UUCP (Dave Jones) (05/28/88)

From article <384@otc.oz>, by mikem@otc.oz (Mike Mowbray):
> In article <552@goofy.megatest.UUCP>, djones@megatest.UUCP (Dave Jones) says:
> 
>> Still, almost anything you can do in C++, you can do in C.  (Proof: cfront
>> generates C-code.)
> 
> Yes.
> 
> I think I will probably strangle the next person around here who tells me
> that they can do what C++ does in C, (or some other language of similar
> level). I could do what C++ does even in assembler; [Proof: C++ gets turned
> into C which gets turned into assembly code]. Extrapolating that argument one
> step further implies that we make do with binary machine code(!)
> 
> "There is none so blind as he who ...."
> 

I think I will probably decapitate and eviscerate the next person who
says he will strangle me.  :-)  Now that the pleasantries are disposed of,
let's see here about this "blindness" premise:

I don't think your assembly language *reductio ad absurbum* holds water.
With C, it is usually possible to write machine-independant code.  Not
so with assembler.  C does semantic translation from the C-virtual machine 
to the machine for which it is compiling (perhaps real, perhaps virtual).

C++, though very useful, has the same underlying virtual machine as C --
intentionally so.  The value of C++ is that it automates name-space 
reorganization from an o-o hierachy of classes to the flat name-space of C.

This you can do "by hand", although at the expense of some tedium and an 
increased likelyhood of mistakes. But having done so, you will have a 
machine-independant computer program.

As I noted in the original letter, C++ does more than just reorganize the 
names.  Inline procedure expantion is an example I gave where C++ does
semantic translation, rather than just reorganiztion.  But you can
fake that somewhat with macros.  They're not as good, but you can
survive.  There are other examples.  Still I stand by what I say.

Purhaps I should have said, "C++ is a very useful tool.  But there is
more to be gained from organizing libraries and programs around data-objects
than there is to be gained from selecting a programming language which
is desinged for that purpose.  It is extremely desirable, however, to
select a language which is supported on a large variety of architectures."




			Your truly,

			J. Ripper, ret.

djones@megatest.UUCP (Dave Jones) (05/28/88)

From article <36300005@pyr1.cs.ucl.ac.uk>, by winnie@pyr1.cs.ucl.ac.uk:
> 
> 
>> Our understanding of these techniques do not
>> necessarily require an OO language; we are doing some of them in
>> C.  Are there any references to object-oriented techniques in C?
> 
> I always believe in `right tools for right tasks'. 

No argument there.  But C++ may not be the right tool because of some
non-language reason.  Maybe it's not supported on the Banana-7000.

> I don't think one
> can ever attain the essence of object-oriented paradigm without
> using a proper object-oriented programming language.
> 


I don't know about attaining essences.  

But I think you can write some darn good stuff in C, "if you've a mind to."



			-- Dave J.

flaps@dgp.toronto.edu (Alan J Rosenthal) (06/02/88)

In article <576@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes:
>I don't think your assembly language *reductio ad absurbum* holds water.
>With C, it is usually possible to write machine-independant code.  Not
>so with assembler.

This is a red herring.  If there was only one kind of machine and
operating system ever invented by the human race, so that the whole
concept of portability had never been thought of, it would still be the
case that few people would prefer assembly language to high level
languages.

The original argument stands.  Saying that you can do whatever you can
in C++ in C is no more disparaging of C++ than saying that you can do
whatever you can in C in assembler is of C.

ajr

--
- Any questions?
- Well, I thought I had some questions, but they turned out to be a trigraph.