Comparisons of C++ and Java (I): Static Binding and Dynamic Binding in C++
After years of Java programming, I have to pick up C++ for my work. Sometimes, it is hard to switch from Java thinking. Here is one of the example: Static binding and Dynamic binding in C++.
Let me start with 3 examples.
Example 1 (In Java):
public class base{
public base(){}
public void printMsg(){
System.out.println("I am printMsg() from base class");
}
derived class
public class derived extends base{
public derived(){}
public void printMsg(){
System.out.println("I am printMsg() from derived class")
}
)
A test class:
public class test {
public static void main(String[] args){
base myClass = new derived();
myClass.printMsg();
}
}
>>I am printMsg() from derived class
It is so obvious to a Java programmer. OK, let’s look at C++ version of the example above.
Example 2 (in C++): this example looks exactly same as example 1 but in C++.
base class:
class base{
public:
base(){};
void printMsg( cout<<”hi, printMsg() from base”<<endl;);
};
...
derived class:
class derived : public base {
public:
derived();
void printMsg(cout<<”hi, printMsg() from derived class”<<endl);
};
...
test class snippet
....
base* myClass = new Polygon::derived();
myClass->printMsg();
...
>>hi, printMsg() from base
and not “hi, printMsg() from derived class” as I expected.
How can I access derived class version of printMsg() in C++? There is a way out: by using pure virtual methods. In base.cc we change declaration of void printMsg() as:
Example 3 (in C++): This example is same as example 2 except in the base class. The method printMsg() is made pure virtual:
class base{
public:
base(){};
void printMsg( cout<<”hi, printMsg() from base”<<endl;);
virtual void printMsg() = 0;
};
Then compile and run, I get what I want:
>>hi, printMsg() from derived class
The derived class version of printMsg() get called.
What is going on here?
It is because Java and C++ provide different binding mechanisms to achieve run-time polymorphism.
In C++ there are two kinds of data binding: static binding and dynamic binding. Static binding is by means of nonpuer virtual functions while dynamic binding is by virtual functions.
At run time, the implementation is chosen differently. In static binding, decision is made by the static type of pointer or reference, while in dynamic binding, decision is made by the actual type of object being pointed to.
This can explain the results from example 2 and 3. In example 2, base class contains no virtual printMsg() function, so it is static binding. In example 3, method printMsg() is a virtual function, so dynamic binding applies, therefore the derived class version of printMsg() is picked up.
What happens in Java? In Java, every method is treated as pure virtual method and dynamic binding applies always.
Extra note on pure virtual method in C++:
- When using pure virtual methods in C++, never try to call a pure virtual method from a constructor or destructor. Compiler will complain “error: abstract virtual `virtual method' called from constructor” at compilation time.
- Making destructor virtual is a best practice since it would make sure the destructor in derived class get called too as desired.