Topic: PARTIAL CLASS DEFINITIONS - reposted


Author: David R Tribble <david@tribble.com>
Date: 1999/06/30
Raw View
blargg@flash.net wrote:
>
> In article <7k6gpt$2er$1@nnrp1.deja.com>, gbush@my-deja.com wrote:
>
> > In article <7k356c$s55$1@engnews1.eng.sun.com>,
> >   clamage@eng.sun.com (Steve Clamage) wrote:
> >
> > > Don't write random declarations. Put all related
> > > declarations in a header file and always include it.
> >
> > Yeah, that's what we have to do now: include the whole header even
> > if only one class or function is necessary. As a result each file
> > #includes 200000 lines (typical number for Windows) in header files
> > and the number will grow as SCL and other system files are
> > increasing. It's good that some compilers can precompile and cache
> > headers, but others compile it forever and as the systems grow in
> > complexity this problem will be exacerbating.
>
> The solution to a bad design isn't throwing language features at it
> - it's throwing the bad design in the trash.

Large classes (and thus large header files) do not imply bad design.
Some classes (i.e., some problem domain solutions) simply need to be
big.

Until the language allows us to somehow omit the private and protected
class members that are not necessary for (most) clients of a given
class, we will continue to include extra "useless" source lines
into our client code.

-- David R. Tribble, david@tribble.com --
   Those who do not study for-loops are destined to repeat them.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: gbush@my-deja.com
Date: 1999/06/23
Raw View
In article <7k356c$s55$1@engnews1.eng.sun.com>,
  clamage@eng.sun.com (Steve Clamage) wrote:
> Don't write random declarations. Put all related
> declarations in a header file and always include it.
Yeah, that's what we have to do now: include the whole header even if
only one class or function is necessary. As a result each file
#includes 200000 lines (typical number for Windows) in header files and
the number will grow as SCL and other system files are increasing. It's
good that some compilers can precompile and cache headers, but others
compile it forever and as the systems grow in complexity this problem
will be exacerbating.
Gene.

Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: David R Tribble <dtribble@technologist.com>
Date: 1999/06/23
Raw View
rado42@my-deja.com writes:
> >...
> >The story is quite different as far as the MEMBER FUCTIONS are
> >concerned. It would be good if one can kind of  FORWARD declare class
> >member functions WITHOUT defining the entire class; e.g.
> >
> >class MyClass;
> >void MyClass::myMember() const;
> >
> >MyClass* a;
> >a->myMember();

Steve Clamage wrote:
>...
> A good solution to the encapsulation problem is for C++
> to acquire modules like Modula, Ada, or Borland Pascal.
> A header file provides only the public declarations,
> and the module file tells the compiler the rest of the story.
> There are no incomplete declarations having any of the
> problems above, yet you can hide all implementation details
> of a class.
>
> Modules were considered for C++ early on, but the desire
> was to create a language that could be translated easily
> into C and require little system support.  The early
> versions of C++ met that goal. With templates, exceptions,
> and other later language features, that goal has been
> compromised (if not abandoned).
>
> I wouldn't mind seeing modules and their implementations
> discussed for a future version of C++.

No one (that I am aware of) has done it yet, but it's entirely
possible to provide this sort of thing with a "precompiler" for C++.
What I have in mind is a tool that parses C++ source files
containing C++ source code (along with a few new keywords) and
produces exportable header files containing only the publicly
visible declarations.  (This is similar to the way Eiffel works
when it compiles single class source files into their underlying
implementation files, or to the single-source-file-per-class
approach of Java.)  It would be fairly easy to use the 'public'
and 'private' keywords to tag classes, functions, and variables as
being externally visible or invisible.

The problem is coming up with a reasonable scheme for hiding the
data members of classes in these generated "import" header files;
the compiler still needs to know the size of each class, so that
clients can allocate and 'new' class objects correctly.  There's
also the problem of declaring virtual member functions so that the
object's _vtbl is known properly at compile time.

