Professional Documents
Culture Documents
The semantics of calling virtual methods from base-class constructors in C++ is different from that of
Java/C#. In C++, any virtual calls will be resolved only to the type of the object being constructed;
however in Java/C#, a virtual method call will be made.
Both the approaches have advantages and disadvantages; before covering those details, let us see an
example from C++ and Java first which shows this difference:
// C++ example
struct base {
base() {
vfun();
}
virtual void vfun() {
cout << “Inside base::vfun\n”;
}
};
int main(){
deri d;
}
// prints:
// Inside base::vfun
// Java example
class base {
public base() {
vfun();
}
public void vfun() {
System.out.println("Inside base::vfun");
}
}
In C++, when a virtual method call is made from the base class constructor, only the static type of the
object is considered. If the dynamic type was considered and the derived class method is invoked, then
it will possibly result in accessing the un-initialized parts of the derived object, which is not desirable
(this is what precisely happens in case of Java and C#). However, because of this semantics, sometimes
it can happen that the users accidentally end up calling a pure virtual function in C++.
Calling pure virtual function results in undefined behaviour; the usual behaviour for the compilers is to
throw a runtime exception and terminate the program abnormally. Here is an example:
struct base {
base() {
base * bptr = this;
bptr->bar();
int main(){
deri d;
}
// g++ output:
// pure virtual method called
// ABORT instruction (core dumped)
The compiler can detect virtual method calls inside the pure virtual function calls, but it cannot
invocations detect indirect invocations. In case there is a temporary variable to have indirect invocation
or a typecast present, then the compiler will not detect call to pure virtual function call.
Note that, if Java/C# like semantics were followed in C++, the overridden method would have been
called which would have avoided this possibility of invoking a pure virtual function.
Coming to Java and C#, since the overridden method is called when a virtual method is called in a base
class constructor, the program can end-up accessing the derived parts, which wouldn’t have been
initialized yet. The following example shows this with an example: Derived class has a data member of
type Integer, which will be initialized only when the constructor of Derived is invoked; however, since
the virtual method foo is called from the base class constructor, the program tries to call toString
method from i which is not initialized yet, resulting in NullPointerException.
// Java code
class Base {
public Base() {
foo();
}
public void foo() {
System.out.println("In Base's foo ");
}
}
class Test {
public static void main(String [] s) {
new Derived().foo();
}
}
// this program fails by throwing a NullPointerException
An equivalent program in C# will also fail in the same way by trying to access the un-initialized data
member in Derived object.
[1] Invoking virtual methods in destructors - as in C++ - also doesn’t work well. The object is getting
destroyed and hence the object cannot be expected to be in consistent state, so it will result in defects.