Tuesday, July 17, 2007

Java vs. C++ - Part Two

These are some more differences between Java and C++.

JavaC++
Class attributes and behaviors Attributes are "instance variables".
Behaviors are "methods"
Attributes are "data members".
Behaviors are "member functions"
Extending Class Object Every class is a subclass of Object and so inherits the 11 methods defined by class object, you never create a class from scratch. Even if a class doesn't explicitly use extends in its definition, it implicitly extends Object You can create classes from scratch. A class will inherit attributes and behaviors of a base class ONLY when its declaration explicitly implies that it should.
Packages Every class belongs to a package even if not explicitly specified it will be the default package ( the current directory ) Classes do not have packages. Their containing header files are simply included in source files in which they are to be used
Constructor name Methods other than the constructor of a class ARE ALLOWED to have the same name as the class AND to specify return types but these are not constructors and won't be called when an object is created. It is NOT ALLOWED for any member function other than the constructor to have the same name as the class name AND it is INVALID to specify a return type for any constructor.
Initializing attributes Instance variables CAN be initialized where they are declared IN THE CLASS BODY, by the class's constructor, or they can be assigned values by "set" methods. Instance variables that are not explicitly initialized by the programmer are initialized by the compiler (primitive numeric variables are set to 0, booleans are set to false and references are set to null). Data members can be initialized ONLY by the class's constructor, or they can be assigned values by "set" methods. Instance variables that are not explicitly initialized by the programmer are NOT automatically initialized (they will have whatever values that happened to be stored in their allocated memory space).
Accessing hidden attributes An instance variable hidden by a local variable (having the same name) can be accessed in a method by:
this.variableName
(this is a reference to the current object)
Such a hidden data member can be accessed in the member function by:
ClassName::variableName
or
this->variableName
(this here is a pointer to the current object)
Access modifiers Each instance variable or method declaration in a Class definition must be preceded by an access modifier. Access modifiers are followed by a colon and apply to all following member declarations until overridden by another access modifier. If they were omitted they are implicitly applied by the compiler:
for classes: members are private by default.
for structs: members are public by default.
Package access Members that have no access modifier preceding their declaration are accessible to all the classes included in the same package. Members are either public or private and the only way that another class could access a non-public member of a different class is by inheritance of protected members or by being declared as a friend class of that class.
Memory leaks Are less likely to occur because Java performs automatic garbage collection to help return memory back to the system. When an object is no longer used in a program ( there are no references to the object e.g. if null was assigned to the objects reference ) it is marked for garbage collection. Before the garbage collector returns memory resources to the system it calls the finalize method of the object to be destroyed. Are common because memory is not automatically reclaimed to the system it is the programmer's responsibility to do that himself by freeing the memory in the Class destructor when its task is over.
Multiple inheritance Is not supported but interfaces are supported that allow a class to acquire multiple functionalities from any number of interfaces Is supported.
Over-ridden superclass methods Can be accessed from the subclass by:
super.methodName();
Such an over-ridden base-class member function can be accessed by the derived class by:
BaseClassName::functionName();
Calling superclass constructor To explicitly call the superclass Parent constructor from the subclass Child constructor:
public Child( int a, int b )
{
super( a );
x = b;
}
The calling statement must be the first statement in the subclass constructor
To do the same thing here it goes like this:
Child( int a, int b )
: Parent( a )
{
x = b;
}
here we use the member initializer ( : ) to call the Parent constructor before the body of the constructor is executed
Polymorphism and dynamic binding Applies automatically.
When a reference to a subclass object is assigned to a superclass reference which is then used to invoke a superclass method that is overridden in the subclass definition the java compiler only checks that the class of the reference really has that method and the java interpreter calls the method of the actual data type of the object at execution time.
Does NOT apply automatically.
When a pointer to a derived-class object is assigned to a base-class pointer which is then used to invoke a base-class member function that is overridden in the derived class definition the compiler treats the object exactly as an object of the base-class and the base-class member function is called for the object. This is overcome by declaring the function to be a vertual one and in this case the compiler generates code that would at run time access the appropriate version of the function for the actual object's data type.
final methods and final classes

A method that is declared final cannot be overridden in a subclass.

A class that is declared final cannot be a superclass( cannot have subclasses).

