I tried calling an overridden method from a constructor of a parent class and noticed different behavior across languages.
C++
- echoes A.foo()
class A{ public: A(){foo();} virtual void foo(){cout<<"A.foo()";} }; class B : public A{ public: B(){} void foo(){cout<<"B.foo()";} }; int main(){ B *b = new B(); }
Java
- echoes B.foo()
class A{ public A(){foo();} public void foo(){System.out.println("A.foo()");} } class B extends A{ public void foo(){System.out.println("B.foo()");} } class Demo{ public static void main(String args[]){ B b = new B(); } }
C#
- echoes B.foo()
class A{ public A(){foo();} public virtual void foo(){Console.WriteLine("A.foo()");} } class B : A{ public override void foo(){Console.WriteLine("B.foo()");} } class MainClass { public static void Main (string[] args) { B b = new B(); } }
I realize that in C++ objects are created from top-most parent going down the hierarchy, so when the constructor calls the overridden method, B does not even exist, so it calls the A' version of the method. However, I am not sure why I am getting different behavior in Java and C# (from C++)
Method overriding, in object-oriented programming, is a language feature that allows a subclass or child class to provide a specific implementation of a method that is already provided by one of its superclasses or parent classes. It allows for a specific type of polymorphism (subtyping).
Constructor looks like method but it is not. It does not have a return type and its name is same as the class name. But, a constructor cannot be overridden. If you try to write a super class's constructor in the sub class compiler treats it as a method and expects a return type and generates a compile time error.
Instance MethodsThe ability of a subclass to override a method allows a class to inherit from a superclass whose behavior is "close enough" and then to modify behavior as needed. The overriding method has the same name, number and type of parameters, and return type as the method that it overrides.
In C++, as you correctly noted, the object is of type A
until the A
constructor is finished. The object actually changes type during its construction. This is why the vtable of the A
class is used, so A::foo()
gets called instead of B::foo()
.
In Java and C#, the vtable (or equivalent mechanism) of the most-derived type is used throughout, even during construction of the base classes. So in these languages, B.foo()
gets called.
Note that it is generally not recommended to call a virtual method from the constructor. If you're not very careful, the virtual method might assume that the object is fully constructed, even though that is not the case. In Java, where every method is implicitly virtual, you have no choice.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With