Hypothetical: All code in classes but main()

J

Juha Kettunen

Steven T. Hatton said:
This is a purely *hypothetical* question. That means, it's /pretend/,
CP. ;-)

If you were forced at gunpoint to put all your code in classes, rather than
in namespace scope (obviously classes themselves are an exception to this),
and 'bootstrap' your program by instantiating a single application object
in main(), would that place any limitations on what you could accomplish
with your program? Are there any benefits to doing things that way (other
than survival)?

BTW, yes, I /do/ favor this approach.

wow, finally I meet somebody who likes (c++) classes like me :). I am "with
you" ... I never really liked that c-style programming, if you can do the
same thing with classes, but this just my opinion and taste - I am not
saying, that I have the truth in this issue. Maybe its like that somebody
likes tea, but somebody else might hate tea but like coffee :).

I dont see eny limitations in "normal programming" - I would defenitely
choose class route if possible . I was jus thinking, that some very critical
fast code might need pure c-code because of efficiency. For example in chess
game programming you calculate 2 000 000 moves per second, so classes might
not be suitable in all programming because they might be a little bit too
slow ... but to be honest with you, I am not sure of this ... Does somebody
know if this is true or not?
 
S

Steven T. Hatton

This is a purely *hypothetical* question. That means, it's /pretend/,
CP. ;-)

If you were forced at gunpoint to put all your code in classes, rather than
in namespace scope (obviously classes themselves are an exception to this),
and 'bootstrap' your program by instantiating a single application object
in main(), would that place any limitations on what you could accomplish
with your program? Are there any benefits to doing things that way (other
than survival)?

BTW, yes, I /do/ favor this approach.
 
J

Jeff Schwab

Steven said:
This is a purely *hypothetical* question. That means, it's /pretend/,
CP. ;-)

If you were forced at gunpoint to put all your code in classes, rather than
in namespace scope (obviously classes themselves are an exception to this),
and 'bootstrap' your program by instantiating a single application object
in main(), would that place any limitations on what you could accomplish
with your program? Are there any benefits to doing things that way (other
than survival)?

BTW, yes, I /do/ favor this approach.

I almost always have a single object to represent the whole application,
and use main() only as an entry point. That said, forcing _everything_
into classes seems to disallow use of some of my favorite C++ features
and programming styles. For example, many operator overloads belong
outside the class.

template< typename T >
int add_one( T const& t )
{
return 1 + t; // If T is a UDT, where is operator + defined?
}
 
M

Mark A. Gibbs

I normally don't jump into hypothetical discussions like this, but parts
of this just rankled me.

Juha said:
[snip]
If you were forced at gunpoint to put all your code in classes, rather
than

in namespace scope (obviously classes themselves are an exception to
this),

and 'bootstrap' your program by instantiating a single application object
in main(), would that place any limitations on what you could accomplish
with your program? Are there any benefits to doing things that way (other
than survival)?

Personally, I can see no practical functional limitations or benefits.

[snip]
I dont see eny limitations in "normal programming" - I would defenitely
choose class route if possible . I was jus thinking, that some very critical
fast code might need pure c-code because of efficiency. For example in chess
game programming you calculate 2 000 000 moves per second, so classes might
not be suitable in all programming because they might be a little bit too
slow ... but to be honest with you, I am not sure of this ... Does somebody
know if this is true or not?

Where this whole thing starts to spiral out of control is here. "C-code"
by itself is no slower or faster than the equivalent "C++-code" (ie,
class-based code). If you wanted to, you could write "slow" or "fast"
code in either. In fact, writing the theoretical "fastest" program is
possible in C and C++ - your compiler and your algorithm are what
determine how "fast" your code will run.

For the record, I make games, and I need "efficient" code to move big
chunks of data around very quickly. I use classes with impunity - the
things I usually watch for are polymorphism and virtual functions, and
hidden code (destructors and constructors that aren't immediately
obvious). And even these I use in some cases.

But being told to put all your code into classes is as illogical to me
as being told to use only words and phrases from Shakepeaean iambic
pentameter as variable names. Or, more practically but no less obtuse,
hungarian notation. Does it help anything? Not really. Does it hurt
anything? Not really. And if it does either it does them in equal
measure. So why insist on it?

I mean, compare the elegance of this:

int max(int a, int b) { return (a > b) ? a : b; }

int larger = max(1, 2);

To this:

class Math
{
public:
static int max(int a, int b) { return (a > b) ? a : b; }
};

int larger = Math::max(1, 2);

Only Java programmers could find the latter more legible.

Both can run just as fast (if you inline the former; the latter is
intrinsically inlined), so it's not a speed issue. Namespace Math::max
provides (essentially) the same amount of collision protection and
encapsulation as class Math::max, so it's not a maintennance issue.

What it is, is a design issue. What you're telling me is that there are
such things as "Math" objects. In order to find the max of two numbers,
I have to go get a "Math" and use the "Math"'s "max" operation. Or, in
the static case, that "Math"'s have a behaviour or mechanism that is not
specific to any one "Math", but is nonetheless "Math" object-specific
behaviour.

On the other hand, the free function tells me that "max" is an operation
in category (ie, namespace) "Math". In other words, "max" is a "Math"
operation.

Doesn't the latter just make more sense?

So in conclusion, what the hell are the benefits of such arbitrary
constraints? Write your program so that it makes logical sense and
models the problem it is trying to solve as closely as possible. If the
language has the tools, and if they don't lead to bad design and
maintennance problems, use them.