It is possible to kludge our way towards this with something like
this:
    // Source, all the code for a class is in a single source file
    public class Foo    // New syntax
    {
    public:
        virtual      ~Foo();
                     Foo();
        int          pub1();
        virtual int  pub2();

    private:
        virtual void pri();

        int          memb1;
        int          memb2;
    };

    ...

    // Generated export header
    class Foo
    {
    public:
        virtual      ~Foo();
                     Foo();
        int          pub1();
        virtual int  pub2();

    private:
        virtual void __hide__ _h1();  // New keyword used

        int          __hide__ _h2[2];
                             // Not externally useful, except
                             // for knowing sizeof(Foo)
    };

So, what would we call this new language?  C++TNG (The Next
Generation)?  C++++?  C+=2?  D++?

-- David R. Tribble, dtribble@technologist.com --
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: blargg@flash.net
Date: 1999/06/24
Raw View
In article <7k6gpt$2er$1@nnrp1.deja.com>, gbush@my-deja.com wrote:

> In article <7k356c$s55$1@engnews1.eng.sun.com>,
>   clamage@eng.sun.com (Steve Clamage) wrote:
> > Don't write random declarations. Put all related
> > declarations in a header file and always include it.
>
> Yeah, that's what we have to do now: include the whole header even if
> only one class or function is necessary. As a result each file
> #includes 200000 lines (typical number for Windows) in header files and
> the number will grow as SCL and other system files are increasing. It's
> good that some compilers can precompile and cache headers, but others
> compile it forever and as the systems grow in complexity this problem
> will be exacerbating.

The solution to a bad design isn't throwing language features at it - it's
throwing the bad design in the trash.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: rado42@my-deja.com
Date: 1999/06/13
Raw View
PARTIAL CLASS DEFINITIONS proposal
Sorry - my initial proposal has been cut for unknown reason.
Here it is again:

Hello everybody,

Here I would like to make a proposal for C++ extension and to suggest a
discussion about it.

As all we know, one cannot access the members (both data and function)
of a class if  the class definition is not visible, e.g.

class MyClass* a;
a->myMember();


will cause a compilation error: the compiler does not know that MyClass
has myMember(),  even if actually this is the case.

That means that in order to use ANY class member, the code must see the
ENTIRE class definition: e.g.


class MyClass
{
stuff
stuff
more stuff
private stuff





Author: rado42@my-deja.com
Date: 1999/06/13
Raw View
 [Moderator's note: sorry about the two truncated earlier versions
 of this message.  The original message contained an line with an
 8-bit character followed by a ".", and the news posting software
 unfortunately interpreted that as an end-of-message indicator.
  -mod (fjh).]

PARTIAL CLASS DEFINITIONS proposal
Sorry - my initial proposal has been cut for unknown reason.
Here it is again:

Hello everybody,

Here I would like to make a proposal for C++ extension and to suggest a
discussion about it.

As all we know, one cannot access the members (both data and function)
of a class if  the class definition is not visible, e.g.

class MyClass* a;
a->myMember();


will cause a compilation error: the compiler does not know that MyClass
has myMember(),  even if actually this is the case.

That means that in order to use ANY class member, the code must see the
ENTIRE class definition: e.g.


class MyClass
{
stuff
stuff
more stuff
private stuff
...
void myMember() const;
even more stuff
};

