3

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;
}
damned
  • 935
  • 2
  • 19
  • 35
  • 2
    "Was it intentionally designed this way?" - why would you expect that there was any communication between the people designing Java and those designing C++? They are different languages. Designed and evolved independently – Jesper Juhl Jun 09 '19 at 18:28
  • 1
    There are **many** differences between C++ and Java; and, in fact, some of Java is implemented in C++. I think it's safe to say that where C++ and Java differ it was intentional; else we'd just write C++ and have no need for Java. – Elliott Frisch Jun 09 '19 at 18:30
  • @ElliottFrisch I'd argue that by now (latest java vs C++17) they are sufficiently different that you wouldn't want to try implementing one in terms of the other. – Jesper Juhl Jun 09 '19 at 18:33
  • @JesperJuhl [Ummm....](https://openjdk.java.net/jeps/347) – Elliott Frisch Jun 09 '19 at 18:36
  • 5
    *My motivation for this investigation...* -- I would say to stop wasting time with this "investigation". You should not be using C++ as a guide or model in learning Java -- they are two different languages, different rules, etc. – PaulMcKenzie Jun 09 '19 at 18:38
  • @Elliott Interesting. – Jesper Juhl Jun 09 '19 at 18:39
  • 4
    The C++ reason is that the "inheriting" hasn't been done yet (What if it uses a member that only exists in the derived class? It hasn't been initialized yet, so it must use the base class version). I don't know about Java, but [it looks like it just default initializes](https://ideone.com/FI9c26). – Artyer Jun 09 '19 at 18:43
  • @JesperJuhl That doesn't make any sense. You can implement any language in any other language, more or less. The host language's semantics don't have to leak into the target language. – user207421 Jun 10 '19 at 03:20

1 Answers1

1

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.

anarthal
  • 156
  • 4