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.
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