 MyClass* a;
 a->myMember();


What I don   t like here is the fact that the code MUST know lots of
things it is not interested about in order to use only SMALL PART of
it.  The encapsulation suffers considerably and the code dependencies
grow up.

As far as the DATA MEMBERS are concerned, this limitation has it   s
explanation: the compiler is not able to generate the right code if it
does not see the entire class layout.

The story is quite different as far as the MEMBER FUCTIONS are
concerned. It would be good if one can kind of  FORWARD declare class
member functions WITHOUT defining the entire class; e.g.

class MyClass;
void MyClass::myMember() const;

MyClass* a;
a->myMember();


I will call this feature "PARTIAL CLASS DEFINITION"



Author: "G.B." <gb@web1.ucar.edu>
Date: 1999/06/15
Raw View
<rado42@my-deja.com> wrote in message
news:fixed-7jvem3$os5$1@nnrp1.deja.com...
[snip]
> class MyClass;
> void MyClass::myMember() const;
>
> MyClass* a;
> a->myMember();
>
[snip]
> So, what do you think?
>
It certainly would be very convenient and I myself had many situation where
it was desirable. But here is a problem. If myMember is not virtual or
inline function compiler can leave it to linker to bind correct function.
Inline functions cannot be generated this way, compiler must see the
definition and it's absent in the declaration. Virtual function call also
cannot be generated, because compiler must know the offset of myMember in
the vtable. Compiler can calculate it based of the class definition which is
missing in this declaration.
The solution - make linker more intelligent, it can substitute real
MyClass_vtable_myMember_offset during linkage phase. And in case of inline
member function, compiler could generate non-inlined version and linker can
give warning that inline was discarded.
Gene.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: blargg@flash.net (Gargantua Blargg)
Date: 1999/06/15
Raw View
In article <fixed-7jvem3$os5$1@nnrp1.deja.com>, rado42@my-deja.com wrote:

...
> PARTIAL CLASS DEFINITIONS proposal
...
> As all we know, one cannot access the members (both data and function)
> of a class if  the class definition is not visible, e.g.
>
> class MyClass* a;
> a->myMember();
>
> will cause a compilation error: the compiler does not know that MyClass
> has myMember(),  even if actually this is the case.
...
> It would be good if one can kind of  FORWARD declare class
> member functions WITHOUT defining the entire class; e.g.
>
> class MyClass;
> void MyClass::myMember() const;
>
> MyClass* a;
> a->myMember();
>
> I will call this feature "PARTIAL CLASS DEFINITION"
>
> From technical point of view it looks to me quite nice: if one omits
> this member in the class,
> he will either get compile time error (in case the class sees the
> FORWARD declaration), or at least link error (if you omit to define the
> member function).
>
> I really don't know what's the story with virtual member functions, but
> it looks to me that they can be FORWARD declared too.
>
> At my opinion this possibility would improve the encapsulation
> possibilities and would decrease build dependencies.

Negative on the former (see below). Agreed on the latter (though it is not
a useful means of achieving this).

> This proposal is also fully backward compatible with existing standard,
> too.

Aren't they all? :-)   Everyone says this all the time about their pet
proposal, as if this is all that matters in the end. heh.

> So, what do you think?

I think it sucks (nothing personal). It sucks for the same reason
declaring function signatures directly does - it breaks encapsulation and
prevents libraries from making compatible changes, such as adding a
default argument.

For example, my library provides this function:

    void jump();

And clients use it like this:

    jump();

Later I realize it is to my advantage to ask "how high?", but I want
current clients to compile without specifying this.

    void jump( int how_high = 10 );

However, some short-sighted clients declared my function as taking
nothing, so they got link errors:

    void jump(); // sorry, not defined anymore, sucka!

