calling overridden methods from constructor in C++ vs Java

Viewed 156

Calling overridden methods from constructor differs in java vs C++. Can somebody explain why how their dispatch method differs?

I understand that C++ and Java were designed and evolved differently. But when it comes to calling overridable methods from constructor, any insight into why language spec was intentionally designed this way would help.

My motivation for this investigation is the ErrorProne check : http://errorprone.info/bugpattern/ConstructorInvokesOverridable

Here is the java code which returns 1

class Ideone
{
    static class Simple {
        public int i;
        Simple() {
            this.i = func();
        }
        public int func() {
            return 2;
        }
    }

    static class Complex extends Simple {
        @Override
        public int func() {
            return 1;
        }
    }

    public static void main (String[] args) throws java.lang.Exception
    {
        Complex c = new Complex();
        System.out.println(c.i);
    }
}

Here is the c++ code which returns 2

#include <iostream>
using namespace std;

class Simple {
    public:
    Simple(int i) { i_ = func(); }
    virtual int func() { return 2; }

    int i_;
};

class Complex : public Simple {
    public:
    Complex(int i) : Simple(i) {}
    int func() override { return 1; }
};

int main() {
    // your code goes here
    Complex complex(2);
    printf("Val is : %d\n", complex.i_);
    return 0;
}
1 Answers

Calling a virtual function in a constructor or destructor represents the current object construction/destruction state. As the base gets initialized before the actual class, calling it in the base class constructor will dispatch to the base class function.

The derived class members are not initialized at this point, so any invariant imposed by the derived class has not yet been established. As such, the derived class function may not be able to perform its work properly.

Remember, base classes get initialized first, in order of declaration; then data members, in order of declaration; then the constructor runs. Only then the object is complete.

It is usually considered bad practice to call dynamic dispatched functions in ctors and dtors.

Related