Reputation: 2673
I have some background in C++ and know some Java too (apparently far from enough).
When I see overriding behavior in Java or C++, it does not seem to differ much. Given below example in JAVA:
class Animal{
public void move(){
System.out.println("Animals can move");
}
}
class Dog extends Animal{
public void move(){
System.out.println("Dogs can walk and run");
}
}
public class TestDog{
public static void main(String args[]){
Animal a = new Animal(); // Animal reference and object
Animal b = new Dog(); // Animal reference but Dog object
a.move();// runs the method in Animal class
b.move();//Runs the method in Dog class
}
}
In Java, you use a base class reference, in C++ you use a base class pointer, and depend on the type of instance it points to (a base class object instance or a subclass instance), you can achieve polymorphism.
The above is based on you call the instance method using a base class reference or pointer, right?
Now I see this example in Java.
What is the order of the Constructors in this Java Code?
Basically it says if a base class function is overriden, then in the process of creating a subclass object, even the base class initialization portion will be affected. See below explanation I copied from above link:
new Son()
=>
Son._init
=> first every constructor calls super()
Father._init
Object._init
who() => is overridden, so prints "son" !!!!!
tell(name) => name is private, so cannot be overridden => "father"
who() => "son"
tell(name) => "son"
Why should this happen? I mean does this conform to how polymorphism should be use? When making base class portion of initialization, why use overrided function from subclass?
In Java doc http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.5, I only find this:
"Unlike C++, the Java programming language does not specify altered rules for method dispatch during the creation of a new class instance. If methods are invoked that are overridden in subclasses in the object being initialized, then these overriding methods are used, even before the new object is completely initialized. "
But I don't know the reason behind it, and it feels strange.
Any thoughts?
Upvotes: 2
Views: 96
Reputation: 61986
This is one of the extremely rare cases where C++ is trying to protect you from shooting yourself in the foot more than Java does. (Or at least it has the noble intention to do so.)
You are very likely to shoot yourself in the foot in any language if you try invoking an overridable (virtual) method M of your base class B from within the constructor of B. That's because M is likely to be overridden in derived class D, but at the moment that B is being constructed, D has not been constructed yet. So, D.M is being invoked before the constructor of D has been invoked. That can spell disaster.
So, Java simply allows this to happen, use at your own risk. (If you have sufficient warnings enabled, your compiler will tell you that you are living life dangerously.)
C++ does not prohibit this either, but it slightly changes its behaviour so as to contain the damage, so to speak: when you invoke a virtual method from within a constructor, it does not really invoke it as a virtual method, (with a VMT lookup,) but it invokes it directly, as a non-virtual method.
(Either that, or from within the constructor of B it simply uses class B's VMT instead of D's VMT. Which, come to think of it now, makes sense. But I am not sure about that, it has been a long time since I last troubleshot this behaviour of C++.)
Upvotes: 6