    jump(); // huh? link error? but I wanted to reduce dependencies

Nope, now you've *increased* dependency on my library by doing this. Not good.

With that out of the way for simple functions, you can see that the same
same (and more) applies to member functions. Just to run off a few...
access control, inherited members (you have to know if it is defined in
the specific class, or inherited from a base class), and being virtual
(this would rule out many implementations of vtables).

So, the key problem with it: It would be harmful to a library provider's
ability to make (backwards) compatible changes in their interfaces.

--
"I don't like my edges rounded off" - Ani DiFranco

Gargantua Blargg | blargg@flash.net | http://www.flash.net/~blargg/
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: clamage@eng.sun.com (Steve Clamage)
Date: 1999/06/15
Raw View
rado42@my-deja.com writes:

>As all we know, one cannot access the members (both data and function)
>of a class if  the class definition is not visible, e.g.

>class MyClass* a;
>a->myMember();

>will cause a compilation error: the compiler does not know that MyClass
>has myMember(),  even if actually this is the case.

>That means that in order to use ANY class member, the code must see the
>ENTIRE class definition: e.g.

>class MyClass
>{
>stuff
>stuff
>more stuff
>private stuff
>...
>void myMember() const;
>even more stuff
>};

> MyClass* a;
> a->myMember();


>As far as the DATA MEMBERS are concerned, this limitation has it's
>explanation: the compiler is not able to generate the right code if it
>does not see the entire class layout.

>The story is quite different as far as the MEMBER FUCTIONS are
>concerned. It would be good if one can kind of  FORWARD declare class
>member functions WITHOUT defining the entire class; e.g.

>class MyClass;
>void MyClass::myMember() const;

>MyClass* a;
>a->myMember();

On reason for not allowing partial declarations of
this sort is to prevent inconsistent ideas about the class
definition. A class could be modified in ways that affect
function overloading and valid calls, meaning the partial
declarations would have to be sought out and modified too.

You could argue that the same situation exists for non-
member functions already, and the solution is the same:
Don't write random declarations. Put all related
declarations in a header file and always include it.
Yet classes are special in being strongly typed; we'd
like to avoid the problem in the language, instead of
adding more opportunities for errors to creep in.

A second reason is that partial declarations allow a class
to be hijacked. Without access to the class source files
you could modify its semantics and functionality. The
temptation to add just a little functionality to the class
without forcing recompilation of all its clients would
be too great to ignore, leading to chaos. (Two programmers
independently add conflicting functionality without
modifying the class definition.)

The partial declarations would have to indicate protection
level, although we could reasonably require that only public
functions could be so declared.

The partial declarations would have to indicate whether
the functions were virtual, unless you want to require
that only non-virtual functions could be declared. That
doesn't sound so good, so we need some additional syntax.

You can simulate the encapsulation you want by the so-called
"pimpl" or "letter-and-envelope" idiom. Provide only a
forward declaration for a class that contains the secret
parts, and put a pointer to it in the visible class:
 class T {
 public:
     class impl;
     ... forwarding functions using pointers to impl
 private:
     impl* pimpl; // pointer to the implementation
 };
This solution completely isolates the implementation from
the interface. It has runtime overhead that is sometimes
unacceptable.

A good solution to the encapsulation problem is for C++
to acquire modules like Modula, Ada, or Borland Pascal.
A header file provides only the public declarations,
and the module file tells the compiler the rest of the story.
There are no incomplete declarations having any of the
problems above, yet you can hide all implementation details
of a class.

Modules were considered for C++ early on, but the desire
was to create a language that could be translated easily
into C and require little system support.  The early
versions of C++ met that goal. With templates, exceptions,
and other later language features, that goal has been
compromised (if not abandoned).

I wouldn't mind seeing modules and their implementations
discussed for a future version of C++.

--
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: gbush@my-deja.com
Date: 1999/06/15
Raw View
In article <fixed-7jvem3$os5$1@nnrp1.deja.com>,
  rado42@my-deja.com wrote:
[snip]
> The story is quite different as far as the MEMBER FUCTIONS are
> concerned. It would be good if one can kind of  FORWARD declare class
> member functions WITHOUT defining the entire class; e.g.
>
> class MyClass;
> void MyClass::myMember() const;
>
> MyClass* a;
> a->myMember();
>
> I will call this feature "PARTIAL CLASS DEFINITION"

Don't know what happened to my previous reply to your post. Probably it
befell the same fate as your original post.
In a nutshell, this is a very good proposal. The problem is that modern
linkers do not do this job. When member function is virtual compiler
looks at the class definition to generate offset in vtable. This task
needs to be done by linker. Another problem is when member function is
inlined. The compiler should generate a non-inlined version of the
function also. This maybe difficult. To solve the problem, compiler
could generate for each inline function non-inline version and then
linker can easily remove unused functions from executable file.
Gene.


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]