[comp.lang.c++] information hiding

mgardi@watdcsu.waterloo.edu (M.Gardi - ICR) (06/20/89)

I am a little curious as to how one can completely remove implementation
details of a C++ class from the user of the class.
I would like to design a system that users need only know the public
declarations and nothing else to use the class.
It seems to me that I will always have to provide a Header file that 
contains at least the declarations of all my private information.
Ultimately, I would like to give them a library containing my classes and
NOTHING else.
Could someone please clue me in!
p.

jima@hplsla.HP.COM (Jim Adcock) (06/23/89)

> Ultimately, I would like to give them a library containing my classes and
> NOTHING else.

Why?  Seems like letting people see a little bit of your class might be a 
good thing.  I find it very comforting to be able to look at complex.h for
example.  Reading it, I get the impression that the person writing it might
very well know what they're doing.  Yet not enough is given away that I 
could /cause/get into/ any trouble.

In any case, I hope you meant to say that you would like to at least give
them a manual page explaining how to use your class along with the library.
Software without good documentation isn't reusable.

diamond@diamond.csl.sony.junet (Norman Diamond) (06/26/89)

Some poster (attribution previously deleted) writes:

>> Ultimately, I would like to give them a library containing my classes and
>> NOTHING else.

In article <6590164@hplsla.HP.COM> jima@hplsla.HP.COM (Jim Adcock) writes:

>I find it very comforting to be able to look at complex.h for
>example.  Reading it, I get the impression that the person writing it might
>very well know what they're doing.

Have you looked at your C compiler?  I still use C compilers and they
usually work.  But after seeing two of them, I get the impression that
the people writing them did not know what they were doing.  In some
cases, they did not even know the C language.  If a program works, has
been reviewed/benchmarked/whatever, maybe you're better off accepting
it without looking at its source code.

--
Norman Diamond, Sony Computer Science Lab (diamond%csl.sony.jp@relay.cs.net)
 The above opinions are claimed by your machine's init process (pid 1), after
 being disowned and orphaned.  However, if you see this at Waterloo, Stanford,
 or Anterior, then their administrators must have approved of these opinions.

nevin1@cbnewsc.ATT.COM (nevin.j.liber) (06/26/89)

In article <6590164@hplsla.HP.COM> jima@hplsla.HP.COM (Jim Adcock) writes:
|Someone else wrote:
|> Ultimately, I would like to give them a library containing my classes and
|> NOTHING else.

|Why?  Seems like letting people see a little bit of your class might be a 
|good thing.  I find it very comforting to be able to look at complex.h for
|example.  Reading it, I get the impression that the person writing it might
|very well know what they're doing.  Yet not enough is given away that I 
|could /cause/get into/ any trouble.

Maybe, maybe not.  Programmers are clever people :-); they tend to use
ALL the information they are given.  From the header file one might
guess on how the class is implemented, find some undocumented side
effects, and write code that uses these side effects.  This breaks the
clean interface which classes provide, and leads to many of the
"existing practice" problems which can be found throughout pANS C.  I'd
much rather have all the implementation details for a class hidden from
me.
-- 
NEVIN ":-)" LIBER  AT&T Bell Laboratories  nevin1@ihlpb.ATT.COM  (312) 979-4751

solomon@gjetost.cs.wisc.edu (Marvin Solomon) (06/27/89)

There's been some discussion about why the .h file describing a class
needs to include information about the private part of the class, and
whether that's a good thing.  I remember when I first read about Ada,
I found it strange that a package *specification* contained information
about the hidden parts of the package.  On reflection, I figured out
the justification.  It's simple once you see it, but perhaps not obvious,
especially to those who are not compiler experts.

The trouble is that a class definition serves two purposes:  to document
the class interface to a human user and to provide a compiler with enough
information to compile a client of the class.  The private members are
superfluous (indeed, it could be argued they are harmful) for the former
purpose, but essential for the latter.  Consider:

someclass.h:
	class SomeClass {
	public:
		int visible;
	private:
		char hidden[10];
	};
client.c:
	#include "someclass.h"

	Someclass arr[15];

	...
	arr[1].visible = 17; // movl #17,arr+16, assuming fullword alignment

To compile client.c, the compiler needs to know the size of a SomeClass.
I can think of no straightforward implementation-independent way of
conveying this information other than to include the "private" section
in someclass.h.  The C++ language goes to some pains to ensure that the
client programmer can't "use" the extra info.  For example
	cout << arr[1].hidden;
is an error.  But a sufficiently "clever" hacker might *abuse* the information:
	printf("%s",&(arr[1].visible)+1);
Such programmers get what they deserve.
--
	Marvin Solomon
	Computer Sciences Department
	University of Wisconsin, Madison WI
	solomon@cs.wisc.edu, ...seismo!uwvax!solomon

richard@pantor.UUCP (Richard Sargent) (06/29/89)

Regarding the question of C++ header files containing the public and private
information both, the information *has* to be there for the compiler.

However, you can alleviate the problems caused by extracting only the public
portions and publishing those as adjunct to man pages or whatever. This can
be fairly automated via judicious use of "#if !defined(EXTRACT)" directives
throughout and use 'make' and the preprocessor to fairly automatically 
extract the public portions. Of course, you can write your own utilities to 
do whatever you want ...