Does not have an equivalent in C++
const functions Java has no equivalent for C++'s const functions A member function can be declared as const, indicating that calling that member function does not change the object.
Abstract classes Are declared by using abstract and have one or more abstract mehtods
public abstract ClassName {
private int instanceVariable;
public int someMethod1()....
public void someMethod2()...
public abstract int method();
//abstract method
}
Must have one or more pure virtual functions
class ClassName {
public:
virtual int someFunction1()...
virtual int someFunction2()...
virtual int function() = 0;
// pure virtual funtion
private:
int dataMember;
...
};
GUI support Normally has packages that support frames, windows, Graphical User Interface components. Does not normally support them. Appropriate third party libraries must be obtained to offer their support.

Thursday, June 28, 2007

Java vs. C++ - Part One

Java vs. C++ - Part One

These are only some of the differences between Java and C++ that I found so far that drew my attention and I think are worth mentioning.

JavaC++
Compiling source codeWhen we compile a source file a .class file is generated in java byte-codes ( machine independent = portability ) that is not translated into machine language instructions until in the run time when interpreted by the Java Virtual Machine
( machine dependent ).
A source file is compiled and linked to produce an .exe file in machine language that is ready to be executed when the file is loaded into memory and run by the operating system.
Function definitions All function definitions and variable declarations are inside Classes even main(). Nothing is allowed to be outside a class except imports and package names.Function definitions are outside class definitions. They have prototypes whose place decides function scope
Including classesImporting a package.* just directs the compiler to the location of classes used in the code so that only these classes are included not the whole package. while in C++ I think that including a header file means that all classes in that header file will be compiled and linked to the source file.
Ending class definitionsClass definitions end with } without a semicolon.Class definitions end with };
Creating objectsAll objects must be created with new, so they are all dynamically allocated in the heap.
Only primitive data types can be allocated on the stack.
Objects can also be created and allocated without new so they are put on the stack in the scope of their declaration.
Declaring a reference:Declaring a reference to an object without using new to allocate the object only reserves space for the reference and no object is created in memory until new is used and the resulting object is given to the reference to point to it.Declaring an object without initializing it makes the compiler call the default constructor for the object's class and memory is allocated for the object in the stack.
Calling static methodsClassName.methodName( args.. );ClassName::functionName( args.. );
or ObjectName.functionName( args..);
Wrapper classesJava has wrapper classes for primitive data types that contains static methods for handling them
e.g. String string = Integer.toString( intVariable );
C++ doesn't normally have them in its standard libraries
Array declaration and memory allocation:An array is considered an object that has to be allocated by new.
   int c[];

declares the array reference

   c = new int[ 12 ];

allocates the array and automatically initialize its elements to zero for numeric primitive types, false for boolean, null for references ( non-primitive types)
or

   int c[] = new int[ 12 ];
// in one step

you can never specify the number of elements in the [] in a declaration unlike C++.

For multiple array declarations:

   double a[], b[];     

a = new double[ 100 ];
b = new double[ 27 ];

or

double a[] = new double[ 100 ],
b[] = new double[ 27 ];
or
double[] a, b;

a = new double[ 100 ];
b = new double[ 27 ];

or

double[] a = new double[ 100 ],
b = new double[ 27 ];

Elements of an array of a primitive data type contain values of that data type.
While elements of an array of a non-primitive data type contian "references" to objects of that data type.

( they have the value null by default )

Allocating and initializing arrays in declarations:

   int n[] = { 32, 27, 64, 18, 95,
14, 90, 70, 60, 37 };
// initializer list

Array size is determined by the number of elements in the list. Here new operator is provided by the compiler and the array object is also dynamically allocated.

When a Java program is executed. the Java interpreter checks array element subscripts to be sure they are valid. If there is an invalid subscript, Java generates an exception: ArrayIndexOutOfBoundsException.

   int c[ 12 ];

declares and allocated memory for 12 int elements without initializing them also memory is not dynamically allocated but instead it is preserved from the start and is allocated in the stack I presume.
For multiple array declaration:

   double a[ 100 ],
b[ 27 ];

Elements of an array of any data type contain values or objects of that data type.
Objects for which an array can be declared must have a default constructor to be called for every element when the array is declared.

initializing arrays in declarations:

   int n[ 10 ] = { 0 };

initialize elements of array n to 0

   int n[] = { 1, 2, 3, 4, 5 };

array size determined by the number of elements in the list

No checking for array bounds is done by the compiler so the programmer must be very carful not to exceed the array length

Multiple subscripted arrays

Doesn't directly support multiple-subscripted arrays but allows the programmer to specify single-subscripted arrays whose elements are also single-subscripted arrays, achieving the same effect.
i.e. arrays of arrays:

   int b[][] = { { 1, 2 },
{ 3, 4, 5 } };

b[ 0 ] is a reference to an array of 2 elements
b[ 1 ] is a reference to an array of 3 elements

   int b[][];
