Topic: Common baseclass for all
Author: Nicola.Musatti@ObjectWay.it (Nicola Musatti)
Date: Tue, 30 Mar 2004 18:09:09 +0000 (UTC) Raw View
hattons@globalsymmetry.com ("Steven T. Hatton") wrote in message news:<S4udnY1lyLArcPrdRVn-gg@speakeasy.net>...
> Nicola Musatti wrote:
[...]
> As for presumptuousness, it's probably more presumptuous of me to believe
> I have /any/ valuable insight into how to improve C++.
Just to be sure there's no misunderstanding: I wasn't calling *you*
presumptuous; I don't like language designers that assume they know
better than me what I need or do not need.
> But let me ask this: In view of how a UBC (universal base class) is employed
> in languages such as Java and C# (I know very little about C#), are there
> any properties potentially valuable to a significant portion of the classes
> commonly used by C++ programmers? IOW, *_IF_*, there were a UBC in C++,
> what would you suggest putting there? Addressing this question may lead to
> valuable insight regardless of whether a UBC is ever added to C++.
While some of the functions addressed by java.lang.Object would be
nice additions to C++, I believe none of those are useful to the
majority of the classes I wrote. Let's examine some of these in
detail:
- clone() : Note that there's no way to enforce a correct
implementation
of cloning in derived classes.
- equals() : it is actually very error prone to provide equality
comparison
as a virtual member function (for details see [1]).
- finalize() : C++ has deterministic destructors, which are a far
superior
tool.
- getClass() : Java's reflection is a powerful mechanism that C++ is
lacking;
however I believe it should be optional.
The others are hashCode(), toString() and a bunch of threading related
methods.
The only one of these that really makes more sense as a virtual member
function is clone(), but how often do you need your classes to be
clonable, especially since C++ supports stack based value objects and
assignment redefinition?
[...]
> You raise an interesting issue regarding templates. I'm wondering how many
> problems would arise with templates when trying to incorporate a UBC into
> the language.
None, I think, unless you expect to incorporate somehow your notion of
a UBC into them.
[...]
> > Not to mention the fact that the existence of multiple inheritance
> > makes a common base class rather inconvenient.
>
> I've been told by others this represents a problem, but I'm not sure what
> the problem actually is. How does the introduction of a UBC make MI
> (Multiple Inheritance) more problematic than it already is?
MI is a powerful tool and as it is with all powerful tools, it must be
handled with care. Introducing a UBC would force all kind of
undesirable problems, by forcing the well known "diamond of death" on
all multiple inheritance hyerarchies.
> >> One feature which might be supported by common baseclass inheritance is
> >> introspection. [...]
> >
> > Note that C++ differs from languages such as Java in that
> > introspection is not only desirable at runtime, but also at compile
> > time;
>
> Here I don't follow. Can you elaborate on this? Java actually employs
> introspection at design time through the JavaBeans specification.
Design time is still runtime, even though your components may do
different things than when your application is running. I suspect
you're not familiar with the template metaprogramming technique. Check
out [2] for a (rather tough) introduction.
> > even setting aside my previous objections I don't think that the
> > common base class would be a suitable approach for fulfilling these
> > goals.
>
> The goal of providing introspection? That seems to be contingent on the
> question of whether it's desireable to have universally available
> introspection.
A UBC is not required in order to provide introspection. It would be
sufficient to extend the current typeid/type_info mechanism.
[...]
> > One reason why
> > I consider it unsuitable as a first language is that it instills
> > distorted views of the (programming) world, such as "there has to be
> > an ultimate base class" or "every function must belong to a class".
>
> I am far more inclined to dispense with the former than the latter. (User
> defined) free functions are almost as bad as global variables. Just today
> I encountered a situation where the reuse of good C++ code was encumbered
> because it had been written in the global namespace using the style of C.
How so? did it use very common names?
> > Inheritance is a tool. Sometimes it's useful, sometimes it isn't, and
> > it's important to know that it isn't universal.
>
> This I understand. I've actually been looking into the impact on the
> so-called concrete classes of having a UBC. If the UBC required every
> object to hold a vtbl pointer, that could have enormous consequences on the
> memory required by a program using concrete classes. I actually suggested
> splitting struct off from the UBC hierarchy to maintain support for
> concrete classes.
The amount of trouble you have to go to fit your UBC into C++ should
be conclusive evidence that not only one is not needed, it would
actually be harmful.
> >> In addition to proposing a common baseclass, and a shared descriptor
> >> object per class, I propose there be a specialized form of a namespace
> >> which would contain only one class, and its associated helper functions.
> >
> > A class *is* a namespace. If you really think that some "helper"
> > functions are tightly bound to the class, make them static members.
>
> Stroustrup argues against that approach. He suggests that helper functions
> that don't need access to member variables should not be members of the
> class. This is discussed in 10.3.2 of TC++PL(SE). Ironically, at the end
> of the first paragraph in that section I noted as follows:"Get over it!
> Make them static". At that time I had failed to appreciate his argument.
He is also the one who let free functions into the language ;-)
> >> This serves two useful purposes. First, it serves to encompass helper
> >> functions into the OO framework.
> >
> > Fulfilling one's desire for aesthetic completeness is not what I
> > consider a compelling language design principle.
>
> Please consider my previous comment.
Which one? I do not think you provided any support yet for the need of
a UBC.
> >> using namespace NameSpaceName::*;
> >>
> >> would be used.
> >
> > It's not clear to me what you mean.
>
> I find the current namespace model rather messy. I don't like the way using
> one namespace in another introduces a union of all symbols from both
> namespaces present in the translation unit into a third namespace that uses
> it. My suggestion was meant as a means of limiting what comes into a
> namespace with a using directive. The current form of the directive would
> only bring in 'global' symbols of the namespace.
Still not clear to me. Would you care to provide an example?
> > As I wrote above, your classspace coincides with the class, so it's
> > not necessary.
>
> The distinction is that members of the classspace would not have private or
> protected access to class members.
You can achieve the same by nesting classes.
Cheers,
Nicola Musatti
[1] http://home.camelot.de/langer/Articles/JavaSolutions/SecretsOfEquals/Equals.html
[2] http://www.boost.org/libs/mpl/doc/paper/html/index.html
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hattons@globalsymmetry.com ("Steven T. Hatton")
Date: Wed, 31 Mar 2004 00:17:46 +0000 (UTC) Raw View
Adam H. Peterson wrote:
>>>One reason why
>>>I consider it unsuitable as a first language is that it instills
>>>distorted views of the (programming) world, such as "there has to be
>>>an ultimate base class" or "every function must belong to a class".
>>
>>
>> I am far more inclined to dispense with the former than the latter. (User
>> defined) free functions are almost as bad as global variables. Just
>> today I encountered a situation where the reuse of good C++ code was
>> encumbered because it had been written in the global namespace using the
>> style of C.
>
> I've seen the other situation. Code reuse was impaired because a
> function was tethered to a class as a member function and was difficult
> to overload or refactor. I think it's best to put functions in
> namespaces unless there are design reasons they should be members. But
> IME it's easier to move a global function into a namespace than it is to
> refactor a member function to be a nonmember function even though it
> didn't need to be a member function in the first place. (I usually
> employ namespaces at the module level, rather than the class level.)
It's not uncommon for programmers to create a 'utility' class which holds
(ideally) related public static functions and constants. The class need
never be instantiated. Certainly this is very similar to the use of a
namespace for the same purpose. I prefer to be conservative in what I
introduce into the current namespace. I much prefer introducing a single
class or variable than an entire namespace.
One advantage to having a utility class such as I described is that, with
good IDE support, it is relatively easy to look through the available
functions and constants at the edit cursor by simply typing the classname
to invoke code completion. I guess the same will work for a 'utility'
namespace, or for any namespace.
The idea of using a namespace makes me uneasy because, from what I've seen
in C++, they aren't always as structured as I would like. I hate to pick
on the holyest of namespaces, but I dislike the flatness of the std
namespace.
There seems to be no overall guiding principle for the structure and use of
namespaces.
--
STH
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: ahp6@email.byu.edu ("Adam H. Peterson")
Date: Wed, 31 Mar 2004 05:25:08 +0000 (UTC) Raw View
> It's not uncommon for programmers to create a 'utility' class which holds
> (ideally) related public static functions and constants. The class need
> never be instantiated. Certainly this is very similar to the use of a
> namespace for the same purpose. I prefer to be conservative in what I
> introduce into the current namespace. I much prefer introducing a single
> class or variable than an entire namespace.
I dislike this approach for several reasons, some of which are:
1) It's difficult to oveload these functions, especially without
changing the class definition (which may be impossible, or is at least
likely to force excessive recompilation).
2) You can't import those functions into another namespace, even if you
wanted to. Outside the class, you must always qualify the names.
What benefit does this have over a nested namespace?
>
> One advantage to having a utility class such as I described is that, with
> good IDE support, it is relatively easy to look through the available
> functions and constants at the edit cursor by simply typing the classname
> to invoke code completion. I guess the same will work for a 'utility'
> namespace, or for any namespace.
I can't speak to that, I'm afraid. I used to use IDEs, but haven't for
years. I expect the IDEs are better than they were when I stopped using
them around the turn of the century, but I don't have a feel for it. As
you say, though (and I would assume), you get the same benefits from a
namespace.
>
> The idea of using a namespace makes me uneasy because, from what I've seen
> in C++, they aren't always as structured as I would like. I hate to pick
> on the holyest of namespaces, but I dislike the flatness of the std
> namespace.
I use namespaces at the module level, and I've run into few if any
namespace problems. I tend not to use "using" directives to import an
entire namespace into another, though.
>
> There seems to be no overall guiding principle for the structure and use of
> namespaces.
Depending on your style, this may be true. I don't see how using
classes instead makes the situation any better, though. Are there
better guiding principles for that than namespaces?
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hattons@globalsymmetry.com ("Steven T. Hatton")
Date: Wed, 31 Mar 2004 19:18:18 +0000 (UTC) Raw View
Nicola Musatti wrote:
> hattons@globalsymmetry.com ("Steven T. Hatton") wrote in message
>> IOW, *_IF_*, there were a UBC in C++,
>> what would you suggest putting there? Addressing this question may lead
>> to valuable insight regardless of whether a UBC is ever added to C++.
>
> While some of the functions addressed by java.lang.Object would be
> nice additions to C++, I believe none of those are useful to the
> majority of the classes I wrote. Let's examine some of these in
> detail:
> - clone() : Note that there's no way to enforce a correct
> implementation of cloning in derived classes.
Is this different from the situation with the C++ default copy constructor?
Clone is often overridden in Java, in much the same way as a programmer
provides a copy constructor in C++.
> - equals() : it is actually very error prone to provide equality
> comparison as a virtual member function (for details see [1]).
I looked at [1]. I have to say the assertion that the default behavior of
equals(), (which is the same as Java's '==') does not represent equivalence
is incorrect. To take an abstract example, lets say we have a set S
containing objects as follows {0,1,2,3,...,9,10...,etc}. Now suppose we
have variables x and y which can each hold one of these objects. We could
define == such that x == y is true if and only if x holds the same object
as y. I.e. 1==1,2==2,3==3, etc., are all true, but 1==2,2==3,3==1, are
false. In other words identity forms an equivalence class. It's the
equivalence class used in all of mathematics unless otherwise specified in
the context.
But, now I ask how does C++'s overloaded '==' operator differ from Java's
equals() in such a way as to prevent the same kinds of problems as
described in [1]?
> - finalize() : C++ has deterministic destructors, which are a far
> superior tool.
I assume that comment is in reference to Java's garbage collection? How does
finalize() otherwise differ from the default destructors of C++?
> - getClass() : Java's reflection is a powerful mechanism that C++ is
> lacking; however I believe it should be optional.
I'm really not sure what it would take to implement reflection in C++. I
tend to agree it should be optional. I will also note Stroustrup's
encouraging assessment in TC++PL(SE) 15.4.4.1 "[T]he likelihood is zero
that someone can come up with a single set of information that satisfies
every user."
Reflection is one of the key features I was thinking of when I proposed a
UBC. It's probably worth further investigation. Perhaps a library could be
specified in the Standard or in boost.
> The others are hashCode(), toString() and a bunch of
> threading related methods.
This is another feature I was thinking could be introduced into the core
language through a UBC. I'm not sure of the value of having threading as a
fundamental part of the language. I don't know the value of having a
threaded version of the STL, or even what that would mean.
> MI is a powerful tool and as it is with all powerful tools, it must be
> handled with care. Introducing a UBC would force all kind of
> undesirable problems, by forcing the well known "diamond of death" on
> all multiple inheritance hyerarchies.
Something tells me that could be handled through some kind of special
provision, but I'm fairly well persuaded a UBC really isn't advisable for
C++. I kind of hate to give up the cause so easily because I think it
would be productive to get a lot of people looking at it. It's part of a
bigger objective I believe is worth persuing. Determining what can be
learned and adopted from C# and Java to add value to C++ without
subtracting value?
>> Here I don't follow. Can you elaborate on this? Java actually employs
>> introspection at design time through the JavaBeans specification.
>
> Design time is still runtime, even though your components may do
> different things than when your application is running. I suspect
> you're not familiar with the template metaprogramming technique.
> Check out [2] for a (rather tough) introduction.
Sure, Ozone http://www.ozone-db.org/frames/home/what.html uses a kind of
metaprogramming approach. Qt's moc is used to implement slots and signals
as a form of metaprogramming. And of course, C++ has templates. I'm not
sure how reflection plays into this. I'll admit I have not read the entire
document you referenced. Can you tell me what parts might shed some light
on how reflection could be useful in this area?
>> I am far more inclined to dispense with the former than the latter. (User
>> defined) free functions are almost as bad as global variables. Just
>> today I encountered a situation where the reuse of good C++ code was
>> encumbered because it had been written in the global namespace using the
>> style of C.
>
> How so? did it use very common names?
It was reusable in the sense of copy and paste. But that isn't very elegant
in my book. As soon as I caught on to Java's paradigm, I realized it was
exactly what I had been looking for in terms of OO thinking. Sure, I could
simple consider functions in the global namespace to be 'member functions'
of a global 'class', but It just feels wrong.
> The amount of trouble you have to go to fit your UBC into C++ should
> be conclusive evidence that not only one is not needed, it would
> actually be harmful.
It may mean I simply haven't found the proper angle on the problem.
>> Please consider my previous comment.
>
> Which one? I do not think you provided any support yet for the need of
> a UBC.
The current protion of the overall UBC proposal doesn't require a UBC, and
stand on its own.
> Still not clear to me. Would you care to provide an example?
namespace foo{
const int BAR_CONST = 42;
using namesapce blah;
classspace equestrian{
bool helperFunciton(const &equestrian eq){
return testresult(eq);
}
class <gets name from classspace>{
}
}
}
using namespace foo;
//I can see BAR_CONST but nothing else from the namespace, and nothing
// from namespace blah.
using namespace foo::*;
//I can see everything from the foo namespace including class equestrian.
>> > As I wrote above, your classspace coincides with the class, so it's
>> > not necessary.
>>
>> The distinction is that members of the classspace would not have private
>> or protected access to class members.
>
> You can achieve the same by nesting classes.
I don't think that would accomplish my objective. A better solution might
be an access specifier in addition to public, private and protected.
Perhaps 'associated'. A function declared as associated would be resolved
like a member function, but would not be given access to private or
protected members. The problem would be getting people to use it
correctly.
[http://home.camelot.de/langer/Articles/JavaSolutions/SecretsOfEquals/Equals.html
>
> [2] http://www.boost.org/libs/mpl/doc/paper/html/index.html
Both articles look very worthwhile. Thanks!
--
STH
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: ahp6@email.byu.edu ("Adam H. Peterson")
Date: Wed, 31 Mar 2004 22:15:55 +0000 (UTC) Raw View
Steven T. Hatton wrote:
> Nicola Musatti wrote:
>
>
>>hattons@globalsymmetry.com ("Steven T. Hatton") wrote in message
>>
>>>IOW, *_IF_*, there were a UBC in C++,
>>>what would you suggest putting there? Addressing this question may lead
>>>to valuable insight regardless of whether a UBC is ever added to C++.
>>
>>While some of the functions addressed by java.lang.Object would be
>>nice additions to C++, I believe none of those are useful to the
>>majority of the classes I wrote. Let's examine some of these in
>>detail:
>>- clone() : Note that there's no way to enforce a correct
>>implementation of cloning in derived classes.
>
>
> Is this different from the situation with the C++ default copy constructor?
> Clone is often overridden in Java, in much the same way as a programmer
> provides a copy constructor in C++.
Yes, but a class never inherits and uses a base class's copy
constructor. If the user doesn't provide one, the compiler generates an
appropriate one, unless it's disallowed (usually by a base or member
according to fairly sensible rules), in which case copying a class
generates a diagnostic.
[...]
> But, now I ask how does C++'s overloaded '==' operator differ from Java's
> equals() in such a way as to prevent the same kinds of problems as
> described in [1]?
Someone will probably immediately contradict me, but I think they both
tend to have much the same problems. It is easier to overload C++'s
equivalent mechanism for derived types, though, but that's not a
guarantee that the base version won't still accidentally be called
through a base interface.
>
>
>>- finalize() : C++ has deterministic destructors, which are a far
>>superior tool.
>
>
> I assume that comment is in reference to Java's garbage collection? How does
> finalize() otherwise differ from the default destructors of C++?
Because C++ destructors are deterministic and ownership is much clearer
in C++. In Java, when finalize() is called, the only things I can count
on still being valid are my primitive data elements and my base type's
primitive data elements. Any references to other objects or resources
may be there or may be gone -- I don't know what order things are
destroyed in. In C++, I know that anything I "own" is still there and
can be used in the destructor, including all member objects and all
bases. (It doesn't help things that in Java you can't have "member
objects," only member references, which might be bad when finalize() is
called.
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Nicola.Musatti@ObjectWay.it (Nicola Musatti)
Date: Mon, 5 Apr 2004 18:05:32 +0000 (UTC) Raw View
hattons@globalsymmetry.com ("Steven T. Hatton") wrote in message news:<zIGdnclWP8up2_Hd4p2dnA@speakeasy.net>...
> Nicola Musatti wrote:
>
> > hattons@globalsymmetry.com ("Steven T. Hatton") wrote in message
> > news:<SNqdnbFsCt2yMffdRVn-jA@speakeasy.net>...
> >> Nicola Musatti wrote:
> >>
> >> > hattons@globalsymmetry.com ("Steven T. Hatton") wrote in message
> > [...]
>
> > They are different operations from a conceptual point of view. Cloning
> > is polymorphic, in that the dynamic type of an object is involved. The
> > result may be a shallow copy by default, but it is never sliced.
>
> I'd have to consider what happens if I call clone through a superclass
> pointer in Java. I don't know if that would effectively slice or not.
According to the Sun documentation, it does not.
> > Cloning makes sense for classes with pointer semantics, while copy
> > construction mostly makes sense for objects with value semantics. As
> > Java doesn't directly support classes with value semantics, cloning is
> > much more important than in C++.
>
> I'm not really sure I understand what you mean by value semantics verse
> pointer semantics. From the purely conceptual reference, I will argue Java
> more readily and frequently supports value semantics than does C++. This
> seems somewhat off topic, so I don't want to pursue it unless it
> contributes to the objective of this newsgroup. If it helps to clarify
> definitions used to specify the language then it probably is worth further
> discussion.
No, Java only supports value semantics for primitive types. User
defined types have pointer semantics.
> > You are confusing values and objects. Where class instances are
> > involved in Java, equality comparisons implements identity, not
> > equivalence. Given the following (pseudo) Java:
> >
> > Integer i = 1;
> > Integer j = 1;
> > i == j is false.
> >
> > This is more or less the same as C++'s:
> >
> > int i = 1;
> > int j = 1;
> > &i == &j which is also false.
>
> Mathematically, identity forms an equivalence class over a set of enumerable
> objects. That equivalence class is isomorphic to the subset of non-negative
> integers with an upperbound of n where n is the number of objects. It's not
> a question of confusion, it's a question of semantics. But here we are
> trespassing on the ground of philosophy and fast approaching that of
> religion. Let's agree to disagree on this one.
No, sorry. It's a question of language semantics. In Java the '=='
operator always compares addresses. Two objects of user defined types
are different unless they are the same object. This doesn't really
make sense for classes that represent quantities, whereas it might be
reasonable for classes whose instances represent different entities in
the real world. You and me might have the same first and last names
and thus be "equal" in a sense, but we still are different persons.
> >> But, now I ask how does C++'s overloaded '==' operator differ from Java's
> >> equals() in such a way as to prevent the same kinds of problems as
> >> described in [1]?
> >
> > By applying value oriented semantics, i.e. operate on the arguments'
> > static type rather than on their dynamic type.
>
> I'm not sure such a clear distinction can be drawn. An experiment is in
> order. I hypothesize that clone() can be called on a Java object's
> superclass producing basically the same result as slicing in C++. C++
> assignment operators can optionally be declared virtual (13.5.3.2). Doing
> so will produce a result comperable to Java's clone() when called on the
> most derived class of an object.
The assumption is wrong. Unless it is overridden the clone method
always returns an object of the same type as the most derived type of
the object on which it is called.
> Perhaps I should run the experiment before I post this, but at some point I
> have to break the infinite regression, so I'll simply post the hypothesis.
If only to avoid embarassment :-)
> > The difference is that you know exactly when a destructor is called in
> > C++, while you are not even guaranteed that a finalizer will ever run
> > in Java.
>
> The consequence of this is unclear to me. Certainly in terms of garbage
> collection there is meaning, but the impact of further execution of the
> program after the point at which finalize could be called is less clear.
> I'm not disagreeing. I'm simply expressing ignorance of the details.
You are missing the important point, which is what would happen in C++
if a destructor weren't called when it is supposed to be. One very
useful application of C++ destructor is the release of resources upon
scope exit, both in the normal case *and* in the presence of
exceptions. Stack unwinding ensures that a local object's destructor
is called in both cases.
> > Actually I'm convinced that many commercial STL implementations
> > currently available *are* thread safe, as the platform they run on
> > support some form of multithreading.
>
> Being thread safe, and running on threaded platforms are not synonymous.
> It's is possible to 'wrap' objects in synchronized objects. Thus the STL
> implementation need never have threadding support incorporated. I'm not
> sure it's even meaningful to talk about a thread-safe implementation of the
> STL. But this again brings us to semantics.
Such an implementation would most likely be useless. Instead most STL
implementations I know guarantee that the handling of internal
structures is thread safe and the user only has to worry about the
public interface to STL objects.
> > Again, I believe that a standard
> > approach to multithreading would be very valuable, but this doesn'tr
> > have anything to do with UBC's.
>
> That is not entirely clear. There may be no necessary connection, but, as
> you point out. Java does seem to leverage its UBC to support threading.
That's because inheritance is at the same time the only generalization
mechanism it supports and the basic unit of function grouping.
[...]
> > As far as the core language is concerned, my opinion is very little:
> > after all those languages have mostly been devised by removing
> > features from C++. A more profitable endeavour would be to address
> > some of the features provided by those languages' standard libraries.
>
> I have the sense the UBC is standing over C++ invisibly manifesting itself
> in every class we create. It my be worth persuing as a metaphor if not a
> design feature.
The existence of commonality is not necessarily best expressed by a
common base class, and sometimes it actually may not be expressed in
that way. The STL is probably the best example of this. You can read
the "Concepts and Modeling" and the "Refinement" paragraphs from the
following article for details:
http://www.sgi.com/tech/stl/stl_introduction.html
[...]
> >> I don't think that would accomplish my objective. A better solution
> >> might be an access specifier in addition to public, private and
> >> protected.
> >> Perhaps 'associated'. A function declared as associated would be
> >> resolved like a member function, but would not be given access to private
> >> or
> >> protected members. The problem would be getting people to use it
> >> correctly.
> >
> > Are you aware of the existence of Argument Dependent Lookup, that is
> > that functions participate in overload resolution not only according
> > to the namespace they are defined in, but also according to all the
> > namespaces in which the function's arguments' types are defined.
>
> Is that the same as Koening Lookup? How might that apply here?
Yes. ADL already performs the kind of resolution you describe above.
Cheers,
Nicola Musatti
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: usenet_cpp@lehrerfamily.com (Joshua Lehrer)
Date: Mon, 5 Apr 2004 18:32:37 +0000 (UTC) Raw View
susudata@setidava.kushan.aa ("Steven T. Hatton") wrote in message news:<f4-dnYG_cpTgdPzdRVn-hA@speakeasy.net>...
> In some programming languages there is a common baseclass for all (user
> defined) objects. This allows for certain functionality to be shared by all
> classes. Obviously, C++ accomplishes some of this without providing a
> common baseclass.
>
I've always felt that "void" should be a common baseclass for all.
Thus, the folling would all be legal c++ code:
const void& temp(std::string("hello"));
void func(const void &);
func(std::string("hello"));
void func2(const void *);
std::string s("hello");
func2(&s);
One might ask why you would want to bind a temporary to const void &.
There are many times where you want to rely on the rule that a
temporary will live longer than a reference bound to it, but you don't
necessarily have an easy way to get the type of the temporary:
const void & locker = get_lock(args);
get_lock may be overloaded based on the types of the args, and
deducing the return type may be complex. This is part of the
motivation of the "auto" proposal.
This technique would make programming techniques like Scopeguard and
LockRegion significantly easier.
joshua lehrer
factset research systems
NYSE:FDS
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: ahp6@email.byu.edu ("Adam H. Peterson")
Date: Mon, 5 Apr 2004 19:35:58 +0000 (UTC) Raw View
>>I'm not sure such a clear distinction can be drawn. An experiment is in
>>order. I hypothesize that clone() can be called on a Java object's
>>superclass producing basically the same result as slicing in C++. C++
>>assignment operators can optionally be declared virtual (13.5.3.2). Doing
>>so will produce a result comperable to Java's clone() when called on the
>>most derived class of an object.
>
>
> The assumption is wrong. Unless it is overridden the clone method
> always returns an object of the same type as the most derived type of
> the object on which it is called.
Is this true? I was under the impression that Java's clone() method
returns an object of the most derived type that actually overrides
clone() (assuming clone() is defined to return an object of the class's
type), which means you get slicing _unless_ you override it. This is
certainly what happens in comparable C++ virtual clone factories.
But (assuming I'm correct) from that point of view, slicing in Java
works completely differently than the slicing in C++ that results from a
value copy. In C++, it is the expression performing the copy that
governs the most derived type of the result, and in Java it is the type
of the most derived object that implements clone() on which the
operation is called.
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Nicola.Musatti@ObjectWay.it (Nicola Musatti)
Date: Wed, 7 Apr 2004 01:43:20 +0000 (UTC) Raw View
ahp6@email.byu.edu ("Adam H. Peterson") wrote in message news:<c4sab3$b2g4$1@acs2.byu.edu>...
[...]
> > The assumption is wrong. Unless it is overridden the clone method
> > always returns an object of the same type as the most derived type of
> > the object on which it is called.
>
> Is this true? I was under the impression that Java's clone() method
> returns an object of the most derived type that actually overrides
> clone() (assuming clone() is defined to return an object of the class's
> type), which means you get slicing _unless_ you override it. This is
> certainly what happens in comparable C++ virtual clone factories.
On the contrary, by convention clone() overrides are expected to
obtain the cloned object by calling the base class clone() method and
then perform class local customizations on that object. If you do
nothing you obtain a shallow copy of the most derived object.
In C++ this corresponds to implementing clone() in every class as
MyClass * clone() { return new MyClass(*this); }
but never redefine the copy constructor.
Cheers,
Nicola Musatti
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Nicola.Musatti@ObjectWay.it (Nicola Musatti)
Date: Thu, 1 Apr 2004 13:50:25 +0000 (UTC) Raw View
hattons@globalsymmetry.com ("Steven T. Hatton") wrote in message news:<SNqdnbFsCt2yMffdRVn-jA@speakeasy.net>...
> Nicola Musatti wrote:
>
> > hattons@globalsymmetry.com ("Steven T. Hatton") wrote in message
[...]
> > While some of the functions addressed by java.lang.Object would be
> > nice additions to C++, I believe none of those are useful to the
> > majority of the classes I wrote. Let's examine some of these in
> > detail:
> > - clone() : Note that there's no way to enforce a correct
> > implementation of cloning in derived classes.
>
> Is this different from the situation with the C++ default copy constructor?
> Clone is often overridden in Java, in much the same way as a programmer
> provides a copy constructor in C++.
They are different operations from a conceptual point of view. Cloning
is polymorphic, in that the dynamic type of an object is involved. The
result may be a shallow copy by default, but it is never sliced.
Copy construction operates on the static type of the object and
slicing takes place if you assign an object of a derived class to an
object of a base class; in a way in clonong the type of the source of
the copy wins, while in copy construction the type of the destination
wins.
Cloning makes sense for classes with pointer semantics, while copy
construction mostly makes sense for objects with value semantics. As
Java doesn't directly support classes with value semantics, cloning is
much more important than in C++.
> > - equals() : it is actually very error prone to provide equality
> > comparison as a virtual member function (for details see [1]).
>
> I looked at [1]. I have to say the assertion that the default behavior of
> equals(), (which is the same as Java's '==') does not represent equivalence
> is incorrect. To take an abstract example, lets say we have a set S
> containing objects as follows {0,1,2,3,...,9,10...,etc}. Now suppose we
> have variables x and y which can each hold one of these objects. We could
> define == such that x == y is true if and only if x holds the same object
> as y. I.e. 1==1,2==2,3==3, etc., are all true, but 1==2,2==3,3==1, are
> false. In other words identity forms an equivalence class. It's the
> equivalence class used in all of mathematics unless otherwise specified in
> the context.
You are confusing values and objects. Where class instances are
involved in Java, equality comparisons implements identity, not
equivalence. Given the following (pseudo) Java:
Integer i = 1;
Integer j = 1;
i == j is false.
This is more or less the same as C++'s:
int i = 1;
int j = 1;
&i == &j which is also false.
> But, now I ask how does C++'s overloaded '==' operator differ from Java's
> equals() in such a way as to prevent the same kinds of problems as
> described in [1]?
By applying value oriented semantics, i.e. operate on the arguments'
static type rather than on their dynamic type.
> > - finalize() : C++ has deterministic destructors, which are a far
> > superior tool.
>
> I assume that comment is in reference to Java's garbage collection? How does
> finalize() otherwise differ from the default destructors of C++?
The difference is that you know exactly when a destructor is called in
C++, while you are not even guaranteed that a finalizer will ever run
in Java.
[...]
> > The others are hashCode(), toString() and a bunch of
> > threading related methods.
>
> This is another feature I was thinking could be introduced into the core
> language through a UBC. I'm not sure of the value of having threading as a
> fundamental part of the language. I don't know the value of having a
> threaded version of the STL, or even what that would mean.
Actually I'm convinced that many commercial STL implementations
currently available *are* thread safe, as the platform they run on
support some form of multithreading. Again, I believe that a standard
approach to multithreading would be very valuable, but this doesn'tr
have anything to do with UBC's.
> > MI is a powerful tool and as it is with all powerful tools, it must be
> > handled with care. Introducing a UBC would force all kind of
> > undesirable problems, by forcing the well known "diamond of death" on
> > all multiple inheritance hyerarchies.
>
> Something tells me that could be handled through some kind of special
> provision, but I'm fairly well persuaded a UBC really isn't advisable for
> C++. I kind of hate to give up the cause so easily because I think it
> would be productive to get a lot of people looking at it. It's part of a
> bigger objective I believe is worth persuing. Determining what can be
> learned and adopted from C# and Java to add value to C++ without
> subtracting value?
I'm glad we convinced you :-)
As far as the core language is concerned, my opinion is very little:
after all those languages have mostly been devised by removing
features from C++. A more profitable endeavour would be to address
some of the features provided by those languages' standard libraries.
The immediate accessibility of C libraries has certainly been one of
C++ major asset in the past, but it probably inhibited the development
of proper C++ (standard) libraries; I'm thinking of domains such as
base OS services, networking, multithreading, graphics, etc.
> >> Here I don't follow. Can you elaborate on this? Java actually employs
> >> introspection at design time through the JavaBeans specification.
> >
> > Design time is still runtime, even though your components may do
> > different things than when your application is running. I suspect
> > you're not familiar with the template metaprogramming technique.
> > Check out [2] for a (rather tough) introduction.
>
> Sure, Ozone http://www.ozone-db.org/frames/home/what.html uses a kind of
> metaprogramming approach. Qt's moc is used to implement slots and signals
> as a form of metaprogramming. And of course, C++ has templates. I'm not
> sure how reflection plays into this. I'll admit I have not read the entire
> document you referenced. Can you tell me what parts might shed some light
> on how reflection could be useful in this area?
I'm not the most qualified person to get into details about template
metaprogramming. Maybe someone else would care to step in?
[...]
> >> The distinction is that members of the classspace would not have private
> >> or protected access to class members.
> >
> > You can achieve the same by nesting classes.
>
> I don't think that would accomplish my objective. A better solution might
> be an access specifier in addition to public, private and protected.
> Perhaps 'associated'. A function declared as associated would be resolved
> like a member function, but would not be given access to private or
> protected members. The problem would be getting people to use it
> correctly.
Are you aware of the existence of Argument Dependent Lookup, that is
that functions participate in overload resolution not only according
to the namespace they are defined in, but also according to all the
namespaces in which the function's arguments' types are defined.
Cheers,
Nicola Musatti
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Nicola.Musatti@ObjectWay.it (Nicola Musatti)
Date: Thu, 1 Apr 2004 18:15:19 +0000 (UTC) Raw View
ahp6@email.byu.edu ("Adam H. Peterson") wrote in message news:<c4feud$ea7u$1@acs2.byu.edu>...
> Steven T. Hatton wrote:
> [...]
> > But, now I ask how does C++'s overloaded '==' operator differ from Java's
> > equals() in such a way as to prevent the same kinds of problems as
> > described in [1]?
>
> Someone will probably immediately contradict me, but I think they both
> tend to have much the same problems. It is easier to overload C++'s
> equivalent mechanism for derived types, though, but that's not a
> guarantee that the base version won't still accidentally be called
> through a base interface.
Wha you can do in C++ is realize that equivalence is an operation that
is meaningful for objects with value semantics and not for objects
with pointer semantics, i.e. that the comparison should only take into
account the base subobject whose static type coincides with the
operator argument. It is then easy to implement comparisons for
subclasses in terms of the base class comparison.
Cheers,
Nicola Musatti
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hattons@globalsymmetry.com ("Steven T. Hatton")
Date: Thu, 1 Apr 2004 18:15:58 +0000 (UTC) Raw View
Nicola Musatti wrote:
> hattons@globalsymmetry.com ("Steven T. Hatton") wrote in message
> news:<SNqdnbFsCt2yMffdRVn-jA@speakeasy.net>...
>> Nicola Musatti wrote:
>>
>> > hattons@globalsymmetry.com ("Steven T. Hatton") wrote in message
> [...]
> They are different operations from a conceptual point of view. Cloning
> is polymorphic, in that the dynamic type of an object is involved. The
> result may be a shallow copy by default, but it is never sliced.
I'd have to consider what happens if I call clone through a superclass
pointer in Java. I don't know if that would effectively slice or not.
> Cloning makes sense for classes with pointer semantics, while copy
> construction mostly makes sense for objects with value semantics. As
> Java doesn't directly support classes with value semantics, cloning is
> much more important than in C++.
I'm not really sure I understand what you mean by value semantics verse
pointer semantics. From the purely conceptual reference, I will argue Java
more readily and frequently supports value semantics than does C++. This
seems somewhat off topic, so I don't want to pursue it unless it
contributes to the objective of this newsgroup. If it helps to clarify
definitions used to specify the language then it probably is worth further
discussion.
> You are confusing values and objects. Where class instances are
> involved in Java, equality comparisons implements identity, not
> equivalence. Given the following (pseudo) Java:
>
> Integer i = 1;
> Integer j = 1;
> i == j is false.
>
> This is more or less the same as C++'s:
>
> int i = 1;
> int j = 1;
> &i == &j which is also false.
Mathematically, identity forms an equivalence class over a set of enumerable
objects. That equivalence class is isomorphic to the subset of non-negative
integers with an upperbound of n where n is the number of objects. It's not
a question of confusion, it's a question of semantics. But here we are
trespassing on the ground of philosophy and fast approaching that of
religion. Let's agree to disagree on this one.
>> But, now I ask how does C++'s overloaded '==' operator differ from Java's
>> equals() in such a way as to prevent the same kinds of problems as
>> described in [1]?
>
> By applying value oriented semantics, i.e. operate on the arguments'
> static type rather than on their dynamic type.
I'm not sure such a clear distinction can be drawn. An experiment is in
order. I hypothesize that clone() can be called on a Java object's
superclass producing basically the same result as slicing in C++. C++
assignment operators can optionally be declared virtual (13.5.3.2). Doing
so will produce a result comperable to Java's clone() when called on the
most derived class of an object.
Perhaps I should run the experiment before I post this, but at some point I
have to break the infinite regression, so I'll simply post the hypothesis.
> The difference is that you know exactly when a destructor is called in
> C++, while you are not even guaranteed that a finalizer will ever run
> in Java.
The consequence of this is unclear to me. Certainly in terms of garbage
collection there is meaning, but the impact of further execution of the
program after the point at which finalize could be called is less clear.
I'm not disagreeing. I'm simply expressing ignorance of the details.
> Actually I'm convinced that many commercial STL implementations
> currently available *are* thread safe, as the platform they run on
> support some form of multithreading.
Being thread safe, and running on threaded platforms are not synonymous.
It's is possible to 'wrap' objects in synchronized objects. Thus the STL
implementation need never have threadding support incorporated. I'm not
sure it's even meaningful to talk about a thread-safe implementation of the
STL. But this again brings us to semantics.
> Again, I believe that a standard
> approach to multithreading would be very valuable, but this doesn'tr
> have anything to do with UBC's.
That is not entirely clear. There may be no necessary connection, but, as
you point out. Java does seem to leverage its UBC to support threading.
> I'm glad we convinced you :-)
> As far as the core language is concerned, my opinion is very little:
> after all those languages have mostly been devised by removing
> features from C++. A more profitable endeavour would be to address
> some of the features provided by those languages' standard libraries.
I have the sense the UBC is standing over C++ invisibly manifesting itself
in every class we create. It my be worth persuing as a metaphor if not a
design feature.
> I'm not the most qualified person to get into details about template
> metaprogramming. Maybe someone else would care to step in?
> [...]
I'm interested to know what ideas exist regarding 'compiling' templates. I
guess RT_M applies here to some extent. I have not read the section in the
Standard which discusses templates, so it may address much of what I might
have questions about. Templates are becoming more interesting to me. I'm
starting to consider how they might be used at runtime to define new
classes.
>> >> The distinction is that members of the classspace would not have
>> >> private or protected access to class members.
>> >
>> > You can achieve the same by nesting classes.
>>
>> I don't think that would accomplish my objective. A better solution
>> might be an access specifier in addition to public, private and
>> protected.
>> Perhaps 'associated'. A function declared as associated would be
>> resolved like a member function, but would not be given access to private
>> or
>> protected members. The problem would be getting people to use it
>> correctly.
>
> Are you aware of the existence of Argument Dependent Lookup, that is
> that functions participate in overload resolution not only according
> to the namespace they are defined in, but also according to all the
> namespaces in which the function's arguments' types are defined.
Is that the same as Koening Lookup? How might that apply here?
--
STH
http://www.kdevelop.org
http://www.suse.com
http://www.mozilla.org
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: austern@well.com (Matt Austern)
Date: Sun, 4 Apr 2004 17:23:47 +0000 (UTC) Raw View
susudata@setidava.kushan.aa ("Steven T. Hatton") writes:
> I also find the notion of common baseclass inheritance intuitively
> attractive. My inclination is to believe it would facilitate the
> introduction of such functionality as threading into the core language.
What do you see as the connection between threading and a common base
class? I can think of lots of languages that contain one but not the
other. (For example, pthreads work perfectly well in C.)
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: susudata@setidava.kushan.aa ("Steven T. Hatton")
Date: Thu, 25 Mar 2004 21:56:25 +0000 (UTC) Raw View
In some programming languages there is a common baseclass for all (user
defined) objects. This allows for certain functionality to be shared by all
classes. Obviously, C++ accomplishes some of this without providing a
common baseclass.
One feature which might be supported by common baseclass inheritance is
introspection. The desireability of introspection was recently discussed in
another forum. I find introspection to be useful where it is available. In
order to support introspection a per-type descriptor class would also be
implemented in the language. I believe this is the de facto practice of
most implementations, but not formally specified, or implemented. That is,
structures and data shared by objects of a common class such as member
functions or static members will be represented by a single instance. The
collection of such shared material is/could be/should be represented as a
formal object.
I also find the notion of common baseclass inheritance intuitively
attractive. My inclination is to believe it would facilitate the
introduction of such functionality as threading into the core language.
In addition to proposing a common baseclass, and a shared descriptor object
per class, I propose there be a specialized form of a namespace which would
contain only one class, and its associated helper functions. This serves
two useful purposes. First, it serves to encompass helper functions into
the OO framework. Second, it would facilitate more finegrained control over
the symbols introduced into a translation unit. A class would not be
introduced into a translation unit unless it was explicitly specified. If
the programmer felt the need to introduce all symbols from the namespace a
syntax such as:
using namespace NameSpaceName::*;
would be used.
I certainly have misgivings about the uglyness of the following part of this
suggestion, but it will serve as a first draft. I propose calling this
refinement of a namespace a 'classspace', so a class declaration might look
something like this:
namespace NameSpaceName {
classspace ClassName {
// helper functions for the class...
class ClassName { ...}
}
}
This classspace might serve the additional role of the descriptor object
mentioned above.
--
STH
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Nicola.Musatti@ObjectWay.it (Nicola Musatti)
Date: Mon, 29 Mar 2004 06:04:43 +0000 (UTC) Raw View
susudata@setidava.kushan.aa ("Steven T. Hatton") wrote in message news:<f4-dnYG_cpTgdPzdRVn-hA@speakeasy.net>...
> In some programming languages there is a common baseclass for all (user
> defined) objects. This allows for certain functionality to be shared by all
> classes. Obviously, C++ accomplishes some of this without providing a
> common baseclass.
The existence of a common base class is justified by two assumptions:
first, there is a set of operations that is necessary for all classes
and second, that these operations must be implemented by, possibly
virtual, member functions.
Personally I consider the first assumption false, and I resent such a
presumption in language designers; I much prefer the "You don't pay
for what you don't use" approach, even if it means that at times I
have more work to do.
Note that even if there was such a set of indispensable functions,
free functions and templates would probably be better means to provide
access to it.
Not to mention the fact that the existence of multiple inheritance
makes a common base class rather inconvenient.
> One feature which might be supported by common baseclass inheritance is
> introspection. [...]
Note that C++ differs from languages such as Java in that
introspection is not only desirable at runtime, but also at compile
time; even setting aside my previous objections I don't think that the
common base class would be a suitable approach for fulfilling these
goals.
> I also find the notion of common baseclass inheritance intuitively
> attractive. My inclination is to believe it would facilitate the
> introduction of such functionality as threading into the core language.
Did you learn Java as your first programming language? One reason why
I consider it unsuitable as a first language is that it instills
distorted views of the (programming) world, such as "there has to be
an ultimate base class" or "every function must belong to a class".
Inheritance is a tool. Sometimes it's useful, sometimes it isn't, and
it's important to know that it isn't universal.
> In addition to proposing a common baseclass, and a shared descriptor object
> per class, I propose there be a specialized form of a namespace which would
> contain only one class, and its associated helper functions.
A class *is* a namespace. If you really think that some "helper"
functions are tightly bound to the class, make them static members.
> This serves two useful purposes. First, it serves to encompass helper
> functions into the OO framework.
Fulfilling one's desire for aesthetic completeness is not what I
consider a compelling language design principle.
> Second, it would facilitate more finegrained control over
> the symbols introduced into a translation unit. A class would not be
> introduced into a translation unit unless it was explicitly specified. If
> the programmer felt the need to introduce all symbols from the namespace a
> syntax such as:
>
> using namespace NameSpaceName::*;
>
> would be used.
It's not clear to me what you mean.
> I certainly have misgivings about the uglyness of the following part of this
> suggestion, but it will serve as a first draft. I propose calling this
> refinement of a namespace a 'classspace', so a class declaration might look
> something like this:
>
> namespace NameSpaceName {
> classspace ClassName {
> // helper functions for the class...
> class ClassName { ...}
> }
> }
>
> This classspace might serve the additional role of the descriptor object
> mentioned above.
As I wrote above, your classspace coincides with the class, so it's
not necessary.
Cheers,
Nicola Musatti
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: no@spam.for.me.invalid (Nils Petter Vaskinn)
Date: Mon, 29 Mar 2004 18:09:23 +0000 (UTC) Raw View
On Thu, 25 Mar 2004 21:56:25 +0000, Steven T. Hatton wrote:
> In some programming languages there is a common baseclass for all (user
["mother of all classes" in C++]
One better option (IMHO) is to have a std::object (or something) that has
the "most wanted" functions of a common baseclass. The language should not
require people to use this class, and the std::* classes should probably
not use them either.
So (you may ask) what is the point? If you have two libraries A and B that
use tha common base class principle they can have _the same_ common base
class, and this may make it easier if your program uses both libraries.
--
NPV
"the large print giveth, and the small print taketh away"
Tom Waits - Step right up
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: hattons@globalsymmetry.com ("Steven T. Hatton")
Date: Mon, 29 Mar 2004 18:41:50 +0000 (UTC) Raw View
Nicola Musatti wrote:
> susudata@setidava.kushan.aa ("Steven T. Hatton") wrote in message
> news:<f4-dnYG_cpTgdPzdRVn-hA@speakeasy.net>...
>> In some programming languages there is a common baseclass for all (user
>> defined) objects....
> The existence of a common base class is justified by two assumptions:
> first, there is a set of operations that is necessary for all classes
> and second, that these operations must be implemented by, possibly
> virtual, member functions.
>
> Personally I consider the first assumption false, and I resent such a
> presumption in language designers; I much prefer the "You don't pay
> for what you don't use" approach, even if it means that at times I
> have more work to do.
This whole proposal grew out of a moment of seeming clarity I experienced
while reading the last chapters in the core language part of TC++PL(SE). I
tried to discuss it in another news group and people complained it was off
topic, and suggested I take the topic here. As for presumptuousness, it's
probably more presumptuous of me to believe I have /any/ valuable insight
into how to improve C++.
But let me ask this: In view of how a UBC (universal base class) is employed
in languages such as Java and C# (I know very little about C#), are there
any properties potentially valuable to a significant portion of the classes
commonly used by C++ programmers? IOW, *_IF_*, there were a UBC in C++,
what would you suggest putting there? Addressing this question may lead to
valuable insight regardless of whether a UBC is ever added to C++.
> Note that even if there was such a set of indispensable functions,
> free functions and templates would probably be better means to provide
> access to it.
You raise an interesting issue regarding templates. I'm wondering how many
problems would arise with templates when trying to incorporate a UBC into
the language. As for free functions, that would be addressed by my
follow-on proposal regarding the use of the global namespace as the
proto-object.
> Not to mention the fact that the existence of multiple inheritance
> makes a common base class rather inconvenient.
I've been told by others this represents a problem, but I'm not sure what
the problem actually is. How does the introduction of a UBC make MI
(Multiple Inheritance) more problematic than it already is?
>> One feature which might be supported by common baseclass inheritance is
>> introspection. [...]
>
> Note that C++ differs from languages such as Java in that
> introspection is not only desirable at runtime, but also at compile
> time;
Here I don't follow. Can you elaborate on this? Java actually employs
introspection at design time through the JavaBeans specification.
> even setting aside my previous objections I don't think that the
> common base class would be a suitable approach for fulfilling these
> goals.
The goal of providing introspection? That seems to be contingent on the
question of whether it's desireable to have universally available
introspection.
>> I also find the notion of common baseclass inheritance intuitively
>> attractive. My inclination is to believe it would facilitate the
>> introduction of such functionality as threading into the core language.
>
> Did you learn Java as your first programming language?
No. The first programming language I learned was the Basic available on an
Apple 3e. I have not been programming on a continuous basis for the last
20 years - contrary to what that might suggest. I've also used Pascal, C,
ADA, Mathematica, Lisp, and a few others.
> One reason why
> I consider it unsuitable as a first language is that it instills
> distorted views of the (programming) world, such as "there has to be
> an ultimate base class" or "every function must belong to a class".
I am far more inclined to dispense with the former than the latter. (User
defined) free functions are almost as bad as global variables. Just today
I encountered a situation where the reuse of good C++ code was encumbered
because it had been written in the global namespace using the style of C.
> Inheritance is a tool. Sometimes it's useful, sometimes it isn't, and
> it's important to know that it isn't universal.
This I understand. I've actually been looking into the impact on the
so-called concrete classes of having a UBC. If the UBC required every
object to hold a vtbl pointer, that could have enormous consequences on the
memory required by a program using concrete classes. I actually suggested
splitting struct off from the UBC hierarchy to maintain support for
concrete classes.
>> In addition to proposing a common baseclass, and a shared descriptor
>> object per class, I propose there be a specialized form of a namespace
>> which would contain only one class, and its associated helper functions.
>
> A class *is* a namespace. If you really think that some "helper"
> functions are tightly bound to the class, make them static members.
Stroustrup argues against that approach. He suggests that helper functions
that don't need access to member variables should not be members of the
class. This is discussed in 10.3.2 of TC++PL(SE). Ironically, at the end
of the first paragraph in that section I noted as follows:"Get over it!
Make them static". At that time I had failed to appreciate his argument.
>> This serves two useful purposes. First, it serves to encompass helper
>> functions into the OO framework.
>
> Fulfilling one's desire for aesthetic completeness is not what I
> consider a compelling language design principle.
Please consider my previous comment.
>> using namespace NameSpaceName::*;
>>
>> would be used.
>
> It's not clear to me what you mean.
I find the current namespace model rather messy. I don't like the way using
one namespace in another introduces a union of all symbols from both
namespaces present in the translation unit into a third namespace that uses
it. My suggestion was meant as a means of limiting what comes into a
namespace with a using directive. The current form of the directive would
only bring in 'global' symbols of the namespace.
> As I wrote above, your classspace coincides with the class, so it's
> not necessary.
The distinction is that members of the classspace would not have private or
protected access to class members.
Note: yes the word classspace is ugly; classroom? :-o
--
STH
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]
Author: ahp6@email.byu.edu ("Adam H. Peterson")
Date: Mon, 29 Mar 2004 23:34:14 +0000 (UTC) Raw View
>>One reason why
>>I consider it unsuitable as a first language is that it instills
>>distorted views of the (programming) world, such as "there has to be
>>an ultimate base class" or "every function must belong to a class".
>
>
> I am far more inclined to dispense with the former than the latter. (User
> defined) free functions are almost as bad as global variables. Just today
> I encountered a situation where the reuse of good C++ code was encumbered
> because it had been written in the global namespace using the style of C.
I've seen the other situation. Code reuse was impaired because a
function was tethered to a class as a member function and was difficult
to overload or refactor. I think it's best to put functions in
namespaces unless there are design reasons they should be members. But
IME it's easier to move a global function into a namespace than it is to
refactor a member function to be a nonmember function even though it
didn't need to be a member function in the first place. (I usually
employ namespaces at the module level, rather than the class level.)
---
[ 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://www.jamesd.demon.co.uk/csc/faq.html ]