Wednesday, May 30, 2007

Comparisons of C++ and Java (IV): Accessibility of Indirect Base Classes

Firstly, let’s take a look at two examples in C++ and Java respectively:

Example 1 (In Java):

A.java
public class A {
A (){}
void printMsg(){
System.out.println("print from class A");
}
}

B.java
public class B extends A {
B (){}
void printMsg(){
System.out.println("print from class B ");
}
}

C.java
public class C extends B {
C (){}
void printMsg(){
// direct base class B is accessible but now indirect base class A
super.printMsg();
System.out.println("print from class C");
}
}

Test code snippet

C c = new C();
c.printMsg();

The inheritance path looks like:

A (indirect base)
|
B (direct base)
|
C

The test Results are:
print from class B
print from class C

In class C, method "printMsg()" in direct base class B is accessible by calling:

super.printMsg()

However, the method "printMsg()" in indirect base class A is not accessible. What about in C++? Let’s take a look at an exactly same example but in C++.

Example 2 (In C++): same as Example 1 but written in C++

class A:

class A{
public:
A(){}
void printMsg( ){
cout<<" print from class A "<<endl;
}
};

class B:

class B : public A{
public:
B(){}
void printMsg(){
cout<<" print from class B "<<endl;
}
};

class C:

class C:public B{
public:
C(){}
void printMsg(){
A::printMsg();//indirect base is accessible too
B::printMsg();
cout<<" print from class C "<<endl;
}
};

Test code snippet:

C* c = new Polygon::C();
c->printMsg();

The test code will print:
print from class A
print from class B
print from class C

As we have noticed, the indirect base class A is accessible in class C which is different than in Java as shown in Example 1.

Why C++ and Java are different at this point?

As my understanding it is because in C++, multiple-inheritance is allowed. A derived class may inherit methods with same finger print from different base classes as shown below:

class A
class A {
public A();
pulbic printMsg();
}

class B1
class B1 {
public B1()
pulbic printMsg();
}

class B2
class B2 {
public B2();
pulbic printMsg();
}

class C
class C : public B1,B2{
public C();
pulbic printMsg();
}


The inheritance path is shown as:
A (indirect base)
/ \
B1 B2 (direct base)
\ /
C

Class C has two direct base classes B1 and B2. This arises the ambiguity because both have a method called “printMsg()”. Image what if the printMsg() in class C would like to inherit both "printMsg()" from class B1 and class B2? Fortunately, C++ provides techniques to eliminates the ambiguities by explict qualification: B1::printMsg() or B2::printMsg() explicitly tells compiler which version of "printMsg()" is been used. However, the solution also leads the de-encapsulation of indirect base classes A in the inheritance tree.

Unlike C++, in Java, strict inheritance is enforced and all classes are single-rooted by the class Object. Multiple implementation inheritance is not allowed, thus the confusion in the examples above does not exist. Everything in the super class is inherited by the subclass. Thus, there is no need to access the indirect base class upward in the inheritance tree.

Monday, May 21, 2007

Comparisons of C++ and Java (III): Method Overriding

Method overriding is not quite the same in C++ as in Java. Here are some examples show the differences:

Method overriding in Java

base.java

public class base {
base (){}
void printMsg(){
System.out.println("print from base class");
}
}

Derived.java

public class derived extends base {
derived (){}
void printMsg(){
System.out.println("print from derived class");
}
}

test code snippet:


public static void main(String args[]){
base b = new derived();
b.printMsg();
}

What do we get:

>> print from derived class

Non-virtual method overriding in C++

base.h

class base{
public:
base(){}
void printMsg();
};

base.cc
void base::printMsg(){
cout<<" print from base"<<endl;
}

derived.h
class derived : public base {
public:
derived(){};
void printMsg();
};

derived.cc

void derived::printMsg(){
cout<<" print from derived class"<<endl;
}

test code snippet:

base* d = new derived();
d->printMsg();

And what do I get:

>>print from base class

which is not what I expect? But how does it happen? The reason is still because of the binding mechanisms in C++ and Java.

As we know there are two binding mechanisms in C++: static binding and dynamic binding. Dynamic binding is implemented through virtual functions; the actual code for the functions is not attached or bound until execution time.

On the other hand, static binding occurs when the functions code is “bound” at compile time. This means that when a non-virtual function is called, the compiler determines at compile time which version of the function to call. When overriding a non-virtual method in a derived class, if we call the method via base class reference or pointer type, the method in the base class is called. In our example above, the printMsg() in the base class is called and print out "print from base class".

As we have discussed before, in Java all method are treated as virtual, so dynamic binding applied all the time. And when we override a method in a derived class, we are able to call the method via a base class reference.

So what is the solution in C++ if I want to call the overridden methods in a derived class via a base class reference?

The answer is to make the method in base class virtual, as shown below:

base.h

class base{
public:
base(){}
virtual void printMsg();
};

Because the function printMsg() is virtual, dynamic binding applies. When we call the derived method via a base class reference, we get what we want:

>> print from derived class

Sunday, May 20, 2007

Comparisons of C++ and Java (II): Static Variables

I used a lot of static variables in Java programming and I don't feel any tricks except you have to know why you make a variable static. I thought it would be the same to use static variable in C++. However, it is not true.

In C++, static data member must be defined outside class definition

In Java, we declare a static variable in class scope and can access it anywhere inside the class. In C++, I thought it must be the same way. Actually it is not. Here is the example. I declare a variable static in head file (test.h) and try to use it in the program file (test.cc) as shown in the sample code:

test.h

class test {
private:
static int i;
public:
test();
}

test.cc
test::test(){
i = 0;
}

At compilation, I get an error says “undefined reference to `test::i”. After I looked up some books and also did some Google search, I finally figured out that a static variable must be defined in the program file. So test.cc should look like:

test.cc

int test::i; //We can also initialize i here, eg. int test::i = 0.
test::test(){
i = 0;
}

Now compiler is happy. But why? The reason is that C++ keeps two files for a class: class declaration (header file) and class definition (program) file. The header file contains the class declaration and does not necessary reserve storage space associated with the identifier, while the program file contains method definitions and reserve storage space for each given identifier.

So when we declare a static data member within a class definition, it is NOT defined. In other words, we are not allocate storage for it. Instead, we must provide a global definition for it elsewhere outside class definition because it does not belong to any specific instance of the class.

What about in Java? Java has a simplified matter by only have class and variable definitions. There are no sole declarations in Java, so class definition and variable definitions are also class declarations and variable declarations. In other words, in Java, all classes, data members and variables within methods are defined, therefore storage spaces are reserved for primitive data types.

In C++, a local variable can be static

In C++, a local variable can be static. For example:

test::test(){

i = 0;

static int count = 0;

}

is perfectly legal in C++. A local static variable has the same life time as a global static variable, but its scope is local to the function in which it is declared. It sounds a good idea to me.

In Java, a static variable can only be declared inside a class scope. Compiler will complain if a local variable is declared as static inside a method scope, Even inner classed cannot have static declarations.








Thursday, May 17, 2007

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):

base class:

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();
}
}

What do get? Here we go:

>>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();
...

What do we get? There we go:

>>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++:

  1. 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.
  2. Making destructor virtual is a best practice since it would make sure the destructor in derived class get called too as desired.