Why does inheritance behave differently in Java and C++ with superclasses calling (or not) subclasses' methods?

RajibTheKing :

I have written - what seemed to be - exactly the same example of inheritance both in Java and C++. I am really amazed to see the different outputs of these programs. Let me share both code snippets and the corresponding outputs.


C++ Code:

class A
{
public:
    A() {}
    void sleep() {
        cout << "A.Sleep" << endl;
        eat();
    }
    void eat() {cout << "A.Eat" << endl;}
};

class B: public A
{
public:
    B() {}
    void sleep() {
        A::sleep();
        cout << "B.Sleep " <<endl;
        this->eat();
    }
    void eat() {
        cout << "B.Eat" << endl;
        run();
    }
    void run() {
        A::sleep();
        cout << "B.run" << endl;
    }
};

int main()
{
    B *b = new B();
    b->sleep();
}

Output:

A.Sleep
A.Eat
B.Sleep
B.Eat
A.Sleep
A.Eat
B.run

executed successfully...

Java Code:

class A
{
    A() {}
    void sleep() {
        System.out.println("A.Sleep");
        this.eat();
    }
    void eat() { System.out.println("A.Eat");}
};

class B extends A
{
    B() {}
    @Override
    void sleep() {
        super.sleep();
        System.out.println("B.Sleep");
        this.eat();
    }
    @Override
    void eat() {
        System.out.println("B.Eat");
        run();
    }
    void run() {
        super.sleep();
        System.out.println("B.Run");
    }
}

public class Test {
    public static void main(String[] args) {
        B b = new B();
        b.sleep();
    }
}

Output:

A.Sleep
B.Eat
A.Sleep
B.Eat
A.Sleep
......
......
......
(Exception in thread "main" java.lang.StackOverflowError)

I don't know why these two examples of inheritance behave differently. Shouldn't it work similarly? I am pretty curious to know... what is the explanation for this scenario?

Neuron :

In your C++ example you are hiding the base methods, but you don't override them. So they are actually different methods which just happen to have the same name. If you are calling

A* a = new B();
a->sleep();

it will actually print "A.Sleep". If you want to override a method, you need to declare it virtual in the Base class (automatically making it virtual in all sub classes too). You can read more about function hiding vs overriding in C++ in this post.

In your Java example you actually override the methods, so they are the same method. One taking the place of the old. You can think of it this way: all Java functions are secretly marked as virtual, meaning they can be overridden. If you want a method to not be overridable in Java, you must declare it final.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=430573&siteId=1