Re: On Java and C++
"Noah Roberts" <roberts.noah@gmail.com> wrote in
news:1146856580.878488.221940@i40g2000cwc.googlegroups.com:
Otis Bricker wrote:
Since all references to Java Objects(not primatives sadly) are done
the same way, what reason is there for an explicit notation?
You just mention a difference right there in that sentance. In C++
primatives and objects act the same wrt value, pointer, and reference
semantics.
Actually they are very consistant. It is ALWAYS pass by value. It is
just that variables that hold Objects are always 'references'. Yuo you
are passing the value of the reference.
I said it was consistant. Not obvious.
Java programmers
know how they work. And they only work one way.
They may behave the same but there is no explicit distinction between
when they are there and when they are not...it is implicitly based on
type.
And this is fully understood by any good Java programmer.
That may be a limitation
but it hardly fosters confusion.
Might not be if it was true.
I don't know any halfway good java programmer that it confuses. I
couldprobaly find some butthen I could probaly find C++ programmers that
have trouble understanding references or const.
Yes, C++ references have many uses. Particularly 'const' ones. But
they also provide sources of confusion.
{
int i=10;
foo(i);
}
is i=10 still? C code yes, C++ maybe. In Java, there is no queston.
Sure there is, if i is an object and not a primative. Did Java change
i or not?
As all calls are by value, it cannot change i.
Had the code been
{
A a= new A();
foo(a);
}
a would also have not changed. It would still reference the same object.
But the actual object refered to by a might have changed.
I don't know ... is there a way to implement the following signature
in Java? AFAIK there is not:
void foo(const I & i);
I think you are right and I sometimes wish it were possible. And that
'i' was truly const.
But you seem to have missed my point. The calling code does not provide a
clue about the calling method. If someone changed the declaration of foo
(int i) to foo(int& i), my code is affected and my assumptions are no
longer valid. In Java, I KNOW that foo(a) might modify the object
referenced by 'a' if its an object but the reference will still point to
the same object. And that foo(int i) will not change anything.
That function accepts a reference to an I object that cannot be
changed by foo without purposfully breaking the language's protections
through a const_cast. Callers can rely on the fact that i is not
changed as that definition is a statement to that effect.
As I am primarily a C++ developer and have worked with the language for
close to 15 years, I am aware of those facts. But thank you. Some of the
Java folks may not know about it. Though you should see below since your
statement is a little too broad. Even ignoring 'mutable'. And I do like
and use 'mutable' to allow for logical rather than physical constness.
I think the closest you could come to that behavior is to create an
"unmutable" interface for I objects and accept that interface instead
of I and then implement it for I. Of course this has to be done for
every different type of object you want to do this with...C++ contains
this interface within the class definition through the form of const
operations...a simple keyword that you place on functions that do not
alter the internals of the object...and the language won't let you do
it either unless you explicitly ask it to through casts or the mutable
keyword.
You can only do that if you have control over the I object and can
cause it to 'implement' an interface. Since your language doesn't
provide the idea of const as part of the language it isn't standard to
find interfaces implemented in those terms...in C++ it is. Either way
you have good vs. bad code and in the end can get the same thing done,
but C++ offers a little better way of doing it.
Not sure why it has become my language. But thanks for the gift. Can I
collect royalties?
And const is not quite as const as you imply. Forgive the lack of
using/includes
class TestCase{
char*a;
public:
TestCase(){
a=new char('b');
}
~TestCase(){
delete a;
}
void dump(){
cout<<*a<<endl;
}
void morph()const{
*a='a';
}
};
void foo(const TestCase& t){
t.morph();
}
Const applies only to directly held objects. If you need to dynamically
allocate items, there are open to modification. As are non-const
references. So I cannot make TestCase::a point somepace else in morph or
foo but I can change the value that it points to.
And off course interfaces are just a piss poor replacement for
multiple inheritance ;)
MI is nice sometimes. But I often find it misused. Composition often
works better. Personally, I have found that NOT being able to use MI in
Java has often made me think more about composing objects/interfaces and
provided a better solution in the end. The same can and should be done
with C++ and I try. C++ does not prevent this. But I picked up the skill
working in Java as it was forced upon me. Languages shape out thinking.
Also,
void foo(I i);
Is I changed? Certainly not in C++ where i is passed by _value_ no
matter what type it is...in Java you can't tell...someone may have
called a mutable function on it. In Java if i is an int it is copied
and the original is not changed...but if i is an object then maybe it
is, and maybe it isn't...you can't know from the signature alone.
Actually, your example from before shows that i MIGHT change. At least
logically change.
class I{
int & handle;
public:
I(int& x):handle(x){};
void morph()const{
handle++;
}
void dump(){
cout<<handle<<endl;
}
};
void foo(I i){
i.morph();
}
I guess you could argue that it was the int& that changes. But clearly,
the state of the original i is not the same before and after that call.
But are you are actually saying that having code like a=a2; silently
modify two other objects, z and y, is a reduction in confusion? Got
to love those hidden side effects!
It is certainly not hidden and that was a sample only.
Well, without looking through the definitions/implementations of Y and
Z, I would wave no way of knowing to expect this behaviour. And having
looked, I would have no way of knowing if that behaviour was changed in
the future. My code would still compile but the behaviour would change.
I call that hidden though you are free to use another term.
And yes, the same sort of bad code could be done in Java.
C++ is very flexible and powerful. I like working with it. But that does
not mean that Java is bad. It is different. As are Smalltalk and
Haskell. We should use them all to learn new ideas and understand the
craft better.
OB