Naturally, this does not solve the 'problem' of someone attempting to learn
more about a class than they should, but I doubt anything will, short of a
completely closed and regulated programming/development environment (and you
thought editor wars were extreme!). It will, however, allow people to easily
learn what they do need to know without 'burdening' them with the stuff they
shouldn't know.

As with everything involving C/C++, it all comes down to discipline in the 
end.


Richard Sargent                   Internet: richard@pantor.UUCP
Systems Analyst                   UUCP:     uunet!pantor!richard

db@lfcs.ed.ac.uk (Dave Berry) (06/30/89)

In article <7709@spool.cs.wisc.edu> solomon@gjetost.cs.wisc.edu (Marvin Solomon) writes:
> [An explanation of why class definitions must include private members,
>  so that the compiler knows the size of the class.]

This doesn't explain why private function members must be included.
It's a real pain to have to recompile a large part of a program just
because you've added a private function to do some internal processing.

Of course you could write the function at the top level and make it take
the relevant object as an argument, but this defeats some of the purpose
of using classes.

I'd like to be able to define private member functions outside the
class, e.g.

private Result* Foo::foo (Bar*, Stool*);

Then only the changed .c file would need to be recompiled.


Other approaches to this would be to use a separate header file to store
the private member functions, and to write your makefile so that only the
relevant .c file was recompiled when the private .h file was changed.
Unfortunately this wouldn't work with  makedepend, which I use a lot.

There are several ways that a C++ environment could handle this neatly,
providing the facilities of both make and makedepend, but allowing
private functions to be defined outside the class would be more portable.

Dave Berry, Laboratory for Foundations      db%lfcs.ed.ac.uk@nsfnet-relay.ac.uk
    of Computer Science, Edinburgh Uni.	    <Atlantic Ocean>!mcvax!ukc!lfcs!db

          "It's not a good omen when goldfish commit suicide."

pcg@aber-cs.UUCP (Piercarlo Grandi) (06/30/89)

In article <2465@etive.ed.ac.uk> db@lfcs.ed.ac.uk (Dave Berry) writes:
    In article <7709@spool.cs.wisc.edu> solomon@gjetost.cs.wisc.edu (Marvin Solomon) writes:
    > [An explanation of why class definitions must include private members,
    >  so that the compiler knows the size of the class.]
    
    This doesn't explain why private function members must be included.
    It's a real pain to have to recompile a large part of a program just
    because you've added a private function to do some internal processing.

	[ ... ]
    
    Other approaches to this would be to use a separate header file to store
    the private member functions, and to write your makefile so that only the
    relevant .c file was recompiled when the private .h file was changed.

Let me insist that an import/export facility with compiled headers would
be the ideal solution... And it is fairly easy to implement. And one could
still use #include for backwards compatibility. And ...

(whining again on this subject :->)
-- 
Piercarlo "Peter" Grandi           | ARPA: pcg%cs.aber.ac.uk@nsfnet-relay.ac.uk
Dept of CS, UCW Aberystwyth        | UUCP: ...!mcvax!ukc!aber-cs!pcg
Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk

strange@cbnewsl.ATT.COM (philip.e.brown) (06/30/89)

There is still some discussion about this, so I'll
pass along the mail I sent to the original poster.
(Subsequent articles have covered some of this already.)

///////////////////////////////////////////////////////

In article <6031@watdcsu.waterloo.edu> you write:
>
>I am a little curious as to how one can completely remove implementation
>details of a C++ class from the user of the class.
>I would like to design a system that users need only know the public
>declarations and nothing else to use the class.
>It seems to me that I will always have to provide a Header file that
>contains at least the declarations of all my private information.
>Ultimately, I would like to give them a library containing my classes and
>NOTHING else.
>Could someone please clue me in!

As with everything else, there is a cost for complete
information hiding.  The cost here is the added level of
indirection necessary to defer implementation details.

My suggestion is to try something like:

//////////////
// header file

class hide1;	// classes for hidden implementation
...
class hideN;

class interface {
	hide1 *hidden1;		// handle into implementation
	...
	hideN *hiddenN;
public:
	interface_func1();	// can't define yet
	...
	interface_funcM();
};

// end header file
//////////////////

//////////////
// source file

class hide1 { /* implementation details */ };
...
class hideN { /* implementation details */ };

interface::interface_func1() { /* implementation details */ }
...
interface::interface_funcM() { /* implementation details */ }

// end source file
//////////////////


The header file contains only the information
necessary for the interface.  All else is hidden.

An additional benefit is that recompilation is
only necessary when the interface has changed.
When just the implementation has been updated,
only the files containing the implementation are
affected.


Phil Brown
AT&T Bell Labs
attunix!strange

grunwald@flute.cs.uiuc.edu (Dirk Grunwald) (08/08/89)

there is no reason why information hiding should require more indirection;
it only requires a good compiler.

however, C++ was designed in the good-ol' UNIX programing environment
where there's no intermediate files other than .o files and all
compilers read source files. That's why inlines have to be visible.
--
Dirk Grunwald -- Univ. of Illinois 		  (grunwald@flute.cs.uiuc.edu)