b = new int[ 3 ][ 3 ];

3 by 3 array allocated

   int b[][];
b = new int[ 2 ][];

allocates rows

   b[ 0 ] = new int[ 5 ];

allocates columns for row 0

   b[ 1 ] = new int[ 3 ];

allocates columns for row 1

Directly supports multiple-subscripted arrays and their elements are placed consecutively in memory row after row and the elements are actually located by pointer arithmetic.

   int b[][] = { { 1, 2 },
{ 3, 4, 5 } };

causes an error in C++ "error: declaration of 'b' as multidimensional array must have bounds for all dimensions except the first."

   int b[][ 3 ] = { { 1, 2 },
{ 3, 4, 5 } };

declares and preserves memory for a 2 by 3 multidimensional array b and initializes missing element in the list b[ 0 ][ 2 ] by 0.

Passing arguments

Java does not allow the programmer to decide whether to pass an argument call-by-value or call-by-reference:
Primitive data type variables are always passed call-by-value.
Objects are not passed to methods; references to objects are passed
(call-by-value just like pointers in C++ are) so the method can manipulate the object directly.

You can pass primitive data types or objects either call-by-value or call-by-reference ( using pointers or references to them ).

Returns

When returning information from a method via a return statement:

Primitive data type variables are always returned by value (a copy is returned).
Objects are always returned by reference - a reference to the object is returned.

Objects and primitive data type variables can be returned by value or by reference

Constant variables

Constant variables ( read only variables ) are declared using final.

They are declared using const.

Wednesday, May 23, 2007

Virtual functions in C++




"In order to implement the concept of Polymorphism which is a corner-stone of OOP the C++ compiler has to find a way to make it possible."


Lets see how the story begins.

Derived classes inherit member functions of the base class but when some member functions are not exactly appropriate for the derived class they should provide their own version of these functions to override the immediate base class' functions and make their own objects happy. So if any of these functions is called for a derived object the compiler calls its class' version of that function.

This works quite fine when the types of objects are known at compile time so that the compiler knows which function to call for each particular object. The compiler knows where to find the copy of the function for each class and so the addresses used for these function calls are
settled at compile time. ( static binding )

Suppose that we have a lot of derived objects at different levels of the inheritance hierarchy that have a common base class and that they need to be instantiated at run time. Here the compiler does not know in advance what derived class objects to expect. These objects would be dynamically allocated and the code for handling these objects should be able to deal with all them.

It is perfectly legitimate to use base class pointers to point to these objects but that requires the compiler to handle them exactly the same way they would handle their base class objects. So they would call base class versions of member functions and none of the member functions specific for the derived class would be accessible.

To solve this problem
Virtual functions are used to allow dynamic binding.

"...It seems that our friend, the compiler of course, is very resourceful."


To support Polymorphism at runtime the compiler builds at compile time
virtual function tables ( vtables ). Each class with one or more virtual functions has a vtable that contains pointers to the appropriate virtual functions to be called for objects of that class. Each object of a class with virtual functions contains a pointer to the vtable for that class which is usually placed at the beginning of the object.

The compiler then generates code that will:

1. dereference the base class pointer to access the derived class object.
2. dereference its vtable pointer to access its class vtable.
3. add the appropriate offset to the vtable pointer to reach the desired function pointer.
4. dereference the function pointer to execute the appropriate function.

This allows dynamic binding as the call to a virtual function will be
routed at run time to the virtual function version appropriate for the class.

Impressive isn't it?

Well that made me try just for fun to write code that would do these steps instead of the compiler.

But as I did this another question evolved.

How does member functions get their "this" pointer ? ( pointer to the object the function is called for )

I know that the compiler should implicitly pass 'this' as an argument to the member function so that it can use it to access data of the object it is called for.

I used in my example a single virtual function that takes no arguments and returns void.
So at first I tried calling the destination virtual function with no arguments. The function was called already but the results showed it has used some false value for 'this' that pointed it somewhere other than the object and gave the wrong results.

So I tried calling the function and passing it the pointer to the object and it seemingly worked just fine.

Here's the code I tried...


#include <iostream>

using std::cout;
using std::endl;

class Parent {
public:
   Parent( int = 0, int = 0 );  // default constructor
   void setxy( int, int );
   int getx() const { return x; }
   int gety() const { return y; }
   virtual void print();
private:
   int x;
   int y;
};

Parent::Parent( int a, int b )
{
   setxy( a, b );
}

