JAVA has "instanceof". Why C++ only has "typeid" and "dynamic_cast"?
Is there any reason or concern JAVA implements it but C++ doesn't?
JAVA has "instanceof". Why C++ only has "typeid" and "dynamic_cast"?
Is there any reason or concern JAVA implements it but C++ doesn't?
huh?
Maybe because they're both the freakin' same thing?
Is precisely the same as:Code:x instanceof y
It's syntax. Nothing but syntax.Code:typeid(x) == typeid(y())
Or is your question actually, "Why aren't these two languages identical?" Which is an awfully weird question.
Note that there's no need to actually instantiate the target type.Code:template <typename Of, typename What>
inline bool instanceof(const What &w)
{
return typeid(w) == typeid(Of);
}
instanceof<Foo>(bar)
The reference is being passed by value. The point is, you can't modify the actual argument - you can't modify what the reference points to, or the value of the integer. That's why Java is pass-by-value, always.
I just realized my little function is incorrect. It doesn't test inheritance correctly. This one works:
Of course, that's completely pointless. Now that you have determined that w is an instance of Of, you still have to cast it. You can't use a static_cast (it could be a cross-cast instead of a simple downcast). You can use a dynamic_cast, but you just did, so there's clearly a waste going on here.Code:template <typename Of, typename What>
inline bool instanceof(const What &w)
{
return dynamic_cast<const Of*>(&w) != 0;
}
That's why the standard dynamic_cast usage looks like this:
Code:if(Bar *pb = dynamic_cast<Bar*>(po)) {
// Use pb
}
// pb is not in scope and cannot be used, which is good, because it's not valid
Java's instanceof is a stupid idea anyway. There's very few situationa where you want to do a typecheck and not actually use the object afterwards. Thus, Java's type selection is always a mess of redundant type comparison. Take your average Object.equals implementation:
Note that there are actually two typechecks here, one for the instanceof, and another for the cast. (Some VMs optimize the second away.) Completely redundant. C#'s 'as' operator is much more useful (and, incidently, equivalent in usage to dynamic_cast.)Code:public boolean equals(Object o)
{
if(o instanceof Foo) {
Foo f = (Foo)o;
return this.garble == f.garble;
}
return false;
}
I don't know if the code below is actually correct about the declaration in the condition and implicit bool conversion.
Code:public bool Equals(Object o)
{
if(Foo f = o as Foo) {
return this.garble == f.garble;
}
return false;
}
Yeah ... the problem is that, depending on context, a Java function can be passed an argument by reference (and can modify whatever is referenced) or the same function can be passed something else by value.
Passing arguments always involves passing something by value - in any programming language. But the way it's described in Java is a problem: the mechanism of what is passed changes with context.
Not true. In C++, for example, references aren't objects, so you're not passing anything by value if the parameter is a reference.Quote:
Passing arguments always involves passing something by value - in any programming language.
In C#, if you have a ref or out parameter, you don't pass anything by value.
The underlying implementation may use (will use almost always, actually) pointers, but on the language level, there aren't any.
No, primitive types are passed by value, but objects are passed by reference. Obviously the references themselves are passed by value, just like pointers, but no copy of the object is created, and unless the object is immutable like Strings, you can modify the object that is passed to a function by using the object's member functions.
Objects are passed by value. The thing is it isn't passing the object itself but instead it is passing a pointer... by value.
SoIf it was pass by reference then i would be 6 after the function. Really what you have is something like this in c++ (assume an Integer class has been created)Code:Integer i = new Integer(5);
Foo.meh(i);
public void meh(Integer j)
{
j = new Integer(6);
}
Code:Integer *i = new Integer(5);
Foo.meh(i);
void meh(Integer *j)
{
j = new Integer(6);
}
Anything that can be initialised has a value (where value is "some attribute that can be used to identify, specify, or quantify" - one dictionary definition). The value of a reference is some identifier of (or information that uniquely identifies) an object. Try and create a reference variable in C++ without initialising it.
As far as the underlying implementation is concerned the value of a reference will be that thing which is "almost always" a pointer. The concept of a reference having a value is easier to grasp when you dig down to the detail of underlying implementation, but still has meaning in the higher level language.
The difference is that the higher level languages (C++, Java) constrain how references can be used. For example, once a reference is initialised in C++ it is not possible to make it refer to something else. But the fact it must be initialised (ie some attribute of it must be set) means that a reference has a value.
A reference is just another way of expressing a pointer. I mean if you write a C++ function that calls for a pointer to be past into it, and use that program from your C code, you will need to pass a pointer into that function. A reference isn't anything magical. Its just a semantic thing.
But that would be a fallacy when discussing the theoretical semantics of the language.Quote:
The concept of a reference having a value is easier to grasp when you dig down to the detail of underlying implementation
While there is a meaning, it is not useful in considering the implications of pass by reference and pass by value.Quote:
but still has meaning in the higher level language.
It's pass by reference if you can modify the accessible entity you passed (barring write restrictions imposed through other means), pass by value if you can't. And the accessible entity in the case of Java is the object reference, not the object itself.
I'm not sure I'd agree with that. Pass by value means you make a copy of something. Otherwise with your description, passing a const char* in C/C++ is passing by value since you can't modify the char* string (without a cast at least).
In Java, it helps to throw away the word 'reference' and replace it with 'pointer', since that's really what it is. If you pass a pointer to an object in Java, you can modify that object with the objects set() functions, but obviously you can't reassign it with the = sign, since that would only change the local pointer (reference), but not the pointer outside the function.
In the "theoretical semantics of the language" a reference is an entity that contains or presents information that identifies another object, through which that other object can be accessed or modified.
I disagree.
And, again, a concern with Java is that depending on the context in which a function is called, the argument supplied by the caller is either passed by reference (and that reference is passed by value) or the supplied argument itself is passed by value. This is a bit of unnecessary mental gymnastics in understanding how to do things in Java.
It's pass by value because you can't modify the pointer. If it was about the string, it's the reason I said "barring other write restrictions". The const is such a restriction.Quote:
Otherwise with your description, passing a const char* in C/C++ is passing by value since you can't modify the char* string (without a cast at least).
No. In C++, for example, a reference is simply an alias for an object.Quote:
In the "theoretical semantics of the language" a reference is an entity that contains or presents information that identifies another object, through which that other object can be accessed or modified.
In the end, it comes down to this. Given an entity t of type T
and a function callCode:T t;
then the language natively supports pass by reference if the shallow value (as in, not the value of something t references) can be changed, given a proper implementation of foo. This is the only meaningful definition of support for pass by reference.Code:foo(t)
Java does not support this. If T is int, then I can't change the value. If T is a reference type, I can't change what it references.
C does not support this either.
C++ does, as does VisualBasic. C# kind of allows it - the fact that you have to give the ref or out keyword on argument passing muddles the situation a bit.
C allows emulation of it through pointers. Java kind of allows emulation through wrapper objects, but that still doesn't change t.
Now we're making points on the same side of the discussion - the only difference is that we're highlighting the significance of different (but related) aspects. Using a simple example in C++;
x meets the definition "a reference is an entity that contains or presents information that identifies another object, through which that other object can be accessed or modified" I gave earlier. Related to this, x can also be used as an alias (alternate name) for i.Code:int i;
int &x(i);
The discussion is about chicken and egg at present: you're chasing the chicken and I'm chasing the egg. :)
Perhaps. But I think the issue that led us to this was about the taste of chicken meat. ;)Quote:
The discussion is about chicken and egg at present: you're chasing the chicken and I'm chasing the egg.
So, to clarify a bit things.
The first is like instanceof in Java. It will probably though convert the type even if you just wanted a check, thus be slower.
The second checks if the types are the same, but doesn't check if one in inherited by the other. Correct?
In any case, C++ offers two things, so it should be more efficient.
And, as a final note, there isn't something EXACTLY like instanceof in C++
Not really. The check whether the conversion is allowed is expensive. Performing the conversion is just an afterthought. In fact, I'd wager the additional cost is actually zero on superscalar CPUs, as the necessary instructions are executed in parallel with whatever else is around them.Quote:
It will probably though convert the type even if you just wanted a check, thus be slower.
Correct.Quote:
The second checks if the types are the same, but doesn't check if one in inherited by the other.
Comparing typeids is typically one indirect access plus one comparison, but could also be three indirect accesses and a string comparison. Depends on the platform, the compiler, and the capabilities of the linker.Quote:
In any case, C++ offers two things, so it should be more efficient.
Doing a dynamic_cast is typically linear in the total number of direct and indirect base classes, doing most of the work of a typeid comparison at each step.
Well, given that dynamic_cast isn't significantly (or even measurably, probably) slower than a pure type check, I'd say my function is exactly like instanceof.Quote:
And, as a final note, there isn't something EXACTLY like instanceof in C++
Actually, I think it was whether or not Java supports pass by value that did it.
You're saying that it ONLY supports pass by value, since the references are passed by value, but that's irrelavent, because the same is true of pointers in C/C++. The problem is that there is no way to pass the actual object by value in Java, and thereby create a copy of the object.
The reason is because all objects in Java are created on the heap and there is no way to create an object on the stack, so rather than the objects being passed by value, their references are passed by value instead, which is what I meant by saying Java doesn't support pass by value.
It is better to say that Java doesn't support "object variables". Meaning that you cannot declare an object with a certain name. You can only declare a reference. The object doesn't have a name only its reference.
So when you write Object O in java it means a reference to an object, not an object, even though that seems a bit strange. So a function that is void foo(Object O) wants a reference to an object and deals with it as it will deal with it with an int. There is no difference.
In C++, Object O means a object variable. So it means the same for void foo(Object O).
But C++ also offers you to pass an object by reference. ONLY C++ offers passing by reference, Java doesn't have the feature. Neither does C. In order to distinguish passing by value and passing by reference modes you use the & symbol.
So Java supports pass-by-value ONLY, C++ supports both. C++ also supports "object variables", thus allocating on the stack". Java only supports reference variables.