Topic: why are private functions part of a class' interface?


Author: schuenem@Informatik.TU-Muenchen.DE (Ulf Schuenemann)
Date: 1995/04/18
Raw View
In article <3mjfjr$c98@etca.etca.fr>, chris@alofi.etca.fr (Christian Millour) writes:
[..]
|> Provided that you don't need your private helper functions
|> in friend classes, you might consider implementing them as
|> (static) members of an opaque friend, e.g.:
|>
|> Foo.h: --------------------
|>
|> class Foo {
|> public:
|>   Foo();
|>   double avg() const;
|> private:
|>   double a, b, c;
|> friend struct FooHelpers;
|> };
|>

BTW, can a namespace (that is not a class) be the friend of a class?

|> Foo.cc: -------------------
|>
|> #include "Foo.h"
|> struct FooHelpers {
|>   static void primify(Foo& aFoo) {aFoo.a = 2; aFoo.b = 3; aFoo.c = 5;}
|>   static double sum(const Foo& aFoo) {return aFoo.a + aFoo.b + aFoo.c; }
|> };

To let FooHelpers provide _private_ helper functions it should be:

struct FooHelpers {
  friend class Foo;
private:
  static void primify(Foo& aFoo) {aFoo.a = 2; aFoo.b = 3; aFoo.c = 5;}
  static double sum(const Foo& aFoo) {return aFoo.a + aFoo.b + aFoo.c; }
};

A IMHO more straight foreward way would be:

namespace Foo {
 void primify(Foo& aFoo) {aFoo.a = 2; aFoo.b = 3; aFoo.c = 5;}
};
Foo::Foo() {
 primify(*this);
};

Giving the currently prohibited members-added-to-a-namespace-that-is-a-class
a usefull meaning.


Ulf Schuenemann

--------------------------------------------------------------------
Ulf Sch   nemann
Fakult   t f   r Informatik, Technische Universit   t M   nchen, Germany.
email: schuenem@informatik.tu-muenchen.de





