Xiao Jia Xiao Jia - 2 months ago 10
C++ Question

Invoking virtual method in constructor: difference between Java and C++

In Java:

class Base {
public Base() { System.out.println("Base::Base()"); virt(); }
void virt() { System.out.println("Base::virt()"); }
}

class Derived extends Base {
public Derived() { System.out.println("Derived::Derived()"); virt(); }
void virt() { System.out.println("Derived::virt()"); }
}

public class Main {
public static void main(String[] args) {
new Derived();
}
}


This will output

Base::Base()
Derived::virt()
Derived::Derived()
Derived::virt()


However, in C++ the result is different:

Base::Base()
Base::virt() // ← Not Derived::virt()
Derived::Derived()
Derived::virt()


(See http://www.parashift.com/c++-faq-lite/calling-virtuals-from-ctors.html for C++ code)

What causes such a difference between Java and C++? Is it the time when vtable is initialized?

EDIT: I do understand Java and C++ mechanisms. What I want to know is the insights behind this design decision.

Answer

Both approaches clearly have disadvatages:

  • In Java, the call goes to a method which cannot use this properly because its members haven’t been initialised yet.
  • In C++, an unintuitive method (i.e. not the one in the derived class) is called if you don’t know how C++ constructs classes.

Why each language does what it does is an open question but both probably claim to be the “safer” option: C++’s way prevents the use of uninitialsed members; Java’s approach allows polymorphic semantics (to some extent) inside a class’ constructor (which is a perfectly valid use-case).

Comments