If you really feel the need to apply arbitrary constraints, why not
write your code in morse code ( http://www.ioccc.org/1986/hague.c )?

mark
 
S

Steven T. Hatton

Jeff said:
I almost always have a single object to represent the whole application,
and use main() only as an entry point. That said, forcing _everything_
into classes seems to disallow use of some of my favorite C++ features
and programming styles. For example, many operator overloads belong
outside the class.

template< typename T >
int add_one( T const& t )
{
return 1 + t; // If T is a UDT, where is operator + defined?
}

I believe there is actually a technical limitation met when binary operators
(ones that take two arguments) are forced to be class members. I need to
review the section, but I believe there are some symmetries that are lost.
IOW A@B works but B@A doesn't for cases such as '+' and '*'. Another
problem is the fact that functions which were external to a class now gain
access to member data and potentially become bound to it. This is the
argument Stroustrup gives for having helper functions at namespace scope.

I actually proposed another access specifier in addition to private,
protected, public and firend. I suggested /associated/ which would allow a
function to be a member, but it would only have access to public members of
its own class.
 
S

Steven T. Hatton

Mark said:
I normally don't jump into hypothetical discussions like this, but parts
of this just rankled me.

Juha Kettunen wrote: [snip]

Personally, I can see no practical functional limitations or benefits.

I believe there actually are two. I already mentioned them in another post
in this thread.
Where this whole thing starts to spiral out of control is here. "C-code"
by itself is no slower or faster than the equivalent "C++-code" (ie,
class-based code). If you wanted to, you could write "slow" or "fast"
code in either. In fact, writing the theoretical "fastest" program is
possible in C and C++ - your compiler and your algorithm are what
determine how "fast" your code will run.

As you correctly pointed out below, virtual function calls have some
overhead beyond static calls. A static call to a member should be just as
fast as a global 'C'-style call, as far as I know.
But being told to put all your code into classes is as illogical to me
as being told to use only words and phrases from Shakepeaean iambic
pentameter as variable names. Or, more practically but no less obtuse,
hungarian notation. Does it help anything? Not really. Does it hurt
anything? Not really. And if it does either it does them in equal
measure. So why insist on it?

One argument would be for the sake of uniformity. But I guess that's just
the soldier in me talking.
int larger = Math::max(1, 2);

Only Java programmers could find the latter more legible.

There are advantages to having the static Math class in Java. It provides
for an easy point of reference. It's kind of like having a directory
structure and using it to organize your data. Personally, the following is
my idea of what a more complete set of mathematical operators looks like in
a programming language. But MMA is a specialized language:

http://documents.wolfram.com/v5/TheMathematicaBook/MathematicaReferenceGuide/InputSyntax/A.2.7.html
Both can run just as fast (if you inline the former; the latter is
intrinsically inlined), so it's not a speed issue. Namespace Math::max
provides (essentially) the same amount of collision protection and
encapsulation as class Math::max, so it's not a maintennance issue.

Other than the fact that people tend to be sloppy with namespaces.
What it is, is a design issue. What you're telling me is that there are
such things as "Math" objects.

No. It's saying there are mathematical operators which can be classified as
such.
In order to find the max of two numbers,
I have to go get a "Math" and use the "Math"'s "max" operation. Or, in
the static case, that "Math"'s have a behaviour or mechanism that is not
specific to any one "Math", but is nonetheless "Math" object-specific
behaviour.

You don't instantiate Math. It is a utilities class.
On the other hand, the free function tells me that "max" is an operation
in category (ie, namespace) "Math". In other words, "max" is a "Math"
operation.

And how does this differ from Java's use of a class where you use a
namespace?
Doesn't the latter just make more sense?

It depends how it's managed. Java takes the functional operator approach to
mathematical syntax, whereas C++ allows for infix notation. I find that
far more significant in terms of how it 'feels' to use. An interesting
parallel to this is found in Misner, Thorne and Wheeler's _Gravitation_
where three notational forms are used in parallel through out the text:

http://www.reviewcentre.com/review57645.html
So in conclusion, what the hell are the benefits of such arbitrary
constraints? Write your program so that it makes logical sense and
models the problem it is trying to solve as closely as possible. If the
language has the tools, and if they don't lead to bad design and
maintennance problems, use them.

Actually, this was a hypothetical proposition. One reason for putting
everything in classes is that it usually makes refactoring easier (with the
possible exception of helper functions), and also makes reuse easier.
 
M

Mark A. Gibbs

Steven said:
I believe there actually are two. I already mentioned them in another post
in this thread.

Two what? Limitations or benefits? Are you referring to your comments on
assymetrical binary operations? That is not a design issue, that's an
implementation issue. If you want an operation a @ b to be valid for
objects of type A and B in any order you either have to define
operator@(A) in B and operator@(B) in A (thus coupling the two), or
define operator@(B) in A and operator@(A,B) globally (still coupling the
two), or define operator@(A,B) and operator@(B,A) globally (leaving the
classes uncoupled). To me, this *supports* non-class functions.

But whatever you decide out of the above options, you are limited by the
language. you could write add(A,B) and add(B,A) as class members (of
either class) with no problems. If you are talking about limitations of
possible implementations due to constraints of the language, count me
out. I have no intention of discussing alterations to the language. I
was talking about limitations on possible designs and program structures.

Your second argument, if I understood it, makes no sense. "Another
problem is the fact that functions which were external to a class now
gain access to member data and potentially become bound to it. This is
the argument Stroustrup gives for having helper functions at namespace
scope." So does that support your argument or not?

If a function requires access to member data, then by all means make it
a member function. But static functions can't access member data, now
can they? If they require access to static data, well that's different.
But if you have a function that does not require instance-specific data,
and does not require a class-global data (such as max()), you can choose
to use either a static member function or a non-class function without
concern.
As you correctly pointed out below, virtual function calls have some
overhead beyond static calls. A static call to a member should be just as
fast as a global 'C'-style call, as far as I know.

That is the idea. It is possible for a theoretical implementation to do
something different, I suppose, but for all practical purposes it is
safe to assume that the only functional difference between a global
function and a class static function is that that the class static
function has access to private and protected class static data and
functions.

So in the context of this discussion, there are no performance differences.
One argument would be for the sake of uniformity. But I guess that's just
the soldier in me talking.

Being a former soldier myself, I should point out that while uniformity
is generally a good thing, there are many different types of soldiers,
some specializing in airborne drops, some specializing in beach
landings, not to mention the wildly varying trades like pilots,
artillery, armoured, mechanized infantry etc. etc. etc.

By all means, be uniform, but if the job calls for artillery, don't send
in the infantry.
There are advantages to having the static Math class in Java. It provides
for an easy point of reference. It's kind of like having a directory
structure and using it to organize your data. Personally, the following is

?

You could replace "static Math class in Java" with "Math namespace in
C++" in your statement, and it would still be valid. The *only* reason
there is a static Math class in Java (as opposed to a Math namespace) is
that Java does not support free functions.

Given that C++ has the option, what are the advantages here?
Other than the fact that people tend to be sloppy with namespaces.

People can be just as sloppy with anything in C++, and it's usually the
same people. Is there any emperical evidence that people tend to
sloppiness when namespaces are introduced?

But let me give the benefit of the doubt and ask sloppy in what way?
No. It's saying there are mathematical operators which can be classified as
such.

Yes, but there are many ways of doing this in C++. You could use a
"Math" class, or you could use a "Math" namespace, or you could prefix
global functions with "Math_". Each of these methods groups certain
operations together, and each tell me different things about that
grouping. The class tells me that "Math"'s are things, ie, objects -
it's not called object-oriented programming for giggles - just like
class Student, class smart_ptr_policy or class ifstream. The namespace
tells me that these functions are conceptually grouped in some way, but
otherwise gives me no further indications of how - which is fine, all I
really need to understand is that they are all "Math" functions.

The last? I guess it just tells me that someone's a rotten programmer,
unless they have a better excuse.
You don't instantiate Math. It is a utilities class.

Of course I understand that, it was my argument after all. But a class
describes a (surprise, surprise) class of objects. The ONLY valid
reasons I can think of for having a non-instantiable (static) class is
when that body of operations MUST NOT be extended, and/or they all make
use of some kind of private data/algorithms that MUST NOT be visible to
the rest of the program. There are plenty of situations that satisfy
those constraints. I don't believe max() (or sin(), or round() etc.)
does. Explain to me why you do.
And how does this differ from Java's use of a class where you use a
namespace?

? what do you mean "Java's use of a class where you use a namespace"?

[Taking a guess at what you meant]

As I mentioned before, Java has no choice but to do max() with static
class members. You have a choice in C++.

Let me make this absolutely clear. I believe there is no difference
between designs that use non-class-functions and those that do in terms
of functionality, efficiency and maintainability. If anyone disagrees,
let me know. As far as I'm concerned this discussion is over the
benefits of Class::function() vs. Namespace::function(), and nothing more.

So to answer what I think your question was: it doesn't. It's the same
damn thing. There are no functional benefits either way.

But to me at least, you are making a statement when you create a class
vs. a namespace. A class describes a "thing", an object. A namespace
describes a group. To me, mathematical operations can be grouped. But a
"Math" doesn't have a "cosh()" capability. This is the basis of my
argument for putting these functions in namespaces as opposed to classes.

On the other hand, if I were to create a MemoryManager that was static
(non-instantiable), that's a different story. A "MemoryManager" is a
thing, an object. By making it a static class, I am making clear that
there is only one MemoryManager available, and you are not responsible
for creating or destroying it. Likewise, you are not to add functions to
it (make your own damn MemoryManager). It is a single, global interface
to some hidden memory system that needs managing. The static functions
in that class provide some operation or functionality of this monolithic
MemoryManager thing. Things like allocate(), get_free_memory(). That is
the language of objects.

Do not try to bend the Math into an object. That is impossible. Instead,
try to remember the truth.

There is no Math.
It depends how it's managed. Java takes the functional operator approach to
mathematical syntax, whereas C++ allows for infix notation. I find that
far more significant in terms of how it 'feels' to use. An interesting
parallel to this is found in Misner, Thorne and Wheeler's _Gravitation_
where three notational forms are used in parallel through out the text:

http://www.reviewcentre.com/review57645.html

wha?

[Attempting to decode]

If you prefer to use functional notation as opposed to operators, go
nuts. I think a + b is more understandable than operator+(a, b), but
hey, that's me.

But how is any of that relevant to keeping all the code in classes?
Actually, this was a hypothetical proposition. One reason for putting
everything in classes is that it usually makes refactoring easier (with the
possible exception of helper functions), and also makes reuse easier.

I understand that it was hypothetical, so was my proposed "morse coding
standard". I am learning here, too. If you can convince me that
class-only design is better in some way than using global functions, I
may change my evil ways. But so far, all I have seen are wishy-washy
pseudo-statements like "the 'fact' that people *tend* to be *sloppy*
with namespace" or "putting everything in classes is that it *usually*
makes refactoring *easier*" (emphasis added in all cases), or assertions
to the tune of "that's how Java does it, so it must be good".

So tell me what you mean by "easier" refactoring or reuse, and how a
collection of static class functions makes this possible over a namespace.

For the record, Java is designed to run in distributed and network
environments. Because of the constraints of this environment, everything
*has* to be a class. They didn't make class Math cause it was a good
idea. They did it cause they needed the functions and had no other way
to make them.

But is it a good idea? I don't know, but I don't think so. Explain to me
why I might be wrong.

mark
 
J

Jeff Schwab

Steven said:
I actually proposed another access specifier in addition to private,
protected, public and firend. I suggested /associated/ which would allow a
function to be a member, but it would only have access to public members of
its own class.

What purpose would that serve?
 
S

Steven T. Hatton

Mark said:
If you want an operation a @ b to be valid for
objects of type A and B in any order you either have to define
operator@(A) in B and operator@(B) in A (thus coupling the two), or
define operator@(B) in A and operator@(A,B) globally (still coupling the
two), or define operator@(A,B) and operator@(B,A) globally (leaving the
classes uncoupled). To me, this *supports* non-class functions.

My point exactly. Though I'm not sure there isn't a third approach which
might actually address the situation better than either of the two shown
above.
Your second argument, if I understood it, makes no sense. "Another
problem is the fact that functions which were external to a class now
gain access to member data and potentially become bound to it. This is
the argument Stroustrup gives for having helper functions at namespace
scope." So does that support your argument or not?

Yes it supports the point I was making.
If a function requires access to member data, then by all means make it
a member function. But static functions can't access member data, now
can they?

Of course they can.
That is the idea. It is possible for a theoretical implementation to do
something different, I suppose, but for all practical purposes it is
safe to assume that the only functional difference between a global
function and a class static function is that that the class static
function has access to private and protected class static data and
functions.

A static function has access to all member data. Am I missing something
here? I only have a couple months of real C++ experience, so I may have
misunderstood something, but I'm almost certain a static member function
can access all member data of instances of the class.
Being a former soldier myself, I should point out that while uniformity
is generally a good thing, there are many different types of soldiers,
some specializing in airborne drops, some specializing in beach
landings, not to mention the wildly varying trades like pilots,
artillery, armoured, mechanized infantry etc. etc. etc.

But there are certain attributes every solder shares with all others.
Ironically, the model I used for notions of inheritance when first learning
about the concepts of OO was the military organizational structure. There
were no OO programming languages available to the average user at the time.

If you have a reasonably good IDE its very easy to type:
java.[get a listing of available packages and classes]

select

java.Math.[get a listing of available members with their type displayed]

select what you want.

If you don't like the fully qualified name in the body of your source, just
type /Math.operation(arguments)/, highlight it (it will be displayed with
an indication that the IDE doesn't know about /Math/) hit a specific key
combination to invoke the display of all candidates available in your
classpath. Select java.lang.Math from the list, and it is #imported in the
heading of the source file.

If you don't have an IDE just use bash to hook into the same support
features the IDE uses to search the classpath, and to display member
signatures, etc. It's a bit more work, but with a few scripts, it really
is quite easy.
You could replace "static Math class in Java" with "Math namespace in
C++" in your statement, and it would still be valid. The *only* reason
there is a static Math class in Java (as opposed to a Math namespace) is
that Java does not support free functions.

One might argue that the real difference is that in Java you have another
level of encapsulation. I find 'free' functions to be of questionable
value. Some people seem to think of them as global functions.
Given that C++ has the option, what are the advantages here?

Perhaps. There is the advantage of predictability. That is, since there
are fewer options, it's easier to determine how something is structured.
It also enforces certain structural rules that programmers might otherwise
violate.
People can be just as sloppy with anything in C++, and it's usually the
same people. Is there any emperical evidence that people tend to
sloppiness when namespaces are introduced?

The STL.
But let me give the benefit of the doubt and ask sloppy in what way?


Yes, but there are many ways of doing this in C++. You could use a
"Math" class, or you could use a "Math" namespace, or you could prefix
global functions with "Math_".

And (some) C++ programmers believe the last is a viable option.
Each of these methods groups certain
operations together, and each tell me different things about that
grouping. The class tells me that "Math"'s are things, ie, objects -
it's not called object-oriented programming for giggles - just like
class Student, class smart_ptr_policy or class ifstream. The namespace
tells me that these functions are conceptually grouped in some way, but
otherwise gives me no further indications of how - which is fine, all I
really need to understand is that they are all "Math" functions.

But when you have disorganized your collection of operators as described
above, it is more difficult to work with. As far as OO goes, if you really
understand what Java is doing, you would understand that it is very much OO
to do things that way. But even if you only look at the surface, there is
nothing non-OO about using utilities classes. It's just another way of
using tools effectively.
Of course I understand that, it was my argument after all. But a class
describes a (surprise, surprise) class of objects.

So if there is only one instance of a class, does that mean OO has been
missused? I find that argument against the use of the Math class to be
silly. Ever wonder why the German cognate for the English /dish/ means
table? There is a lesson there.
The ONLY valid
reasons I can think of for having a non-instantiable (static) class is
when that body of operations MUST NOT be extended, and/or they all make
use of some kind of private data/algorithms that MUST NOT be visible to
the rest of the program.

I tend to believe the onus falls in the other direction as far as the
visibility of data. But that's just what the standard texts on OO say.
As I mentioned before, Java has no choice but to do max() with static
class members. You have a choice in C++.

One might argue that you have the illusion of choice in C++. How many
main() functions can exist in a C++ program? How do you specify the
namespace for that function? That sounds like a restraction, not a liberty
to me.
Let me make this absolutely clear. I believe there is no difference
between designs that use non-class-functions and those that do in terms
of functionality, efficiency and maintainability. If anyone disagrees,
let me know. As far as I'm concerned this discussion is over the
benefits of Class::function() vs. Namespace::function(), and nothing more.

That was what I was intending in the immediate discussion. My inclination is
to view namespaces as fairly unstructured in comparison to classes.
So to answer what I think your question was: it doesn't. It's the same
damn thing. There are no functional benefits either way.

But to me at least, you are making a statement when you create a class
vs. a namespace. A class describes a "thing", an object. A namespace
describes a group. To me, mathematical operations can be grouped. But a
"Math" doesn't have a "cosh()" capability.

I could be argued that /a/ math does have a cosine. But I would tend to
argue that for practical purposes, there is only one (singleton) math.
Math /is/ actually instantiated implicitly in Java.
Do not try to bend the Math into an object. That is impossible. Instead,
try to remember the truth.

I don't find that to be a compelling argument. The name Math is just a
shorthand for mathematical utilities. It works reasonably well. I was
horrified when I first saw Java's vecmath (well actually it took a few days
for the horror to sink in). There are some things that are simply awkward
in it. Operator overloading would, perhaps, be a welcome enhancement, but
when I simply accepted it for what it was, a lot of the superficial
objections came to appear irrelevant.
There is no Math.

I sure have a lot of math books about nothing then.
It depends how it's managed. Java takes the functional operator approach
to
mathematical syntax, whereas C++ allows for infix notation. I find that
far more significant in terms of how it 'feels' to use. An interesting
parallel to this is found in Misner, Thorne and Wheeler's _Gravitation_
where three notational forms are used in parallel through out the text:

http://www.reviewcentre.com/review57645.html

wha?

[Attempting to decode]

If you prefer to use functional notation as opposed to operators, go
nuts. I think a + b is more understandable than operator+(a, b), but
hey, that's me.

Yup, you understood the intent. There are some advantages to the functional
operator approach to mathematical symbolism.
I understand that it was hypothetical, so was my proposed "morse coding
standard".

Can you provide an example of a successfull general purpose programming
language that used such an approach?
I am learning here, too. If you can convince me that
class-only design is better in some way than using global functions,

I could rest my case right here.
So tell me what you mean by "easier" refactoring or reuse, and how a
collection of static class functions makes this possible over a namespace.

If you read my comment about namespaces you may notice I already addressed
that. But, namespaces do have on additional drawback in that they are can
easily be concatanated, sometimes in less than obvious ways.
For the record, Java is designed to run in distributed and network
environments. Because of the constraints of this environment, everything
*has* to be a class. They didn't make class Math cause it was a good
idea. They did it cause they needed the functions and had no other way
to make them.

I'm not sure of all the cause and effect, but, yes, Java pretty much forces
the creation of Math. There, of course, are a few alternatives, such as
making a class for each operator, or for some subset of operators. I'll
grant that Java lacks a lot of the available finesse in C++. But that
feature of C++ comes at a cost.
 
S

Steven T. Hatton

Jeff said:
What purpose would that serve?

Binding a helper function to a class, and still exclude it from protected
and private access to data members.
 
D

David Harmon

On Sat, 10 Apr 2004 17:47:46 GMT in comp.lang.c++, "Mark A. Gibbs"
int larger = Math::max(1, 2);

Only Java programmers could find the latter more legible.

Yes, obviously should be

int larger = std::max(1, 2);
 
A

Alf P. Steinbach

* "Steven T. Hatton said:
If you were forced at gunpoint to put all your code in classes, rather than
in namespace scope (obviously classes themselves are an exception to this),
and 'bootstrap' your program by instantiating a single application object
in main(), would that place any limitations on what you could accomplish
with your program?

Yes, AFAIK you cannot put 'extern "C"' in a class, which severely limits
what you can then accomplish with only standard C++.

Apart from that there are issues of design (information hiding) and of
practical stuff like binary operators. Although that doesn't limit what
your executable code can accomplish it limits the usability of that code
in client code, and it impacts negatively on maintainance & performance.

Are there any benefits to doing things that way (other than survival)?

In a real world project much of the grunt work is typically done by less
experienced programmers, who tend to use static storage and namespace scope
functions unless forbidden. As an example, in one mainly Java project many
classes were designed as singletons using static storage for the instances.
That created problems in performance testing where a large number of logins
to the system had to be simulated using threads instead of processes.
 
S

Steven T. Hatton

David said:
On Sat, 10 Apr 2004 17:47:46 GMT in comp.lang.c++, "Mark A. Gibbs"


Yes, obviously should be

int larger = std::max(1, 2);

Hey! Whose side are you on here?
 
J

Jeff Schwab

Steven said:
Jeff Schwab wrote:




Binding a helper function to a class, and still exclude it from protected
and private access to data members.

A function doesn't need to be a member of a class to be associated with
it. Just declare the function in the same namespace as the class, but
outside the definition.

class C { /* ... */ };

void helper_function( C const& );
 
S

Steven T. Hatton

Jeff said:
A function doesn't need to be a member of a class to be associated with
it. Just declare the function in the same namespace as the class, but
outside the definition.

class C { /* ... */ };

void helper_function( C const& );

Well, sure. But then we have people running around thinking of namespace
scope as 'global' and doing unconscionable things such as using::std at
global scope.

Your example is exactly the functionality I was trying to preserve while
more tightly associating the helper function with the specific class. The
idea of having a bunch of classes at namespace scope and a bunch of helper
functions which apply to one or some, but not all the classes seems
unstructured to me.

Certainly if care is taken in naming and choosing members of the namespace,
it is workable. But, from what I've seen, programmers often start grouping
things with category_subcategory_type names. These should more correctly be
category::subcategory::type.
 
J

Jeff Schwab

Steven said:
Jeff Schwab wrote:




Well, sure. But then we have people running around thinking of namespace
scope as 'global' and doing unconscionable things such as using::std at
global scope.

I don't follow your logic. Using namespaces to group related functions
and classes doesn't cause people to misunderstand namespaces. In fact,
this is exactly the canonical usage.

You can't prohibit people from abusing "using" directives. Your
approach prohibits clients placing them even within a single function;
isn't that throwing the baby out with the bath water? Anyway, trying to
prevent your clients from using common coding styles you don't like
seems a little pedantic. It's important to support clients by providing
structure, but it's equally important to respect them, and to allow
flexibility.
Your example is exactly the functionality I was trying to preserve while
more tightly associating the helper function with the specific class. The
idea of having a bunch of classes at namespace scope and a bunch of helper
functions which apply to one or some, but not all the classes seems
unstructured to me.

But changing the word "namespace" to "class" would fix the perceived
problem?
Certainly if care is taken in naming and choosing members of the namespace,
it is workable. But, from what I've seen, programmers often start grouping
things with category_subcategory_type names. These should more correctly be
category::subcategory::type.

How would grouping items in classes instead of namespaces change this?
 
S

Steven T. Hatton

Jeff said:
Steven T. Hatton wrote:

I don't follow your logic. Using namespaces to group related functions
and classes doesn't cause people to misunderstand namespaces. In fact,
this is exactly the canonical usage.

First off I meant to write /using namespace std;/ My brain does weird stuff
like that.

It's ok if used frugally. I still find it to be a bit too permissive and
unstructured.
You can't prohibit people from abusing "using" directives. Your
approach prohibits clients placing them even within a single function;

No. I didn't suggest doing away with them completely. I don't like the way
they concatonate and did make a few whimsical suggestions in that
direction,
isn't that throwing the baby out with the bath water? Anyway, trying to
prevent your clients from using common coding styles you don't like
seems a little pedantic. It's important to support clients by providing
structure, but it's equally important to respect them, and to allow
flexibility.

I wasn't really thinking in those terms. I was just trying to determine
what the technical implications, pro and con, of the all objects approach
are. I'm not even thouroughly convinced there would be that much
difference if namespaces were completely removed from the language, and in
their place people used classes. I'm not suggesting that be done, but I am
suggesting that it is a worthwhile thought experiment.
But changing the word "namespace" to "class" would fix the perceived
problem?

What I'm saying is that, for example, ::std is a collection of templates
(which I intended as well when I wrote 'class' and 'function') with only
the fact that they are part of the Standard Library as a common
characteristic. Yes, one purpose for namespaces is simply a mechanism for
avoiding name collisions. But limiting their use to that goal puts us back
in the same fix of having a bunch of unrelated entities all laying around
on a common floor.

Changing the name would not necessarily fix the problem. Disallowing
functions at namespace scope, however, would be an interesting exercise.
How would grouping items in classes instead of namespaces change this?

It was really a suggestion of how to address my concerns /without/ putting
everything in namespaces. I do believe having a rule of thumb that
everything that could be in a class should be in a class would lead to
tighter designs with cleaner demarkation.
 
S

Steven T. Hatton

Steven said:
It was really a suggestion of how to address my concerns /without/ putting
everything in namespaces.
replace namespaces with class. I'm having one of those days! :-/
 
M

Mark A. Gibbs

Steven said:
Yes it supports the point I was making.

What point? And supports it how? It still makes no sense to me.

I mean, this is how I look at it. If I have a class Foo and a function
bar(), there is no coupling unless there needs to be, and if there needs
to be a relationship, there needs to be a relationship.
Of course they can.

I did not say class static functions, I said static functions, which is
equivalent to globabl functions. I was being very careful not to do this
in order to not muddy the waters, but this one slipped by.

Globabl functions cannot access member data. So there is no imperative
to make them members. It is completely optional.
A static function has access to all member data. Am I missing something
here? I only have a couple months of real C++ experience, so I may have
misunderstood something, but I'm almost certain a static member function
can access all member data of instances of the class.

class Foo
{
public:
static void foo();
static int foo_and_bar_can_see_me;
int foo_cannot_see_me1;
protected:
static int foo_can_see_me1;
int foo_cannot_see_me2;
private:
static int foo_can_see_me2;
int foo_cannot_see_me3;
};

void bar();

Given an instance of Foo f in foo or bar:

void foo()
{
foo_and_bar_can_see_me = 1; // ok
foo_can_see_me1 = 1; // ok
foo_can_see_me2 = ; // ok

Foo f;
f.foo_cannot_see_me1 = 1; // ok
f.foo_cannot_see_me2 = 1; // ok
f.foo_cannot_see_me3 = 1; // ok
}


void bar()
{
foo_and_bar_can_see_me = 1; // ok
// foo_can_see_me1 = 1; // bad
// foo_can_see_me2 = ; // bad

Foo f;
f.foo_cannot_see_me1 = 1; // ok
// f.foo_cannot_see_me2 = 1; // bad
// f.foo_cannot_see_me3 = 1; // bad
}

While you are technically right, that a class static function can access
all data members, if it needs to access private and protected instance
members, why is it a class static function?

Actually, that brings up another area that you're way out in left field
on. Public data members. I was actually shaking my head in disbelief at
your proposed "associated" extension. I have never heard any recommend
the use of public data members in good OO design. It violates
encapsulation. I have heard some Java wags claim that for performance
reasons the cost of the accessor methods can be too much, but even that
has been debunked as nonsense. Just declare your accessor methods final
and most compilers will optimize them away. In C++ you don't even need
to rely on the compiler's whims and fancies, just make the accessor
functions inline.

There are no benefits to public data members except for backwards
compatability with old C code (and that is not an issue in this discussion).
If you have a reasonably good IDE its very easy to type:
java.[get a listing of available packages and classes]

Oh my lord. Your justification for a restrictive design constraint to be
applied to an entire body of work is that it makes it easier to make
flashy IDE's?

But I'll tell you what, I'll play along.

Why is it not possible for a C++ ide to detect a function sin() in a
namespace math in a namespace top?

I type "top" then a "::" and the IDE looks for a class or namespace
called top. It finds the namespace named top and pops up a charming
little list box of all namespaces, classes and functions in namespace
top. Then I click on the "math" namespace, and the box refreshes, now
with a list of all the namespaces, classes and functions in namespace
top::math. I could scroll down, but I'm too lazy, so I type "s". the
field is narrowed considerably. There's sec(), sin(), sqrt() and more. I
could click, but I paid a lot for this snazzy IDE, so I type the "i".
Now the field is narrowed down to sin(), sinh() and a couple others. So
I click on the "sin". Now I see a list of all the overloads of "sin".

Now, none of my IDE's do it, but I've never been impressed by IDE's, so
my compilers often have none to speak of (or I don't use them often, as
in the case of CodeWarrior). I suppose I could get a better editor. So
I'm not an authority on the subject, but there's probably an IDE out
there right now that does it for C++. If not, there's no practical
reason why there can't be, once someone is willing to put in the work.

select

java.Math.[get a listing of available members with their type displayed]

java.lang.Math perhaps?
One might argue that the real difference is that in Java you have another
level of encapsulation. I find 'free' functions to be of questionable
value. Some people seem to think of them as global functions.

There is no other level of encapsulation, encapsulation happens (as it
does in Java) at the class level. If you expose the guts of your class,
that is hardly the fault of an external function.

An external function that uses a class is just another client of that
class. It sees the same interface as anyone else. If that interface
changes, well you broke your program anyway, that's not the function's
fault.
Perhaps. There is the advantage of predictability. That is, since there
are fewer options, it's easier to determine how something is structured.
It also enforces certain structural rules that programmers might otherwise
violate.

I thought the structure was quite clear. All the math functions are in
the Math namespace.

What you're telling me is that you think having all the math functions
in the Math class is more structured than having all the math functions
in the Math namespace. But they're the same thing.

The only possible plausible argument in your favour is that having a
Math class means that all the math functions must be declared in a
*single translation unit* (or a single header file, in practice). Yeah,
I suppose there's some merit to that - you know exactly where to look
for a function. But that comes at a price.

The price is that I now have to include ALL the math functions in a
source file, even if I just want sqrt(). Also, if I have 1000+ math
functions (which is not inconceivable, what with overloads and all), and
I want to change or add just one, ALL files that use ANY math functions
will now need to be rechecked by the compiler. So much for predefined
headers.

Plus the obvious maintennance headaches trying to maintain one HUGE
header file instead of a dozen smaller ones.

You have not decreased coupling, you have increased it.

Ok, that's not even a complete sentence. The STL what? Sucks? R0x0rs?
Tastes like candy? What makes the STL empirical evidence that namespaces
cause sloppyness? And once again, sloppy in what way? What is sloppy?
And (some) C++ programmers believe the last is a viable option.

Your point? Some Java programmers believe that public data members are a
viable option. I wouldn't hire from either group.
But when you have disorganized your collection of operators as described
above, it is more difficult to work with. As far as OO goes, if you really
understand what Java is doing, you would understand that it is very much OO
to do things that way. But even if you only look at the surface, there is
nothing non-OO about using utilities classes. It's just another way of
using tools effectively.

How have I disorganized anything? From what I can read it's perfectly
well organized. The only difference between your organization and mine is:

// mine
namespace Math {
// organization
}

// yours
class Math {
public:
static // organization
};

I understand perfectly well what Java is doing. And why. And while I
could argue over whether it may or may not be "the" OO way to do things
(because OO is not exactly written in stone, you know, there are many
interpretations of the OO gospel), I will point out instead that OO is
hardly the last word in software design theory. Just search for object
oriented critiques, and alternatives.

As for utilities classes not being "non-OO", that's quite open to
debate, but I am not going to debate it. Instead I am going to take you
up on your final statement. "It's just another way of using tools
effectively."

The problem with that is that you're not using the tools effectively. In
fact, you're not using the tools at all. Namespace-scope functions are
tools, too. They are designed to solve a specific problem: operations
that are not associated with class data. You're tossing the screwdriver
aside and using the hammer to drive screws.

In Java, all you have is the hammer, so what can you do but use it
everywhere. In C++ (WHICH IS NOT AN "OO" LANGUAGE - it supports multiple
paradigms), you have a whole array of tools. Why stick to the hammer?
So if there is only one instance of a class, does that mean OO has been
missused? I find that argument against the use of the Math class to be
silly. Ever wonder why the German cognate for the English /dish/ means
table? There is a lesson there.

I am not an OO expert, so I really can't speak on that authoritatively.
Personally, I don't think singletons violate OO design. But we're back
again to insisting that you can create a "Math" (although we're now
insisting there can be only one (from the Matrix to Highlander)). And
once more I say, there is no Math. But prove me wrong, make one.

And no, I've never wondered why any german thinker for english crockery
would mean table, and for what. And I'm sure there is a lesson there,
there are lessons everywhere. The questions should, is it a good lesson?
And, is it relevant?
I tend to believe the onus falls in the other direction as far as the
visibility of data. But that's just what the standard texts on OO say.

Wha?

What onus? What other direction? I mean, if the body of operations CAN
be extended, and if they do not make use of any private data or
functions (that cannot be contained within the function of course), why
do the "standard texts on OO" say that they must be in a class instead
of a namespace?
One might argue that you have the illusion of choice in C++. How many
main() functions can exist in a C++ program? How do you specify the
namespace for that function? That sounds like a restraction, not a liberty
to me.

There is no illusion. You can have as many main() functions as you want.
You specify namespaces for main() functions the same way as for any
other function. You can only have one *entry point*, but that's true for
Java too (in the least illogical case). The only "restriction" here is
that the main() function in the global namespace is the entry point.

Java's restriction is no less restricting: the entry point must be a
static function called main in your startup class. You can have static
functions called main in other classes if you want. You can have free
main functions in other namespaces if you want. What's the problem?
I could be argued that /a/ math does have a cosine. But I would tend to
argue that for practical purposes, there is only one (singleton) math.
Math /is/ actually instantiated implicitly in Java.

It could also be argued that the world is a flat plate resting on the
back of an infinitely high pile of turtles, and that there are fairies
whose job it is to catch us when we fall off one side and put us on the
other and to alter all of our memories and measurements to keep the
truth from us. That doesn't make it right.

If you really understood object oriented terminology, you'd be laughing
at the idea of instantiating math. What's next, inheriting from Humour?
Extending Peace? Overriding Truth?
Yup, you understood the intent. There are some advantages to the functional
operator approach to mathematical symbolism.

Unless, of course, you're doing math.
Can you provide an example of a successfull general purpose programming
language that used such an approach?

After you provide me with a coherent and compelling argument in favour
of ditching non-class functions.
I'm not sure of all the cause and effect, but, yes, Java pretty much forces
the creation of Math. There, of course, are a few alternatives, such as
making a class for each operator, or for some subset of operators. I'll
grant that Java lacks a lot of the available finesse in C++. But that
feature of C++ comes at a cost.

Yes, more complicated compilers and a shortage of IDE's that are smart
enough to automatically guess the function you intend to use from part
of the qualified name.

Frankly, I don't care how hard my compiler vendor has to work to make me
a working compiler. I mean, props to the dudes at Edison, but I don't
see how that's relevant to my design process. So Java lacks a lot of the
finesse of C++, that doesn't explain to me why you would choose to dumb
down C++ now to make it more like Java.

And of course, it doesn't answer the cardinal question. If Java is the
model that C++ should follow, why does Java keep evolving to look more
like C++?

mark
 
M

Mark A. Gibbs

Steven said:
First off I meant to write /using namespace std;/ My brain does weird stuff
like that.

It's ok if used frugally. I still find it to be a bit too permissive and
unstructured.

Then don't use it. That doesn't preclude the use of namespaces or
namespace global functions.
I wasn't really thinking in those terms. I was just trying to determine
what the technical implications, pro and con, of the all objects approach
are. I'm not even thouroughly convinced there would be that much
difference if namespaces were completely removed from the language, and in
their place people used classes. I'm not suggesting that be done, but I am
suggesting that it is a worthwhile thought experiment.

I can tell you what would happen, the same thing that would happen if
you removed packages from Java. A mess.
What I'm saying is that, for example, ::std is a collection of templates
(which I intended as well when I wrote 'class' and 'function') with only
the fact that they are part of the Standard Library as a common
characteristic. Yes, one purpose for namespaces is simply a mechanism for
avoiding name collisions. But limiting their use to that goal puts us back
in the same fix of having a bunch of unrelated entities all laying around
on a common floor.

Except now there are no more name collisions.

If I'm reading you correctly your concern with namespaces is that people
don't use them enough. You would have preferred if there were
std::container and std::algorithm namespaces. Correct?

In the context of the STL namespace, anything more than std is not
necessary anyway. After all, you're not supposed to add anything to it.
And what do I gain by typing std::container::vector over std::vector?
Changing the name would not necessarily fix the problem. Disallowing
functions at namespace scope, however, would be an interesting exercise.

Interesting in the sense of the old chinese curse, perhaps. I maintain
that it adds no functionality and takes away design choices. Ergo, it
has no benefits.

What I'm still waiting for you to explain to me is how it could possibly
decrease the possibility of bugs, or increase clarity - SOMETHING,
ANYTHING - to justify it.
everything in namespaces. I do believe having a rule of thumb that
everything that could be in a class should be in a class would lead to
tighter designs with cleaner demarkation.

But just what is a "tighter" design? How do I measure this "tight"ness?
What are the benefits of "tight" vs. "loose" code? How does
Class::function() provide cleaner demarcation than Namespace::function()?

Just answer me this: can you provide me with any HARD arguments or
PROVABLE facts that support your argument, or is this all just based on
what you "feel" would be "better"?

mark
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top