Author: chu@prosun.first.gmd.de (Vladimir Chukharev)
Date: 1995/04/18
Raw View
In article <CROIZIER.95Apr13154319@gauss.enstb.enst-bretagne.fr>, croizier@enstb.enst-bretagne.fr (Valery CROIZIER) writes:
|> In article <3mj5b1$nr5@locutus.rchland.ibm.com>
|> pstaite@powertool.rchland.ibm.com (Philip Staite) writes:
|>
|> > |> Whenever I add a private helper function to a class, I have to change its
|> > |> interface in the .h file and thus recompile all dependent classes (unless I
|>
|> > |>   I think it would be useful to permit member function definitions without
|> > |> requiring a declaration.
|>
|> > Also, if I can define a "member" function without the class
|> > declaring it as a member/friend, this blows encapsulation.  What stops
|> > me from doing anything I want to the private/protected instance data?
|>
|>
|> It could be possible to declare private methods without adding them to
|> the .h file, since you can do it with Ada.
|> But with C++, the encapsulation is performed *only* by the class
|> descrition, which is usually in the .h file.
|> As a result, there is no way you can safely define such a function
|> outside the .h file and avoid recompiling everything.
|>
|> --
|> Valery

There is a way in C++ to avoid recompiling everything. It's called
pure abstract class. Use in .h file pure abstract class
(no data, all functions public pure virtual). In implementation .c file
you derive a real class. Of course, you need now to use only
pointers or refferences to your pure abstract class, but no recompilation
is needed if you change implementation and don't change interface.

D&EoC++ discusses this.

---
Vladimir Chukharev
chu@first.gmd.de





Author: adok@algonet.se (Anders Adok)
Date: 1995/04/14
Raw View
vladimir@tees.cs.ualberta.ca (Vladimir Alexiev) wrote:

>Whenever I add a private helper function to a class, I have to change its
>interface in the .h file and thus recompile all dependent classes (unless I
>use touch to bump back the timestamp).
>  I think it would be useful to permit member function definitions without
>requiring a declaration.


The problem is virtual methods. Compiler figures out how the virtual
table looks like from declaration only. If you insert private virtual
method between two public the pointers are moved. One could put all
private stuff after public but then you have to create virtual tables
in your full source code.

I hate it to and think it   s not object oriented at all. Under
development to skip recompiling you could use feature in C++ that you
can have forward class declaration and do so.

in header
class TestPrivate;

class Test {
  Test();
  ~Test();
   void sumeMethod();
   TestPrivate *testPrivate();
};

in code
class  TestPrivate {
   void sumeMethod();
};
void Test::sumeMethod() { testPrivate->someMethod(); }

In this case you have nice code but little overhead.
I hate also that private methods are global WHY ???
I use local classes in C++ code everyware, even class decl. is in C++
but there  is now way to skip overhead.


Hope it helps

Anders







Author: cgenly@teleport.com
Date: 1995/04/14
Raw View
> It could be possible to declare private methods without adding them to
> the .h file, since you can do it with Ada.
> But with C++, the encapsulation is performed *only* by the class
> descrition, which is usually in the .h file.
> As a result, there is no way you can safely define such a function
> outside the .h file and avoid recompiling everything.

I was concerned with this problem too.  Bjarne Stroustrup replied with the
technique of using an abstract class to be included by clients of the
class.  This abstract class would not declare private members.  A derived
class of the abstract class would be used in the implmentaion, and would
declare the private members.  This isolates clients from implementation
issues.  I find this a bit of awkward, but workable.










Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/04/16
Raw View
Ian T Zimmerman <itz@rahul.net> writes:

>Vladimir Alexiev <vladimir@tees.cs.ualberta.ca> wrote:
>>Whenever I add a private helper function to a class, I have to change its
>>interface in the .h file and thus recompile all dependent classes (unless I
>>use touch to bump back the timestamp).
>
>But that is a fault of a stupid compiler / nonexistent dependency
>analyzer, not of C++ language definition.

The state of the art seems to be stupid compilers / nonexistent dependency
analyzers.  But there are other languages where you can add the equivalent
of private helper functions without recompiling all dependent classes, even
though the compiler / dependency analyzer is very dumb!

Hence, I think you have to conclude that problem is at least in part
the fault of the C++ language definition.

--
Fergus Henderson            | As practiced by computer science, the study of
fjh@cs.mu.oz.au             | programming is an unholy mixture of mathematics,
http://www.cs.mu.oz.au/~fjh | literary criticism, and folklore. - B. A. Sheil





Author: jones@cais2.cais.com (Ben Jones)
Date: 1995/04/13
Raw View
Vladimir Alexiev (vladimir@tees.cs.ualberta.ca) wrote:
: Whenever I add a private helper function to a class, I have to change its
: interface in the .h file and thus recompile all dependent classes (unless I
: use touch to bump back the timestamp).
:   I think it would be useful to permit member function definitions without
: requiring a declaration.

For a solution to this and many other annoying features in C++, please take
a look at ARC++ at the anonymous ftp:

    arsoftware.arclch.com: /pub/arc++

Ben Jones






Author: pstaite@powertool.rchland.ibm.com (Philip Staite)
Date: 1995/04/13
Raw View
In article <VLADIMIR.95Apr12160158@tees.cs.ualberta.ca>, vladimir@tees.cs.ualberta.ca (Vladimir Alexiev) writes:
|> Whenever I add a private helper function to a class, I have to change its
|> interface in the .h file and thus recompile all dependent classes (unless I
|> use touch to bump back the timestamp).
|>   I think it would be useful to permit member function definitions without
|> requiring a declaration.

Well, definition without declaration takes us back to the pre-prototype days of C...  Kinda blows argument type checking and type safety...

Also, if I can define a "member" function without the class declaring it as a member/friend, this blows encapsulation.  What stops me from doing anything I want to the private/protected instance data?

--
Phil Staite
pstaite@vnet.ibm.com





Author: croizier@enstb.enst-bretagne.fr (Valery CROIZIER)
Date: 1995/04/13
Raw View
In article <3mj5b1$nr5@locutus.rchland.ibm.com>
pstaite@powertool.rchland.ibm.com (Philip Staite) writes:

> |> Whenever I add a private helper function to a class, I have to change its
> |> interface in the .h file and thus recompile all dependent classes (unless I

> |>   I think it would be useful to permit member function definitions without
> |> requiring a declaration.

> Also, if I can define a "member" function without the class
> declaring it as a member/friend, this blows encapsulation.  What stops
> me from doing anything I want to the private/protected instance data?


It could be possible to declare private methods without adding them to
the .h file, since you can do it with Ada.
But with C++, the encapsulation is performed *only* by the class
descrition, which is usually in the .h file.
As a result, there is no way you can safely define such a function
outside the .h file and avoid recompiling everything.

--
Valery





Author: chris@alofi.etca.fr (Christian Millour)
Date: 1995/04/13
Raw View
In article <VLADIMIR.95Apr12160158@tees.cs.ualberta.ca>, vladimir@tees.cs.ualberta.ca (Vladimir Alexiev) writes:
|> Whenever I add a private helper function to a class, I have to change its
|> interface in the .h file and thus recompile all dependent classes (unless I
|> use touch to bump back the timestamp).
|>   I think it would be useful to permit member function definitions without
|> requiring a declaration.

Provided that you don't need your private helper functions
in friend classes, you might consider implementing them as
(static) members of an opaque friend, e.g.:

Foo.h: --------------------

class Foo {
public:
  Foo();
  double avg() const;
private:
  double a, b, c;
friend struct FooHelpers;
};

Foo.cc: -------------------

#include "Foo.h"
struct FooHelpers {
  static void primify(Foo& aFoo) {aFoo.a = 2; aFoo.b = 3; aFoo.c = 5;}
  static double sum(const Foo& aFoo) {return aFoo.a + aFoo.b + aFoo.c; }
};

Foo::Foo() {
  FooHelpers::primify(*this);
};

double
Foo::avg() const {
  return FooHelpers::sum(*this) / 3.0;
}


Although a bit verbose this makes it possible to have invisible
inline private helpers.


--chris@etca.fr





Author: Ian T Zimmerman <itz@rahul.net>
Date: 1995/04/13
Raw View
In article <VLADIMIR.95Apr12160158@tees.cs.ualberta.ca>,
Vladimir Alexiev <vladimir@tees.cs.ualberta.ca> wrote:
>Whenever I add a private helper function to a class, I have to change its
>interface in the .h file and thus recompile all dependent classes (unless I
>use touch to bump back the timestamp).

But that is a fault of a stupid compiler / nonexistent dependency
analyzer, not of C++ language definition. Moreover, even within such
an environment you can limit the set of `dependent classes' by using
*A's instead of A's, together with one of the following:

1/ forward class declaration of A
2/ abstract base class for A

Granted, sometimes one lacks these methods because instances of A's
are created by a class library one must use. Again, that's not a C++ problem.

>  I think it would be useful to permit member function definitions without
>requiring a declaration.

I think there are two major reasons why all members must be
specified in the class declaration. One is to prevent `hijacking' a
class -- that is, it should be the prerogative of the author of a
class to specify once and forever its interface. Otherwise you could
access a private data member anywhere you wanted: just define a new
member function. It seems to me that this could be weakened for
member functions, though, under the following circumstances:
1/ the class declaration has been seen (so that the compiler knows
   the  access rights for each declared member); and
2/ undeclared member functions are deemed private.

The second reason is that any code `depending' on A needs to know the
size and layout of A objects. Stroustrup in his writings seems to
imply that the only alternative is to do a heap allocation whenever a
class instance is created (as is done eg. in Modula-3). I think that's
not quite so - one could do _stack_ allocation of run-time sized
objects, a-la alloca(). Even that may be too heavy a penalty for class
instantiation in the eyes of some people, though.

Now for member _nonvirtual functions_ even this second reason sounds
hollow at first, because declaring such doesn't affect the
layout. However, it's probably much too subtle to make such
declarations legal or not depending on if a corresponding virtual
already exists (perhaps many base classes higher in the hierarchy).

--
Ian T Zimmerman            +-------------------------------------------+
P.O. Box 13445             I    With so many executioners available,   I
Berkeley, California 94712 I suicide is a really foolish thing to do.  I
USA  <itz@rahul.net>       +-------------------------------------------+





Author: leech@cs.unc.edu (Jon Leech)
Date: 1995/04/13
Raw View
In article <3mj5b1$nr5@locutus.rchland.ibm.com>,
Philip Staite <pstaite@vnet.ibm.com> wrote:
>In article <VLADIMIR.95Apr12160158@tees.cs.ualberta.ca>, vladimir@tees.cs.ualberta.ca (Vladimir Alexiev) writes:
>|> Whenever I add a private helper function to a class, I have to change its
>|> interface in the .h file and thus recompile all dependent classes (unless I
>|> use touch to bump back the timestamp).
>|>   I think it would be useful to permit member function definitions without
>|> requiring a declaration.
>
>Well, definition without declaration takes us back to the pre-prototype
>days of C... Kinda blows argument type checking and type safety...

    If the issue is recompilation, perhaps what he really wants is to only
recompile the source that's affected by the semantics of the change, rather
than all the source that includes the modified header.

    I believe SGI's new 'Delta C++' does something along these lines (thus
the 'Delta'), as well as more far-reaching support for incremental
compilation. Check out their web site (www.sgi.com). There's a big section
on Delta C++ somewhere in there.

    Jon
    __@/





Author: vladimir@tees.cs.ualberta.ca (Vladimir Alexiev)
Date: 1995/04/12
Raw View
Whenever I add a private helper function to a class, I have to change its
interface in the .h file and thus recompile all dependent classes (unless I
use touch to bump back the timestamp).
  I think it would be useful to permit member function definitions without
requiring a declaration.