void Parent::setxy( int a, int b )
{
   x = ( a >= 0 ? a : 0 );
   y = ( b >= 0 ? b : 0 );
}

void Parent::print()
{
   cout << " [ x: " << a =" 0," b =" 0," c =" 0" d =" 0" z =" (">= 0 ? c : 0 );
   t = ( d >= 0 ? d : 0 );
}

void Child::print()
{
   Parent::print();
   cout << " [ z: " << int =" 0," int =" 0," int =" 0," int =" 0," int =" 0);" e =" (">= 0 ? num : 0 );
}

void GrandChild::print()
{
   Child::print();
   cout << " [ e: " << e << " ]";
}

int main()
{
   Parent parentObj( 7, 8 );
   Child childObj( 56, 23, 6, 12 );
   GrandChild grandchildObj( 4, 64, 34, 98, 39 );
   
   // declare an array of pointers to Parent
   Parent *parentPtr[ 3 ];          

   cout << "size of Parent = " << sizeof( Parent ) << " bytes\n";
   cout << "size of Child = " << sizeof( Child ) << " bytes\n";
   cout << "size of GrandChild = "
        << sizeof( GrandChild ) << " bytes\n";


   parentPtr[ 0 ] = &parentObj;      // direct assignment
   parentPtr[ 1 ] = &childObj;       // implicit casting
   parentPtr[ 2 ] = &grandchildObj;  // implicit casting

   cout << "\nThe Derived objects accessed by"
         " an array of pointers to Parent:\n\n";

   for ( int i = 0; i < 3; i++ ) {
      cout << "Object " << i + 1 << " : ";
      cout << "\tvtable ptr (" << *( ( void ** ) parentPtr[ i ] ) << ")\n" ;
                  // vtable ptr at the beginning of the object
    
      // initialize pointer to function
      void (* funptr ) ( Parent * ) = NULL;       

      // assign to it pointer to function in vtable    
      funptr = *( *( ( void (*** ) ( Parent * ) ) parentPtr[ i ] ) );
    
      cout << "\t\tpointer 1 in vtable is (" << ( void * ) funptr
           << ")\n\t\t( pointer to virtual function 1 'print()' )";

      cout << "\n\n\t\tdata: ";

      funptr( parentPtr[ i ] ); // call the 1st function in vtable
                               // and passing ( this ) to it
                              // without using parentPtr[ i ]->print();
      cout << "\n" << endl;
   }

   return 0;
}
The output should look like this:


size of Parent = 12 bytes
size of Child = 20 bytes
size of GrandChild = 24 bytes

The Derived objects accessed by an array of pointers to Parent:

Object 1 : vtable ptr (0043FD90)
pointer 1 in vtable is (00401480)
( pointer to virtual function 1 'print()' )

data: [ x: 7, y: 8]

Object 2 : vtable ptr (0043FD80)
pointer 1 in vtable is (004015B8)
( pointer to virtual function 1 'print()' )

data: [ x: 56, y: 23] [ z: 6, t: 12]

Object 3 : vtable ptr (0043FD70)
pointer 1 in vtable is (004016E6)
( pointer to virtual function 1 'print()' )

data: [ x: 4, y: 64] [ z: 34, t: 98] [ e: 39 ]



In order to reach the function pointer to the desired function ( print() ) the parentPtr of the object which normally points to its beginning had to be casted to type pointer to pointer to pointer to function before it was dereferenced to give the vtabel pointer and then dereferenced again to give the first pointer to function in the vtable.

Polymorphism uses virtual functions in another interesting way. Virtual functions enables us to create special classes for which we never intend to instantiate any objects. These classes are called abstract classes and they only used to provide an appropriate base class that passes a common interface and/or implementation to their derived classes.

Abstract classes are not specific enough to define objects. Concrete classes on the other hand have the specifics needed to have a real object. To make a base class abstract it must have one or more pure virtual functions which are those having = 0 added at the end of its function prototype.

virtual void draw() const = 0;


These pure virtual functions should be all overridden in the derived classes for these to be concrete ones or else they would be abstract classes too.

Suppose we have a base class Hardware. We can never draw, print the production date or price unless we know the exact type of hardware we're talking about. So it looks that class Hardware could make a good example for an abstract base class.

Another example could be class Furniture and it might look something like this:

Class Furniture {
public:
// ...
   virtual double getVolume() const = 0; // a pure virtual
                                          function
   virtual void draw() const = 0;       // another one here
// ...               
}

Here class Furniture definition contains only the interface and implementation to be inherited.
It even does not contain any data members.

That's it.
Hope you liked this article.

I will be happy to receive your comments.