Language Equivalences: Java, C and C++


Java 
Author: Prof. Rahul Simha
(ANSI) C 
Author: Prof. Rahul Simha
(ANSI) C++ 
Author: Rizwan Sattar
A.  Overview  About Java: 
  • Java is a programming language and programming system developed at SUN Microsystems in 1995. 
  • Java really consists of (1) the programming language (which is compiled to bytecode), (2) the Java Virtual Machine (which interprets bytecode) and (3) the Java API (libraries). 
  • Since Java 1.1, no new syntax or reserved words have been added; however, the API has grown significantly from Java 1.1 to Java 1.2. 
More
About C: 
  • C was developed at (the then) Bell Laboratories in 1972. 
  • C usually refers to the programming language and a modest standard library. 
  • ANSI C is a "standard" version of C, although other versions continue to be used today. 

About C++:

  • Written by Bjarne Stroustrup around 1983
  • Acheived goals: More scalable than C, more reusable (libraries)
  • Can be thought of as superset of C; possible to write C code on a C++ compiler
  • Stricter than C
  • Support for Object-Oriented Programming (OOP) and more data abstractions

 

B.  Hello World
1.  Code  Here is the customary Hello-World program in Java, in a plain text file called HelloWorld.java
public class HelloWorld {
  public static void main (String[] argv)
  {
    System.out.println ("Hello World!");
  }
}
  
More
Here is the customary Hello-World program in C, in a plain text file called helloworld.c
#include <stdio.h>

int main ()
{
  printf ("Hello World!\n");
}
  

Here is the customary Hello-World program in C++, in a plain text file called helloworld.cpp

#include <iostream>
using namespace std;
main() 
{
    cout << "Hello World!" << endl;
}

Since C++ is a superset of C, one can also use the printf() function if they want:

#include <iostream>
using namespace std;
main() 
{
    printf("Hello World!\n");
}


2.  Compiling and executing  For compilation and execution, you will either use a GUI-based development environment or a standalone compiler/interpreter invoked from the commandline of the operating system. The following example assumes you are using the standard Java tools on Unix: 
  • Save the above code in a plain text file called HelloWorld.java
  • Compile the file using the javac compiler by typing javac HelloWorld.java at the Unix prompt. 
  • Execute the file using the java interpreter by typing java HelloWorld at the Unix prompt. 
Note: 
  • You need to set up your Unix shell path variables to be able to invoke the compiler and interpreter. 
  • The file name must be the same as the class name HelloWorld, but with a .java extension. 
  • The procedure is similar from the DOS prompt on Windows, once the paths are set up properly. 
  • You can download the JDK (Java Development Kit) from SUN and install it yourself - it comes with the compiler and interpreter, among other tools. 
For compilation and execution, you will either use a GUI-based development environment or a standalone compiler invoked from the commandline of the operating system. The following example assumes you are using the "gcc" C compiler on Unix: 
  • Save the above code in a plain text file called, say, helloworld.c
  • Compile the file using the gcc compiler by typing gcc -ansi helloworld.c -o helloworld at the Unix prompt. 
  • Execute the file by typing helloworld at the Unix prompt. 
Note: 
  • Most Unix installations nowadays include "gcc", so you should have no trouble accessing the compiler. 
  • On Windows, you are more likely to use Visual C/C++. However, "gcc" is also available for Windows. 

For compilation and execution, you will either use a GUI-based development environment or a standalone compiler invoked from the commandline of the operating system. The following example assumes you are using the "gcc" C/C++ compiler on Unix:

  • Save the above code in a plain text file called helloworld.cpp
  • Compile the file using the gcc compiler by typing g++ helloworld.cpp -o helloworld at the Unix prompt.
  • Execute the file by typing helloworld at the Unix prompt.

Note:

  • Most Unix installations nowadays include "gcc", so you should have no trouble accessing the compiler.
  • On Windows, you are more likely to use Visual C/C++. However, "gcc" is also available for Windows
C.  Lexical 
1.  Reserved words  Java's reserved words (some are not in use today): 

abstract, 
boolean, break, byte, 
case, catch, char, class, const, continue, 
default, do, double, 
else, extends, 
false, final, finally, float, for, 
goto, 
if, implements, import, instanceof, int, interface, 
long, 
native, new, null, 
package, private, protected, public, 
return, 
short, static, super, switch, synchronized, 
this, throw, throws, transient, true, try, 
void, volatile, while 

C's reserved words: 

auto, 
break, 
case, char, const, continue, 
default, do, double, 
else, enum, extern 
float, for, 
goto, 
if, int, 
long, 
register, return, 
short, signed, sizeof, static, struct, switch, 
typedef, 
union, unsigned, 
void, volatile, while 

C++ Reserved Words:

asm, auto,
break,
case, catch, char, class, const, continue,
default, delete, do, double,
else, enum, extern,
float, for, friend,
goto,
if, inline, int,
new,
operator,
private, protected, public,
register, return,
short, signed, sizeof, static, struct, switch,
template, this, throw, try, typedef,
union, unsigned,
virtual, void, volatile,
while

2.  Identifiers  About Java identifiers: 
  • An identifier must begin with a letter or underscore 
  • An identifiers can contain any number of letters, digits, or underscores. 
  • Case (upper or lower) is significant. 
  • No Java reserved word can be used as an identifier. 
  • Identifiers can actually be more complex when using Unicode characters, allowing currency symbols. But these are best avoided. 
  • Examples of legal identifiers: 

  • i
    really_important_integer_for_counting_lines_in_a_text_file (bad style) 
    num_lines_in_file (acceptable) 
    numLinesInFile (recommended) 
About C identifiers: 
  • An identifier must begin with a letter or underscore 
  • An identifiers can contain any number of letters, digits, or underscores. 
  • Case (upper or lower) is significant. 
  • No C reserved word can be used as an identifier. 
  • Examples of legal identifiers: 

  • i
    really_important_integer_for_counting_lines_in_a_text_file (bad style) 
    num_lines_in_file (acceptable) 
    numLinesInFile (recommended) 

About C++ indentifiers:

  • An identifier can contain the characters A-Z (upper and lower case) and the numbers 0-9
  • All other characters are illegal
  • An identifier must begin with a letter or an underscore
  • No C++ reserved word can be used as an identifier
  • Examples of legal identifiers:

i
really_important_integer_for_counting_lines_in_a_text_file (bad style) 
num_lines_in_file (acceptable) 
numLinesInFile (recommended) 

3.  Whitespace 
  • Whitespace between keywords, symbols and identifiers is compressed: 
  • End-of-line is ignored except in the middle of strings, in which case it is not permitted. 
  • Whitespace in comments is not processed by the compiler. 
Example: 
//           Comment1 

public    class     WhiteSpaceExample {

        // Comment2 

  public static void main (String[] argv) 
  {
    // Comment3 
  }
  
}
  
  • Whitespace between keywords, symbols and identifiers is compressed: 
  • End-of-line is ignored except in the middle of strings, in which case it is not permitted. 
  • You can continue a line onto the following line by ending the line with a backslash. 
  • Preprocessor commands must begin a line with the # symbol. 
  • Whitespace in comments is not processed by the compiler. 
Example: 
#include <stdio.h>

int       main ()
      {
  printf    (    "Hello \
World!\n")   ;
}
 
  • Whitespace between keywords, symbols and identifiers is compressed: 
  • End-of-line is ignored except in the middle of strings, in which case it is not permitted. 
  • You can continue a line onto the following line by ending the line with a backslash. 
  • Preprocessor commands must begin a line with the # symbol. 
  • Whitespace in comments is not processed by the compiler. 
Example: 
#include <iostream>
using namespace std;

int       main ()
      {
  cout    <<   "Hello \
World!\n"   ;
}
 
4.  Escapes  C-type escape characters in Java: 
\b (backspace), 
\f (form feed), 
\n (new line), 
\r (return), 
\t (tab), 
\" (double quote), 
\' (single quote), 
\\ (backslash), 
\xxx (Latin-1 characters, where x is octal). 
Unicode characters: 
\uxxxx (x is hexadecimal), 
Escape characters in C: 
\a (alert), 
\b (backspace), 
\f (form feed), 
\n (new line), 
\r (return), 
\t (tab), 
\v (vertical tab), 
\" (double quote), 
\' (single quote), 
\\ (backslash), 
\? (question mark), 
\xxx (Latin-1 characters, where x is octal). 

Escape characters in C++:

\a
 
sounds a beep
\n
 
new line 
\'
 
single quote 
\\
 
backslash 
\b
 
backspace
\t
 
tab 
\"
 
double quote
\'
 
single quote
\?
 
question mark
\xxx
 
Latin-1 characters, where x is octal









5.  Comments  There are three types of comments in Java: 
  1. In-line comments, using // that comment out everything up to end of the current line. 
  2. Block comments (C-style) using /* and */ that comment out everything in between. 
  3. Documentation comments using /** and */ that are used by the javadoc utility to produce documentation. 
Example: 
// This is an in-line comment. It ends at the end of this line.

/* Long comments are best
   placed inside block comments
   like this, (but do not nest). */

/** 
 * Finally, there is the type of documentation that
 * javadoc produces. To use this, you need to use javadoc
 * commands inside the comment block, such as:
 * @version 1.1
 * @author Rahul Simha
 * @return No value returned
 * @param  command arguments (any number of strings)
 * Note: each line must start with a `*' symbol.
 */

// javadoc will produce HTML documentation. 
Comments in C begin with /* and end with */. ANSI C does not allow such comments to nest, although some C compilers will allow it; also some compilers allow C++/Java single-line comments, but ANSI C does not. 

Example:

#include <stdio.h>

/* A simple C program that prints
   something to the screen. */

int main ()
{
  printf ("Hello World!\n");   /* Notice the escape char. */
}

Comment in C++ can either be single line (//) or a block (/* ...... */):

Example:

// This is a single-line comment

main() 
{
// This is another single line comment /* this is a block comment which will be a comment until the the block is ended */ }
D.  Data Types 
1. Characters A character in Java: 
  • requires 2 bytes of storage; 
  • is stored in Unicode format; 
  • is declared using the char keyword; 
  • uses single quotes for constants. 
Example: 
public class TestChar {
  public static void main (String[] argv)
  {
    // Declare a char variable called "myFavoriteChar".
    char myFavoriteChar;
    // Assign to it the constant 'z', using single quotes.
    myFavoriteChar = 'z';
    // Print a message out (without a newline).
    System.out.print ("What I sound like: ");
    // Print out the char variable contents.
    System.out.println (myFavoriteChar);
  }
}
  
A character in C: 
  • does not specify required storage; 
  • does not have a standard format; 
  • is declared using the char keyword; 
  • uses single quotes for constants. 
Example: 
#include <stdio.h>

int main ()
{
  /* Declare a char variable called "myFavoriteChar". */
  char myFavoriteChar;
  /* Assign to it the constant 'z', using single quotes. */
  myFavoriteChar = 'z';
  /* Print a message out (without a newline). */
  printf ("What I sound like: ");
  /* Print out the char variable contents. */
  printf ("%c\n", myFavoriteChar);
}
  
Note: 
  • C does not specify the format or size of data types; programmers need to be aware of formats on different systems. 
  • ANSI C allows char types to be signed or unsigned, which can create confusion when the customary "-1" is returned to signify end-of-file. In this case, it is better to use an int and then cast to a char after determining you have a valid character. 
  • ANSI C allows a "wider" character type called wchar_t

A character in C++:

  • 1 byte variable
  • represents a single ASCII character
  • is declared using the char keyword; 
  • uses single quotes for constants. 

Example:

#include <iostream>
using namespace std;
int main() 
{
    // Declare a char variable called "myFavoriteChar"
    char myFavouriteChar = 'z';

    // Print a message out (without a newline)
    printf("What I sound like: ");

    // Print out the char variable contests
    printf("%c\n", myFavouriteChar);

    // Can even store the letter 'A' by it's ASCII code:

    char oneLetter = 65;    // Same as 'A'
}

 

2. Integers  Java has four integer types: 
  1. byte
    • 1 byte of storage. 
    • Range: -128 to 127. 
  2. short
    • 2 bytes of storage. 
    • Range: -32,768 to 32,767. 
  3. int
    • 4 bytes of storage. 
    • Range: -2,147,483,648 to 2,147,483,647. 
  4. long
    • 8 bytes of storage. 
    • Approximate range: -9 x 10^{18} to 9 x 10^{18}. 
    • Literals end in L
Note: 
  • Integer literals can also be specified using octal or hexadecimal. 
  • Long literals end in "L". 
Example: 
public class TestInt {
  public static void main (String[] argv)
  {
    // Declare a byte variable "b" and assign an octal value to it.
    byte b = 012;
    // Declare a short variable "s" and assign a hexadecimal value to it.
    short s = 0xA;
    // Declare an int variable "i" and assign a decimal value to it.
    int i = 10;
    // Declare a long variable "j" and assign a long decimal value to it.
    long j = 10000000L;

    // Print them all.
    System.out.println ("b=" + b);
    System.out.println ("s=" + s);
    System.out.println ("i=" + i);
    System.out.println ("j=" + j);
  }
}
  
About C's integer types: 
  • C has three basic integer types: short, int and long
  • There are also modifiers: signed and unsigned
  • Confusingly, long can also be used as a modifer for int
  • ANSI requires at least 16 bits for an int, and that the number of bits used for short, int and long be non-decreasing. 
  • ANSI C requires that implementations document their ranges in a file called limits.h, usually in a system directory. 
Example: 
#include <stdio.h>

int main ()
{
  /* Declare a "short" variable and assign a value to it. */
  short i = 1;

  /* Likewise, declare int's, long's etc. */
  int j = 2;
  long k = 3;
  signed int m = -4;
  unsigned long int n = 1000000L;

  /* Print to screen. */
  printf ("i=%d\n", i);
  printf ("j=%d\n", j);
  printf ("k=%ld\n", k);
  printf ("m=%d\n", m);
  printf ("n=%ld\n", n);
}
  
About C++'s integer types: 
  • C++ has three basic integer types: short, int and long
  • There are also modifiers: signed and unsigned
  • Confusingly, long can also be used as a modifer for int
  • ANSI requires at least 16 bits for an int, and that the number of bits used for short, int and long be non-decreasing. 
  • ANSI C requires that implementations document their ranges in a file called climits, usually in a system directory. 
Example: 
#include <iostream>
using namespace std;

int main ()
{
  /* Declare a "short" variable and assign a value to it. */
  short i = 1;

  /* Likewise, declare int's, long's etc. */
  int j = 2;
  long k = 3;
  signed int m = -4;
  unsigned long int n = 1000000L;

  /* Print to screen. */
  cout << "i=" << i << endl;
  cout << "j=" << j << endl;
  cout << "k=" << k << endl;
  cout << "m=" << m << endl;
  cout << "n=" << n << endl;
}
  
3. Reals  Java has two floating point types: 
  • float
    • 4 bytes of storage. 
    • Approx. range: +/- 3.40282347 x 10^{38}. 
    • 6-7 digits of accuracy. 
    • floatliterals end with a F 
    • If a real-valued literal does not end in F, it's assumed to be a double
  • double
    • 8 bytes of storage. 
    • Approx. range: +/- 1.7 x 10^{308}. 
    • About 15 digits of accuracy. 
Example:
public class TestReal {
  public static void main (String[] argv)
  {
    float f = 3.141F;
    double d = 3.14159265;

    System.out.println ("Pi=" + f);
    System.out.println ("Pi2" + d);
  }
}
  
About C's floating point types: 
  • There are two types: float and double
  • The modifier long can be applied to double
  • As with integers, C does not dictate the storage size used for these types. 
  • ANSI C requires that an implementation describe size information in float.h
Example: 
#include <stdio.h>

int main ()
{
  float f = 3.141;
  double d = 3.14159;
  long double ld = 3.14159265;

  printf ("Pi = %f\n", f);
  printf ("Pi2 = %4.2lf\n", d);   /* Specify precision. */
  printf ("Pi3 = %10.8e\n", ld);  /* Use exp notation. */
}
  
About C++'s floating point types: 
  • There are two types: float and double
  • The modifier long can be applied to double
  • As with integers, C does not dictate the storage size used for these types. 
  • ANSI C requires that an implementation describe size information in cfloat
Example: 
#include <iostream>
using namespace std;

int main ()
{
  float f = 3.141;
  double d = 3.14159;
  long double ld = 3.14159265;

  /* Use C++ style formatting for output */
  printf ("Pi = %f\n", f);
  printf ("Pi2 = %4.2lf\n", d);   /* Specify precision. */
  printf ("Pi3 = %10.8e\n", ld);  /* Use exp notation. */
}
  
4. Booleans  About Java's boolean type: 
  • Although the storage size is not specified, it's usually a byte. 
  • A boolean can only take values true or false
  • A boolean variable cannot be cast into an integer or any other type. 
Example: 
public class TestBoolean {
  public static void main (String[] argv)
  {
    boolean earthIsFlat = false;
    boolean earthIsRound = ! earthIsFlat;
    
    System.out.println ("It's " + earthIsFlat + " that the earth is flat");
    System.out.println ("It's " + earthIsRound + " that the earth is round");
  }
}
  
About boolean's in C: 
  • C has no special boolean type. 
  • Use an integer with zero for "false", and a nonzero value for "true". 
  • You can use the pre-processor to make code a little more readable. 
Example: 
#include <stdio.h>

/* These are purely for readability. */
#define false 0
#define true 1
#define boolean int

int main ()
{
  int isEarthFlat = 0;          /* False. */
  boolean isEarthRound = true;  /* More readable. */

  // Prints 0 for isEarthFlat
  printf ("It's %d that the earth is flat\n", isEarthFlat);  

  // Prints 1 for isEarthRound
  printf ("It's %d that the earth is round\n", isEarthRound);  
}
  
Here's a version without the "define's": 
#include <stdio.h>

int main ()
{
  int isEarthFlat = 0;   /* False. */
  int isEarthRound = 1;  /* True. */

  /* Prints 0 for isEarthFlat */
  printf ("It's %d that the earth is flat\n", isEarthFlat);  

  /* Prints 1 for isEarthRound */
  printf ("It's %d that the earth is round\n", isEarthRound);  
}
  
About boolean's in C++: 
  • C++ boolean is called bool
  • Can be assigned values true or false.
Example: 
#include <iostream>
using namespace std;

int main() {
bool isEarthFlat = false;
bool isEarthRound = true; // Prints 0 for isEarthFlat cout << "It's " << isEarthFlat << " that the earth is flat" << endl; // Prints 1 for isEarthRound cout << "It's " << isEarthRound << " that the earth is round" << endl;
 }
5. Enumerated Java does not support enumerated types. You can, however, simulate them with integers or strings. Here's an example using strings: 
public class TestEnum {

  static final String MONDAY = "Monday";
  static final String TUESDAY = "Tuesday";
  static final String WEDNESDAY = "Wednesday";
  static final String THURSDAY = "Thursday";
  static final String FRIDAY = "Friday";

  public static void main (String[] argv)
  {
    String lastWeekDay = FRIDAY;

    if (lastWeekDay.equals (THURSDAY))
      System.out.println ("Now, that's what I call a real work week");
  }
}
  
Example: 
#include <stdio.h>

int main ()
{
  /* Declare the enum type and the variable lastWeekDay simultaneously. */
  enum weekdays {monday, tuesday, wednesday, thursday, friday} lastWeekDay;

  /* Better way: */
  typedef enum weekendDays {saturday, sunday} weekendDayType;
  weekendDayType restDay;  /* Variable. */

  lastWeekDay = thursday;
  restDay = sunday;

  if (lastWeekDay == thursday)
    printf ("Now, that's what I call a real work week\n");
}
  
Example: 
#include <iostream>
using namespace std;
main() 
{
  /* Declare the enum type and the variable lastWeekDay simultaneously. */
  enum weekdays {monday, tuesday, wednesday, thursday, friday} lastWeekDay;

  /* Better way: */
  enum weekendDays {saturday, sunday} weekendDayType;
  weekendDayType restDay;  /* Variable. */

  lastWeekDay = thursday;
  restDay = sunday;

  if (lastWeekDay == thursday)
    cout << "Now, that's what I call a real work week" << endl;
}
5a. Scalar Subtypes Java does not support subtypes, so there is no automatic way to cause range-checking of variables. The programmer must code the range check, where appropriate, with an if statement. C does not support subtypes, so there is no automatic way to cause range-checking of variables. The programmer must code the range check, where appropriate, with an if statement. C++ does not support subtypes, so there is no automatic way to cause range-checking of variables. The programmer must code the range check, where appropriate, with an if statement.
6. Pointers Pointers in Java: 
  • Java has no pointers in the following sense: there is no way to access memory locations, or assign addresses to pointers. 
  • However, any object variable has some pointer-like properties: 
    • Object variables simply point (or refer) to object instances. 
    • Assignment between object variables only assigns references, and does not perform an object-copy. 
    • The reference is what permits us to build linked data structures. 
    • An object variable may only point to instances of that object type (or subclasses) - this will be clear after learning about Java objects. 
Pointers in C: 
  • Pointers are variables that hold references (addresses) of memory locations, which in turn typically contain data (but may contain pointers to other things). 
  • C defines the * and & operators for pointer usage. 
  • ANSI C does not guarantee that pointers can be safely cast to int's or that function pointers can be safely cast to void*
Example: 
#include <stdio.h>

int main ()
{
  int myAge;                   /* Plain "int" variable. */
  int *myAge_ptr = NULL;       /* Pointer to an int, initialized to NULL. */
  char myFirstInitial = 'R';   /* Plain "char" variable. */
  void *ptr_to_anything;       /* The unusual void pointer. */

  /* Regular "int" stuff. */
  myAge = 19;
  printf ("My age: %d\n", myAge);

  /* Use "malloc" and "sizeof" and a cast to create space
     and make the pointer point to the allocated space. */
  myAge_ptr = (int *) malloc (sizeof (int));
  /* Use the "*" de-referencing operator to get at what
     the pointer points to. */
  *myAge_ptr = 38;
  printf ("OK, I lied. It's really: %d\n", *myAge_ptr);  /* Again. */

  /* Use the "&" address-extraction operator to extract 
     an address and put it in a pointer. */
  ptr_to_anything = & (myAge);
  /* "ptr_to_anything" is of type "void*" so it needs to be cast. */
  printf ("But I look %d\n",   *( (int*) ptr_to_anything) );

  /* Different use of the same "void*" pointer. */
  ptr_to_anything = & myFirstInitial;
  printf ("My first initial: %c\n", *( (char*) ptr_to_anything) );
}
  
Pointers in C++: 
  • Pointers are variables that hold references (addresses) of memory locations, which in turn typically contain data (but may contain pointers to other things). 
  • C++ defines the * and & operators for pointer usage. 
  • ANSI C++ does not guarantee that pointers can be safely cast to int's or that function pointers can be safely cast to void*
Example: 
#include <iostream>
using namespace std;

main() {
    int myAge;                  // Plain "int" variable
    int *myAge_ptr = NULL;      // Pointer to an int, initialize as NULL
    char myFirstInitial = 'R';  // Plain "char" variable
    void *ptr_to_anything;      // The unusual void pointer

    // Regular "int" stuff
    myAge = 19;
    cout << "My Age: " << myAge << endl;

    // Use the "new" keyword to create space and make the pointer point
    // to the allocated space
    myAge_ptr = new int;

    // Use the "*" de-referencing operator to get get at what
    // the pointer points to
    *myAge_ptr = 23;
    cout << "OK, I lied. It's really: " << *myAge_ptr << endl;

    // Use the "&" address-extraction operator to extract
    // and address and put it in a pointer
    ptr_to_anything = &myAge;

    // ptr_to_anything is of type "void *" so it needs to be cast
    cout << "But I look " << *( (int*) ptr_to_anything ) << endl;

    // Different use of the same "void *" pointer
    ptr_to_anything = &myFirstInitial;
    cout << "My first initial: " << *( (char *) ptr_to_anything ) << endl;
}
7. Arrays Arrays in Java: 
  • Square brackets are used for enclosing indices. 
  • Arrays can be built out of any basic type, even objects (as we'll see later). 
  • Space for arrays is always allocated dynamically in Java. 
  • Array initializing can be done with constants. 
  • Arrays are "pseudo-objects" in Java - they have some object-like features, such as a "length" attribute. 
  • The library java.util.Array provides useful methods for manipulating arrays. 
  • Array bounds are checked at run-time. 
  • Array indices start with 0
Consider the following example using int's: 
public class TestArray {
  public static void main (String[] argv)
  {
    // Declare a simple array of int's.
    int[] intArray;
    // Assign space to it.
    intArray = new int [5];
    // Use it.
    intArray[0] = 0;
    intArray[1] = 1;  // ...etc.

    // This will cause a run-time, but not compile-time error:
    intArray[6] = 6;

    // Space can be assigned on the fly using variables.
    int[] intArray2;
    int size = 3;
    intArray2 = new int [size];
    intArray2[0] = 3;
    intArray2[1] = 4;  // ...etc.

    // Print contents. Notice the ".length" attribute:
    for (int i=0; i < intArray2.length; i++)
      System.out.println (intArray2[i]);
    
    // Multidimensional example with pre-determined sizes.
    int[][] intMatrix = new int [5][6];
    intMatrix[3][2] = 19;  // ...etc.
    
    // Preferred approach: create space on the fly.
    int[][] intMatrix2;
    int rows = 5;
    int columns = 6;
    intMatrix2 = new int [rows][];
    for (int i=0; i < rows; i++)
      intMatrix2[i] = new int [columns];

    // Now space has been allocated; use the array.
    intMatrix2[3][2] = 19;  // ...etc.

    // Example of array initialization using literals:
    int[] intArray3 = {15, 16, 17}; 

    // A 2D example:
    int[][] intMatrix3 = {  {15, 16, 17},
                            {19, 20, 21},
                            {22, 23, 24}  };
  }
}
  
Arrays in C: 
  • Square brackets are used for enclosing indices. 
  • Arrays can be built out of any basic type. 
  • Space can be allocated both statically and dynamically (using malloc). 
  • Array initializing can be done with constants. 
  • Array bounds are not checked at run-time. 
  • Array indices start with 0
Example: 
#include <stdio.h>

int main ()
{
  /* Need to declare all variables before other statements. */
  int intArray[5];        /* Example 1: Declare a size-5 array. */
  int *intArray2;         /* Example 2: Dynamically assign space. */
  int intMatrix[5][6];    /* Example 3: Static space for 2D array. */
  int **intMatrix2;       /* Example 4: Dynamic allocation for 2d array. */
  int size;               /* Used in Example 2. */
  int rows = 5;           /* Used in Example 4. */
  int columns = 6;        /* Used in Example 4. */
  int value;              /* Used in several examples. */
  int i;                  /* For loop variables. */

  /* Example 1. */
  intArray[0] = 0;
  intArray[1] = 1;

  /* No run-time checking, can cause error. */
  intArray[6] = 7; 

  /* Example 2: dynamic allocation of space using malloc. */
  size = 3;
  /* Notice "sizeof" operator. */
  intArray2 = (int*) malloc (sizeof(int) * size);
  intArray2[0] = 3;
  intArray2[1] = 4;

  /* Example 3: 2D statically allocated space. */
  intMatrix[3][2] = 19;

  /* Example 4: 2D dynamic allocation. */
  intMatrix2 = (int**) malloc (sizeof (int*) * rows);
  for (i=0; i < rows; i++)
    intMatrix2[i] = (int*) malloc (sizeof (int) * columns);
  intMatrix2[3][2] = 19;

  /* Using the array-variable-as-pointer approach: 1D case. */
  value = *(intArray + 1);
  printf ("intArray[1] = %d\n", value);

  /* Using the array-variable-as-pointer approach: 2D case. */
  value = *( (*(intMatrix + 3)) + 2);
  printf ("intMatrix[3][2] = %d\n", value);

  /* If possible, avoid using the pointer approach! */
}
  
Arrays in C++: 
  • Square brackets are used for enclosing indices. 
  • Arrays can be built out of any basic type. 
  • Space can be allocated both statically and dynamically (using new). 
  • Array initializing can be done with constants. 
  • Array bounds are not checked at run-time. 
  • Array indices start with 0
Example: 
#include <iostream>
using namespace std;

main ()
{
  // Need to declare all variables before other statements.  
  int intArray[5];        // Example 1: Declare a size-5 array.
  int *intArray2;         // Example 2: Dynamically assign space.
  int intMatrix[5][6];    // Example 3: Static space for 2D array.
  int **intMatrix2;       // Example 4: Dynamic allocation for 2d array.
  int size;               // Used in Example 2.
  int rows = 5;           // Used in Example 4.
  int columns = 6;        // Used in Example 4.
  int value;              // Used in several examples.
  int i;                  // For loop variables.
  // Example 1.
  intArray[0] = 0;
  intArray[1] = 1;

  // No run-time checking, can cause error.
  intArray[6] = 7; 

  // Example 2: dynamic allocation of space using new.
  size = 3;
  intArray2 = new int[size];
  intArray2[0] = 3;
  intArray2[1] = 4;

  // Example 3: 2D statically allocated space.
  intMatrix[3][2] = 19;

  // Example 4: 2D dynamic allocation.
  intMatrix2 = new int*[rows];
  for (i=0; i < rows; i++)
      intMatrix2[i] = new int[columns];

  intMatrix2[3][2] = 19;

  // Using the array-variable-as-pointer approach: 1D case.
  value = *(intArray + 1);
  cout << "intArray[1] = " << value << endl;

  // Using the array-variable-as-pointer approach: 2D case.
  value = *( (*(intMatrix + 3)) + 2);
  cout << "intMatrix[3][2] = " << value << endl;

  // If possible, avoid using the pointer approach!

}
8. Strings Strings in Java: 
  • Java strings are not basic types but, like arrays, are specially treated objects. 
  • String objects are special in that they have an operator, +, for concatenation. 
  • Strings are immutable. You cannot change a string; you can modify a string only by creating a new one. 
  • The library provides a number of string manipulation functions. 
Example:
public class TestString {
  public static void main (String[] argv)
  {
    String msg = "Hello World!";
    String msg2 = "Hola ";
    
    System.out.println ("English: " + msg        // Note concatenation
                        + "\n" +                 // Expressions can spill over
                        "Spanish: " + msg2 );    // lines but strings may not.

    // length() method returns # chars in string
    int i = msg.length(); 

    System.out.println ("String \""              // Note backslash-quote
                        + msg + "\" has length " 
                        + i                      // Automatic conversion 
                                                 // to string
                        + " chars");

    // Assignment
    String msg3 = msg;                           // Actually, a pointer.
                                                 // But since strings are 
                                                 // immutable, there's 
                                                 // no problem.
    System.out.println ("Third message: " + msg3);

    // Modifying strings using String methods
    String msg4 = msg.substring (0,5);           // First 5 letters
    System.out.println ("Fourth: " + msg4);

    // Picking out particular characters:
    char c1 = msg.charAt (0);
    char c2 = msg.charAt (4);
    System.out.println ("Fifth: " + c1 + c2);

    // Testing equality
    if (msg.equals (msg3))
      System.out.println (msg + " equals " + msg3);

    // Alphabetical order.
    int comp = msg.compareTo (msg2);
    if (comp < 0)
      System.out.println (msg + " comes before " + msg2);
    else if (comp > 0)
      System.out.println (msg + " comes after " + msg2);
    else 
      System.out.println (msg + " equals " + msg2);
  }
}
  
Strings in C: 
  • C string variables are declared as char* pointers or as char arrays. 
  • The library provides a number of string manipulation functions. 
  • A string constant is null-terminated when you use a char* variable: a '\0' character is appended to the string. 
  • The printf function expects a null-terminated string for its %s placeholder. 
  • The library includes functions for: string concatention, tokenizing, substring search, copying and conversion. 
Example: 
#include <stdio.h>
#include <string.h> /* C's string manipulation library. */

int main ()
{
  /* Strings are declared as "char*" or an array of chars. */
  char *msg = "Hello World!";
  /* There are 5 chars pointed to by "msg2": the last is the null-char. */
  char *msg2 = "Hola";
  char *msg3;
  char msg4[11] = "Bye World!";     
  /* Must have enough space in the array for the string. 
     Note: a null-char is not appended automatically. */
  char *msg5;
  int len;
  int comp;
  int i;

  /* Note how "%s" is a placeholder for the string. */
  printf ("English: %s \nSpanish: %s\n", msg, msg2);
  
  /* "strlen" is a library function. */
  len = strlen (msg);
  printf ("String \"%s\" has length %d chars\n", msg, len);

  /* Simple pointer assignment. */
  msg3 = msg;
  printf ("Third message: %s\n", msg3);

  /* "strcmp" is a library function. */
  comp = strcmp (msg, msg2);
  if (comp < 0) 
    printf ("%s comes before %s\n", msg, msg2);
  else if (comp > 0)
    printf ("%s comes after %s\n", msg, msg2);
  else
    printf ("%s equals %s\n", msg, msg2);
  
  /* Let's put a non-null char (a beep) at the end of the string. */
  msg4[10] = '\a';
  /* We can make a char-pointer point to the same array. */
  msg5 = (char*) msg4;
  /* Will print out some junk because it's not null-terminated. */
  printf ("Fifth: %s\n", msg5);
  /* Moral: char arrays may not have the null-char: you have to put it in. */

  /* OK, so let's add that. */
  msg4[10] = '\0';
  /* Prints fine. */
  printf ("Fifth: %s\n", msg5);
}
  
Strings in C++: 
  • C++ string variables are declared as char* pointers or as char arrays. 
  • The library provides a number of string manipulation functions. 
  • A string constant is null-terminated when you use a char* variable: a '\0' character is appended to the string. 
  • The cout function expects a null-terminated string. 
  • The library includes functions for: string concatention, tokenizing, substring search, copying and conversion. 
Example: 
#include <iostream>
using namespace std;

#include <string.h> // String manipulation library.

int main () {
    // Strings are declared as "char*" or an array of chars.
    char *msg = "Hello World!";
    // There are 5 chars pointed to by "msg2": the last is the null-char.
    char *msg2 = "Hola";
    char *msg3;
    char msg4[11] = "Bye World!";
    // Must have enough space in the array for the string.
    //Note: a null-char is not appended automatically.
    char *msg5;
    int len;
    int comp;


    cout << "English: " << msg << endl;
    cout << "Spanish: " << msg2 << endl;

    // "strlen" is a library function.
    len = strlen (msg);
    cout << "String \"" << msg << "\" has length " << len << " chars" << endl;

    // Simple pointer assignment.
    msg3 = msg;
    cout << "Third message: " << msg3 << endl;;

    // "strcmp" is a library function.
    comp = strcmp (msg, msg2);
    if (comp < 0){
        cout << msg << " comes before " << msg2 << endl;
    } else if (comp > 0) {
        cout << msg << " comes after " << msg2 << endl;
    } else {
        cout << msg << " equals " << msg2 << endl;
    }

    // Let's put a non-null char (a beep) at the end of the string.
    msg4[10] = '\a';
    // We can make a char-pointer point to the same array.
    msg5 = (char*) msg4;
    // Will print out some junk because it's not null-terminated.
    cout << "Fifth: " << msg5 << endl;
    // Moral: char arrays may not have the null-char: you have to put it in.

    // OK, so let's add that.
    msg4[10] = '\0';
    // Prints fine.
    cout << "Fifth: " << msg5 << endl;
}
9. Structured Structured data in Java: 
  • A structured type is a way to put related data together and define variables to reference the collected data. 
  • Java does not distinguish between objects and structured types. Thus, Java's equivalent of a structured type is simply an object (class) without methods. 
  • The members are declared within brace-delimited blocks. 
  • Object variables are always pointers (more accurately, references), so assignment simply makes another variable point to the same thing. 
  • It's unusual to define classes without methods; read material on objects for better understanding. 
Example: 
class Complex {        // A "class" without methods, only data.
  double real_part;
  double imag_part;
}

class ListNode {
  Complex data;        // A member variable called "data" of type "Complex".
  ListNode next;       // Here's how to define the "next" pointer.
}


public class TestStructure {
  public static void main (String[] argv)
  {
    // Declare a "Complex" variable and allocate space.
    Complex c = new Complex();
    // Use the "." operator to access members.
    c.real_part = 1.0;
    c.imag_part = 2.0;
    System.out.println ("c: real part = " + c.real_part +
                        "   imag part = " + c.imag_part);

    // Pointer-like assignment.
    Complex c2 = c;
    c2.real_part = 3.0;    // Changes c.real_part.

    // Let's create a simple linked list and traverse it.
    ListNode front = new ListNode();
    // The data itself requires allocation of space.
    front.data = new Complex();
    front.data.real_part = c.real_part;
    front.data.imag_part = c.imag_part;
    // The variable "next" is really a sort-of pointer.
    front.next = new ListNode();
    front.next.data = new Complex();
    front.next.data.real_part = 3.0;
    front.next.data.imag_part = 4.0;
    // "null" is a keyword.
    front.next.next = null;
    
    // Traverse and print.
    ListNode temp_ptr = front;
    while (temp_ptr != null) {
      System.out.println ("real part = " + temp_ptr.data.real_part +
                          "   imag part = " + temp_ptr.data.imag_part);
      temp_ptr = temp_ptr.next;
    }
    
  }
}
  
Structured data in C: 
  • A structured type is a way to put related data together and define variables to reference the collected data. 
  • Structured types are what you use for linked data structures. 
  • C's structures cannot contain functions. 
  • The struct keyword is used to declare a structured type. 
  • The elements are declared within brace-delimited blocks. 
  • A semi-colon is required at the end of the block. 
  • Structures may nest. 
  • ANSI C requires support of the . (dot) and -> operators. 
  • Assignment between structured variables is supported by some compilers, not required by ANSI C. 
  • There is considerably more to C's struct than described here, such as "unions" and bitfields. These are best used sparingly, by an expert. 
Example: 
#include <stdio.h>

int main ()
{
  /* Define a structured type called "Complex". */
  struct Complex { 
    double real_part;
    double imag_part;
  };

  /* Define another structure for use in the classical linked list. */
  struct ListNode {
    struct Complex data;    /* You can nest structures. */
    struct ListNode *next;  /* Note how we define the "next" pointer. */
  };

  /* Declare a variable, with space allocated. */
  struct Complex c;
  /* Declare a pointer variable, with no space yet allocated. */
  struct Complex *c2;

  /* Pointers for the list. */
  struct ListNode *front;
  struct ListNode *temp_ptr;

  /* The "." operator accesses struct members. */
  c.real_part = 1.0;
  c.imag_part = 2.0;
  printf ("c: real part = %lf   imag part = %lf\n", c.real_part, c.imag_part);

  /* First allocate memory using "malloc". 
     Note "sizeof" operator and cast. */
  c2 = (struct Complex *) malloc (sizeof (struct Complex));
  /* The "->" operator accesses struct members via a pointer. */
  c2->real_part = c.real_part;
  /* Alternatively (and more confusingly) first de-reference the pointer. */
  (*c2).imag_part = c.imag_part;
  printf ("c2: real part = %lf   imag part = %lf\n", c2->real_part, c2->imag_part);

  /* Let's create a simple 2 node linked list. */
  front = (struct ListNode *) malloc (sizeof (struct ListNode));
  front->data.real_part = c.real_part;
  front->data.imag_part = c.imag_part;
  /* The assignment "front->data = c;" is allowed by some compilers. */
  front->next = (struct ListNode *) malloc (sizeof (struct ListNode));
  /* Note the use of multiple operators. Same as "(front->next)->data". */
  front->next->data.real_part = c2->real_part;
  front->next->data.imag_part = c2->imag_part;
  front->next->next = NULL;

  /* Traverse the list and print the data part. */
  temp_ptr = front;  
  /* Now "temp_ptr" and "front" point to the same thing. */
  while (temp_ptr != NULL) {
    printf ("real part = %lf   imag part = %lf\n", 
            temp_ptr->data.real_part, temp_ptr->data.imag_part);
    temp_ptr = temp_ptr->next;
  }
}
  
Structured data in C++: 
  • A structured type is a way to put related data together and define variables to reference the collected data. 
  • Structured types are what you use for linked data structures. 
  • C++ supports the use of C's struct and defines its own structured data as a class.
  • While a struct cannot contain functions, classes can.
  • A class usually represents an object with its own functions, while a struct represents data.
  • However, a class can behave like a struct if all it contains is data.
  • Thus, concept of object and structured data is more closely linked.
  • The struct keyword is used to declare a structured type. 
  • The class keyword is used to declare an object
  • The elements are declared within brace-delimited blocks. 
  • A semi-colon is required at the end of the block. 
  • C++ supports the . (dot) and -> operators to access its members.. 
  • It's unusual to define classes without methods; read material on objects for better understanding. 

Example: 

#include <iostream>
using namespace std;

// Define a class called Complex
class Complex {
    double real_part;
    double imag_part;
};

// Define another class for use in a classical linked list
class ListNode {
    Complex data;    // can nest classes
    ListNode *next;  // note how we define the next pointer
};

int main ()
{

  // Declare a variable, with space allocated.
  Complex c;
  // Declare a pointer variable, with no space yet allocated.
  Complex *c2;

  // Pointers for the list.
  ListNode *front;
  ListNode *temp_ptr;

  // The "." operator accesses struct members.
  c.real_part = 1.0;
  c.imag_part = 2.0;
  cout << "c: real part = " << c.real_part << " imag part = " << c.imag_part << endl;

  // First allocate memory for the pointer
  c2 = new Complex();
  // The "->" operator accesses struct members via a pointer.
  c2->real_part = c.real_part;
  // Alternatively (and more confusingly) first de-reference the pointer.
  (*c2).imag_part = c.imag_part;
  cout << "c2: real part = " << c2->real_part << " imag part = " << c2->imag_part << endl;

  // Let's create a simple 2 node linked list.
  front = new ListNode();
  front->data.real_part = c.real_part;
  front->data.imag_part = c.imag_part;
  // The assignment "front->data = c;" is allowed by some compilers.
  front->next = new ListNode();
  // Note the use of multiple operators. Same as "(front->next)->data".
  front->next->data.real_part = c2->real_part;
  front->next->data.imag_part = c2->imag_part;
  front->next->next = NULL;

  // Traverse the list and print the data part.
  temp_ptr = front;  
  // Now "temp_ptr" and "front" point to the same thing.
  while (temp_ptr != NULL) {
    cout << "real part = " << temp_ptr->data.real_part;
    cout << " imag part = " << temp_ptr->data.imag_part << endl; 

    temp_ptr = temp_ptr->next;
  }
}
10. Type definitions Java has no type definitions. The Java philosophy is: if you want to define your own type, then simply place the type into an object (class) and use the object instead.  Type definitions in C: 
  • A type is a way to associate a single name for user-defined data types, and to use the name in declarations. 
  • The keyword typedef is used in C to create type definitions. 
  • Unfortunately, C's syntax in these type definitions can sometimes be quite difficult to read. 

Example:

#include <stdio.h>

int main ()
{
  /* Define a type for integer pointers. */
  typedef int *intPtrType;
  /* Declare a variable using the so-defined type name. */
  intPtrType int_ptr;

  /* Type definitions are more useful for structures. */
  typedef struct Complex {
    double real_part;
    double imag_part;
  } ComplexType;             /* Note where the type name appears. */
  ComplexType c;             /* Now declare the variable. */

  /* A linked list node. */
  typedef struct ListNode {
    ComplexType data;
    struct ListNode *next;   /* Cannot use ListNodePtrType. */ 
  } ListNodeType;
  /* Create a pointer-type for ListNode's. */
  typedef ListNodeType *ListNodePtrType;
  ListNodePtrType front;     /* Variable declaration. */

  /* Example of using the integer pointer type. */
  int_ptr = (intPtrType) malloc (sizeof(int));
  *int_ptr = 0;
  printf ("Bank balance = %d\n", *int_ptr);

  /* Same code as in previous examples. */
  c.real_part = 1.0;
  c.imag_part = 2.0;
  printf ("c: real part = %lf   imag part = %lf\n", c.real_part, c.imag_part);

  /* A one-node linked list. Note the use of type names in malloc. */
  front = (ListNodePtrType) malloc (sizeof (ListNodeType));
  front->data.real_part = c.real_part;
  front->data.imag_part = c.imag_part;
  front->next = NULL;
}
  

Type Definitions in C++:

  • C++ supports all the typedef features of C, although it's functionality has been largely superceded by the support for objects.
  • Typedefs is prevalent in Windows(tm) programming and so they are still used in C++ for many programming tasks
12. Void type Java's void type: 
  • The void keyword in Java is used to declare methods that do not return anything. 
C's void type: 
  • The void keyword in C is used to declare functions that do not return anything. 
  • void is also used to declare pointers that can point to anything (See the section on pointers). 
C++'s void type: 
  • The void keyword in C++ is used to declare functions that do not return anything. 
  • void is also used to declare pointers that can point to anything (See the section on pointers). 
E.  Operators 
1. Arithmetic - Integer Java's integer operators: 
  • Unary operators: +,- (for the sign of an integer). 
  • Standard binary operators: +,-,*,/ (Note that / is an integer-divide). 
  • Remainder (mod) operator: %
  • Pre/post increment and decrement: ++, --
Example: 
public class TestIntegerOps {
  public static void main (String[] argv)
  {
    // Unary operators.
    int i = -1;
    int j = +2;

    // Standard plus, minus, mult and div.
    int k = (i + j) + (i - j) + (i * j) + (i / j);

    // Remainder.
    int m = i % j;

    // Post and pre operators
    int n = (i++) + (++i) + (j--) + (--j);

    System.out.println ("i=" + i + " j=" + j + " k=" + k
                        + " m=" + m + " n=" + n);
  }
}
  
C's integer operators: 
  • Unary operators: +,- (for the sign of an integer). 
  • Standard binary operators: +,-,*,/ (Note that / is an integer-divide). 
  • Remainder (mod) operator: %
  • Pre/post increment and decrement: ++, --
Example: 
#include <stdio.h>

int main ()
{
  /* Unary operators. */
  int i = -1;
  int j = +2;
  int k, m, n;

  /* Standard plus, minus, mult and div. */
  k = (i + j) + (i - j) + (i * j) + (i / j);

  /* Remainder. */
  m = i % j;

  /* Post and pre operators. */
  n = (i++) + (++i) + (j--) + (--j);

  printf ("i=%d j=%d k=%d m=%d n=%d\n", i, j, k, m, n);
}
  
C++'s integer operators: 
  • Unary operators: +,- (for the sign of an integer). 
  • Standard binary operators: +,-,*,/ (Note that / is an integer-divide). 
  • Remainder (mod) operator: %
  • Pre/post increment and decrement: ++, --
Example: 
#include <iostream>
using namespace std;

main ()
{
  // Unary operators.
  int i = -1;
  int j = +2;
  int k, m, n;

  // Standard plus, minus, mult and div.
  k = (i + j) + (i - j) + (i * j) + (i / j);

  // Remainder.
  m = i % j;

  // Post and pre operators.
  n = (i++) + (++i) + (j--) + (--j);

  cout << "i=" << i << " j=" << j << " k=" << k << " m=" << m << " n=" << n << endl;
}
2. Arithmetic - Real Java's floating point operators: 
  • Unary operators: +,- (for the sign of an integer). 
  • Standard binary operators: +,-,*,/ (Note that / is an integer-divide). 
  • Remainder (mod) operator: % 
  • Pre/post increment and decrement: ++, --
  • The remainder and pre/post increment or decrement operators are rarely used with real numbers. 
Example: 
public class TestRealOps {
  public static void main (String[] argv)
  {
    // Unary operators.
    double a = -1.2;
    double b = +3.4;

    // Standard plus, minus, mult and div.
    double c = (a + b) + (a - b) + (a * b) + (a / b);

    // d = 0.7
    double d = (5.5 % 1.2);

    // Post-increment, so e=-1.2.    
    double e = (a++);

    System.out.println ("a=" + a + " b=" + b + " c=" 
                        + c + " d=" + d + " e=" + e);
  }
}
  
C's floating point operators: 
  • Unary operators: +,- (for the sign of an integer). 
  • Standard binary operators: +,-,*,/ (Note that / is an integer-divide). 
  • The operator % is not permitted with floating-point types. 
  • Pre/post increment and decrement: ++, --
  • The pre/post increment or decrement operators are rarely used with real numbers. 
Example: 
#include <stdio.h>

int main ()
{
  /* Unary operators. */
  double a = -1.2;
  double b = +3.4;
  double c, d, e;

  /* Standard plus, minus, mult and div. */
  c = (a + b) + (a - b) + (a * b) + (a / b);

  /* Post-increment, so e=-1.2. */
  e = (a++);

  printf ("a=%lf b=%lf c=%lf e=%lf\n", 
          a, b, c, e);
}
  
C++'s floating point operators: 
  • Unary operators: +,- (for the sign of an integer). 
  • Standard binary operators: +,-,*,/ (Note that / is an integer-divide). 
  • The operator % is not permitted with floating-point types. 
  • Pre/post increment and decrement: ++, --
  • The pre/post increment or decrement operators are rarely used with real numbers. 
Example: 
#include <iostream>
using namespace std;

main ()
{
  // Unary operators.
  double a = -1.2;
  double b = +3.4;
  double c, d, e;

  // Standard plus, minus, mult and div.
  c = (a + b) + (a - b) + (a * b) + (a / b);

  // Post-increment, so e = -1.2.
  e = (a++);

  cout << "a=" << a << " b=" << b << " c=" << c << " e=" << e << endl;
}
  
3. Comparison  Java's comparison operators: 
  • Number comparison operators: <,>, <=, >=
  • Equality operators: == (equals), != (not equals). 
  • Equality operators apply to both numbers and object references. 
  • The result of a comparison is always a boolean value. 
  • The instanceof operator for determining object inheritance. 
Example: 
public class TestCompareOps {
  public static void main (String[] argv)
  {
    // Some data.
    int myAge = 19;
    int yourAge = 25;
    double averageAge = 24.39;
    
    // Number comparisons.
    boolean IAmYounger = (myAge < yourAge);
    boolean sameAge = (myAge == yourAge);
    // "yourAge" is cast to a double before comparison.
    boolean youAreYoung = (yourAge <= averageAge);

    System.out.println ("IAmYounger=" + IAmYounger +
                        " sameAge=" + sameAge +
                        " youAreYoung=" + youAreYoung);
    
    // Example of "instanceof" operator.
    String str = "hello";
    boolean fromObject = (str instanceof Object);
    System.out.println ("fromObject=" + fromObject);
  }
}
  
C's comparison operators: 
  • Number comparison operators: <,>, <=, >=
  • Equality operators: == (equals), != (not equals). 
  • Equality operators apply to both numbers and pointers. 
  • The result of a comparison is either 0 (false) or nonzero (true). 
Example: 
#include <stdio.h>

#define false 0
#define true 1
#define boolean int

int main ()
{
  /* Some data. */
  int myAge = 19;
  int yourAge = 25;
  double averageAge = 24.39;
  boolean IAmYounger;
  int sameAge;          /* No different from the boolean's. */
  boolean youAreYoung;
  int *intPtr1, *intPtr2;
  boolean badComparison;

  /* Number comparisons. */
  IAmYounger = (myAge < yourAge);
  sameAge = (myAge == yourAge);
  youAreYoung = (yourAge <= averageAge);

  /* Bad practice, but allowed. */
  yourAge = (yourAge <= averageAge);

  printf ("IAmYounger=%d sameAge=%d youAreYoung=%d yourAge=%d\n",
          IAmYounger, sameAge, youAreYoung, yourAge);

  /* Pointer comparisons are allowed, but discouraged. */
  badComparison = (intPtr1 < intPtr2);    
}
  
C++'s comparison operators: 
  • Number comparison operators: <,>, <=, >=
  • Equality operators: == (equals), != (not equals). 
  • Equality operators apply to both numbers and pointers. 
  • C++ has support for the datatype bool, which is either true or false
  • The boolean data type can be considered as a byte, and represent true as non-zero and false as a 0
  • The result of a comparison is either false (0) or true (non-zero). 
Example: 
#include <iostream>
using namespace std;

int main ()
{
  // Some data.
  int myAge = 19;
  int yourAge = 25;
  double averageAge = 24.39;
  bool IAmYounger;
  int sameAge;          // No different from the boolean's.
  bool youAreYoung;
  int *intPtr1, *intPtr2;
  bool badComparison;

  // Number comparisons.
  IAmYounger = (myAge < yourAge);
  sameAge = (myAge == yourAge);
  youAreYoung = (yourAge <= averageAge);

  // Bad practice, but allowed.
  yourAge = (yourAge <= averageAge);

  printf ("IAmYounger=%d sameAge=%d youAreYoung=%d yourAge=%d\n",
          IAmYounger, sameAge, youAreYoung, yourAge);
  cout << "IAmYounger=" << IAmYounger;
  cout << " sameAge=" << sameAge;
  cout << " youAreYoung=" << youAreYoung;
  cout << " yourAge=" << yourAge << endl;

  // Pointer comparisons are allowed, but discouraged.
  badComparison = (intPtr1 < intPtr2);    
}
4. Bitwise  Java's bitwise operators: 
  • Bitwise operators operate on integer types. 
  • Bitwise operators operate on individual bits in the representation of integers. 
  • The only unary bitwise operator: ~ (complement). 
  • Shift operators: << (left-shift), >> (sign-preserving right-shift), >>> (zero-sign-bit right shift). 
  • Other binary bitwise operators: & (and), | (or), ^ (xor). 
Example: 
public class TestBitwiseOps {
  public static void main (String[] argv)
  {
    int i = 1;  

    // Complement.
    System.out.println ("i complement: " + (~i));

    // Shift operators.
    System.out.println ("i left-shifted 2 places: " + (i << 2));
    System.out.println ("-i right-shifted one place: " + (-i >> 1));
    System.out.println ("-i unsigned right-shifted one place: " + (-i >>> 1));

    int j = 3;
    // Logical bitwise operators.
    System.out.println ("i AND j: " + (i & j));
    System.out.println ("i OR j: " + (i | j));
    System.out.println ("i XOR j: " + (i ^ j));
  }
}
  
C's bitwise operators: 
  • Bitwise operators operate on integer types. 
  • Bitwise operators operate on individual bits in the representation of integers. 
  • The only unary bitwise operator: ~ (complement). 
  • Shift operators: << (left-shift), >> (sign-preserving right-shift). 
  • Other binary bitwise operators: & (and), | (or), ^ (xor). 
  • ANSI C does not specify the result of shifting signed integers. 
Example: 
#include <stdio.h>

int main ()
{
  int i = 1;  
  int j = 3;

  /* Complement. */
  printf ("i complement: %d\n", (~i));

  /* Shift operators. */
  printf ("i left-shifted 2 places: %d\n", (i << 2));
  printf ("-i right-shifted one place: %d\n", (-i >> 1));

  /* Logical bitwise operators. */
  printf ("i AND j: %d\n", (i & j));
  printf ("i OR j: %d\n", (i | j));
  printf ("i XOR j: %d\n", (i ^ j));
}
  
C++'s bitwise operators: 
  • Bitwise operators operate on integer types. 
  • Bitwise operators operate on individual bits in the representation of integers. 
  • The only unary bitwise operator: ~ (complement). 
  • Shift operators: << (left-shift), >> (sign-preserving right-shift). 
  • Other binary bitwise operators: & (and), | (or), ^ (xor). 
Example: 
#include <iostream>
using namespace std;

main ()
{
  int i = 1;  
  int j = 3;

  // Complement.
  cout << "i complement: " << (~i) << endl;

  // Shift operators.
  cout << "i left-shifted 2 places: " << (i << 2) << endl;
  cout << "-i right-shifted one place: " << (-i >> 1) << endl;

  // Logical bitwise operators.
  cout << "i AND j: " << (i & j) << endl;
  cout << "i OR j:  " << (i | j) << endl;
  cout << "i XOR j: " << (i ^ j) << endl;
}
5. Shortcuts  Java's shortcut operators: 
  • Shortcut operators combine assignment with an operator. 
  • Example: the assignment x = x + 1 can be written as x += 1 using the += shortcut. 
  • Arithmetic shortcut operators: +=, -=, *=, /=, %=
  • Bitwise shortcut operators: <<=, >>=, >>>=, &=, ^=, |=
  • Shortcut operators can sometimes make code difficult to read. 
C's shortcut operators: 
  • Shortcut operators combine assignment with an operator. 
  • Example: the assignment x = x + 1 can be written as x += 1 using the += shortcut. 
  • Arithmetic shortcut operators: +=, -=, *=, /=, %=
  • Bitwise shortcut operators: <<=, >>=, &=, ^=, |=
  • Shortcut operators can sometimes make code difficult to read. 
C++'s shortcut operators: 
  • Shortcut operators combine assignment with an operator. 
  • Example: the assignment x = x + 1 can be written as x += 1 using the += shortcut. 
  • Arithmetic shortcut operators: +=, -=, *=, /=, %=
  • Bitwise shortcut operators: <<=, >>=, &=, ^=, |=
6. Boolean Java's boolean operators: 
  • Boolean operators operate on boolean variables. 
  • The standard boolean operators are: && (and), || (or), ! (not). 
  • Less frequently used: & (and), | and ^ (xor). 
  • The difference between && and &: all operands are evaluated with &, whereas only needed operands (in left-to-right order) are evaluated with &&
Example: 
public class TestBooleanOps {
  public static void main (String[] argv)
  {
    boolean x = true, y=false;

    // The second expression is not evaluated.
    // because the first is enough to determine z.
    boolean z = (x && false) && (x || !y);
    System.out.println ("z=" + z);
    
    // Same result, but all expressions are  evaluated.
    // Not recommended.
    z = (x & false) & (x | !y);
    System.out.println ("z=" + z);
    
    // More typical use of boolean operators.
    int i = -5, j =6;
    if ( (j < 0) || (i < 0) ) {
      System.out.println ("One of i or j is negative");
    }
  }
}
  
C's boolean operators: 
  • Boolean operators operate on all integer variables. 
  • The standard boolean operators are: && (and), || (or), ! (not). 
  • The operators & (and), | and ^ (xor) are not intended for logical expressions, but can be used (with care). 
  • The difference between && and &: all operands are evaluated with &, whereas only needed operands (in left-to-right order) are evaluated with &&
Example: 
#include <stdio.h>

#define false 0
#define true 1
#define boolean int

int main ()
{
  boolean x=true, y=false, z;
  int i=-5, j=6;

  /* The second expression is not evaluated.
     because the first is enough to determine z. */
  z = (x && false) && (x || !y);
  printf ("z=%d\n", z);

  /* Same result, but all expressions are evaluated. 
     Not recommended. */
  z = (x & false) & (x | !y);
  printf ("z=%d\n", z);

  /* More typical use of boolean operators. */
  if ( (j < 0) || (i < 0) ) {
    printf ("One of i or j is negative\n");
  }

  /* Permitted, but not recommended. */
  z = i && j;
}
  
C++'s boolean operators: 
  • Boolean operators operate on all integer variables. 
  • The standard boolean operators are: && (and), || (or), ! (not). 
  • The operators & (and), | and ^ (xor) are not intended for logical expressions, but can be used (with care). 
  • The difference between && and &: all operands are evaluated with &, whereas only needed operands (in left-to-right order) are evaluated with &&
Example: 
#include <iostream>
using namespace std;

main ()
{
  bool x=true, y=false, z;
  int i=-5, j=6;

  /* The second expression is not evaluated.
     because the first is enough to determine z. */
  z = (x && false) && (x || !y);
  cout << "z=" << z << endl;


  /* Same result, but all expressions are evaluated. 
     Not recommended. */
  z = (x & false) & (x | !y);
  cout << "z=" << z << endl;


  // More typical use of boolean operators.
  if ( (j < 0) || (i < 0) ) {
    cout << "One of i or j is negative" << endl;
  }

  // Permitted, but not recommended.
  z = i && j;
}
7. Casting  Casting in Java: 
  • Casting is what occurs when a value of one type (e.g., int) is stored in a variable of another type (e.g., double). 
  • Casting also refers to object variables that refer to objects of different types. 
  • Casting is either implicit (performed automatically by the compiler when it makes sense) or explicit (forced by the programmer). 
  • To create an explicit cast, use the target type in parentheses, e.g., ((int)). 
  • Not all casts are legal: you cannot cast a boolean into an int
Example: 
public class TestCasting {
  public static void main (String[] argv)
  {
    int i = 5;

    // Implicit cast provided by compiler.
    long j = i;

    // Explicit cast required to acknowledge possible
    // loss of information. Note: (2 * j) is a "long"
    // value, because "2" is cast into a long.
    i = (int) (2 * j);
    
    // Explicit cast that's not needed, but recommended
    // for clarity.
    double x = (double) i;

    // Cast works with constants as well.
    j = (long) 3.14159;
    
    // Advanced topic: casting with object variables.
    String str = "hello";
    // String inherits from Object, so implicit cast works.
    Object obj = str;
    // The other way around requires an explicit cast.
    str = (String) obj;
  }
}
  
Casting in C: 
  • Casting is what occurs when a value of one type (e.g., int) is stored in a variable of another type (e.g., double). 
  • Casting is either implicit (performed automatically by the compiler when it makes sense) or explicit (forced by the programmer). 
  • To create an explicit cast, use the target type in parentheses, e.g., ((int)). 
  • C allows all kinds of casts, but many are not recommended. 
Example: 
#include <stdio.h>

int main ()
{
  int i = 5;
  long j;
  double x;
  int intArray[5];
  int *intPtr;
  double *doublePtr;
  void *voidPtr;

  /* Implicit cast provided by compiler. */
  j = i;

  /* Explicit cast required to acknowledge possible
     loss of information. Note: (2 * j) is a "long"
     value, because "2" is cast into a long. */
  i = (int) (2 * j);

  /* Explicit cast that's not needed, but recommended
     for clarity. */
  x = (double) i;

  /* Cast works with constants as well. */
  j = (long) 3.14159;

  /* You can cast between array variables and pointers. */
  intPtr = (int*) intArray;

  /* Unfortunately, you can also perform these ill-advised 
     casts. Avoid them! */
  doublePtr = (double*) intPtr;
  i = (int) intPtr;
  intPtr = (int*) j;
  voidPtr = (void*) j;
}
  
Casting in C++: 
  • Casting is what occurs when a value of one type (e.g., int) is stored in a variable of another type (e.g., double). 
  • Casting is either implicit (performed automatically by the compiler when it makes sense) or explicit (forced by the programmer). 
  • To create an explicit cast, use the target type in parentheses, e.g., ((int)). 
  • C++ allows all kinds of casts, but many are not recommended. 
Example: 
int main ()
{
  int i = 5;
  long j;
  double x;
  int intArray[5];
  int *intPtr;
  double *doublePtr;
  void *voidPtr;

  // Implicit cast provided by compiler.
  j = i;

  /* Explicit cast required to acknowledge possible
     loss of information. Note: (2 * j) is a "long"
     value, because "2" is cast into a long. */
  i = (int) (2 * j);

  // Explicit cast that's not needed, but recommended for clarity.
  x = (double) i;

  // Cast works with constants as well.
  j = (long) 3.14159;

  // You can cast between array variables and pointers.
  intPtr = (int*) intArray;

  // Unfortunately, you can also perform these ill-advised casts. Avoid them!
  doublePtr = (double*) intPtr;
  i = (int) intPtr;
  intPtr = (int*) j;
  voidPtr = (void*) j;
}
8. Expressions  Expressions in Java: 
  • Use parentheses to build complex expressions out of simpler ones. 
  • Simple expressions consist of: variables, method calls, object creation, array element selection and object-member access. 
  • Larger expressions from simple ones using operators. 
Example: 
public class TestExpression {
  public static void main (String[] argv)
  {
    // Simple constant expression "5" on the right.
    int i = 5;

    // Larger expression 2 * i created from "2" and "i"
    int j = 2 * i;

    // Parentheses not needed, but can be used.
    j = (2 * i);

    // Parentheses not needed, but recommended.
    j = (2 * i) + i

    // Parentheses needed for clarity.
    int k = ( (i+j) + (i-j) ) / ( (i+j) - (i-j) );

    // Another example.
    if ( 
        ( (i < 0) && (i < j) )
        ||
        ( (j < 0) && (j < i) )
       ) {
      System.out.println ("I have no idea what this really means");
    }
    
  }
}
  
Expressions in C: 
  • Use parentheses to build complex expressions out of simpler ones. 
  • Simple expressions consist of: variables, method calls, object creation, array element selection and object-member access. 
  • Larger expressions from simple ones using operators. 
Example: 
#include <stdio.h>

int main ()
{
  /* Simple constant expression "5" on the right. */
  int i = 5;
  int j, k;

  /* Larger expression 2 * i created from "2" and "i" */
  j = 2 * i;

  /* Parentheses not needed, but can be used. */
  j = (2 * i);

  /* Parentheses not needed, but recommended. */
  j = (2 * i) + i;

  /* Parentheses needed for clarity. */
  k = ( (i+j) + (i-j) ) / ( (i+j) - (i-j) );

  /* Another example. */
  if ( 
      ( (i < 0) && (i < j) )
      ||
      ( (j < 0) && (j < i) )
     ) {
    printf ("I have no idea what this really means\n");
  }
    
}
  
Expressions in C++: 
  • Use parentheses to build complex expressions out of simpler ones. 
  • Simple expressions consist of: variables, method calls, object creation, array element selection and object-member access. 
  • Larger expressions from simple ones using operators. 
Example: 
#include <iostream>
using namespace std;

int main ()
{
  // Simple constant expression "5" on the right.
  int i = 5;
  int j, k;

  // Larger expression 2 * i created from "2" and "i"
  j = 2 * i;

  // Parentheses not needed, but can be used.
  j = (2 * i);

  // Parentheses not needed, but recommended.
  j = (2 * i) + i;

  // Parentheses needed for clarity.
  k = ( (i+j) + (i-j) ) / ( (i+j) - (i-j) );

  // Another example.
  if ( 
      ( (i < 0) && (i < j) )
      ||
      ( (j < 0) && (j < i) )
     ) {
    cout << "I have no idea what this really means" << endl;
  }
    
}
9. Other operators  Additional operators in Java: 
  • The assignment operator =
  • The + operator for concatenating strings. 
  • The "dot" operator to access elements of an object. 
  • The square-brackets operator to access elements of an array. 
  • The parentheses operator for method calls and parameter passing. 
  • The new operator for creating an object. 
  • The instanceof operator for object comparisons. 
  • The unnecessary ternary "conditional" operator, a C legacy. 
  • Other "operator" facts: 
    • You cannot use == (equals) for string or array comparison. 
    • You cannot use the comparison operators for strings. 
    • Java does not support operator overloading. 
Example: 
public class TestAdditionalOps {
  public static void main (String[] argv)
  {
    // The new operator. And use of square-brackets, but
    // not as an operator.
    int[] A = new int [5];

    // Square-brackets being used as an operator.
    A[0] = 0;
    
    // The new operator again. And the "+" concatenation
    // operator for strings.
    String str = new String ("hello" + " world!");

    // The "." operator for member access (length() is a 
    // method in the class String. And "()" parentheses for
    // a method call.
    int len = str.length();

    // The "instanceof" operator.
    if (str instanceof Object) {
      System.out.println ("str is an Object instance");
    }
    // The "conditional" operator - not recommended.
    int n = (len > 5) ? 5 : len;
  }
}
  
Additional operators in C: 
  • The assignment operator =
  • The "dot" operator to access elements of a structured type. 
  • The square-brackets operator to access elements of an array. 
  • The parentheses operator for function calls and parameter passing. 
  • The & "address-of" operator. 
  • The * "pointer-dereferencing" operator. 
  • The -> operator to access elements of a structure using a pointer to the structure. 
  • The sizeof operator for helping allocate memory. 
  • The (unnecessary) ternary "conditional" operator. 
  • Other "operator" facts: 
    • You cannot use == (equals) for array or string comparison. 
    • You cannot use the comparison operators for strings. 
    • C does not support operator overloading. 
Example: 
#include <stdio.h>

int main ()
{
  /* Use of "sizeof" operator to get 5 int-size 
     chunks of memory. */
  int arraySize = sizeof(int) * 5;
  /* Use of parentheses to pass parameter "arraySize" 
     to the function "malloc". */
  int *A = (int*) malloc ( arraySize );

  int i, *intPtr;

  /* Use of "&" operator to extract address of 
     variable i. */
  intPtr = &i;
  /* Use of "*" operator to dereference "intPtr". */
  *intPtr = 5;
  printf ("i=%d\n", i);

  /* The ternary conditional operator. Not recommended. */
  i = (i < A[0]) ? i : A[0];
}
  
Additional operators in C++: 
  • The assignment operator =
  • The "dot" operator to access elements of a structured type. 
  • The square-brackets operator to access elements of an array. 
  • The parentheses operator for function calls and parameter passing. 
  • The & "address-of" operator. 
  • The * "pointer-dereferencing" operator. 
  • The -> operator to access elements of a structure using a pointer to the structure. 
  • The sizeof operator for helping allocate memory. 
  • The (unnecessary) ternary "conditional" operator. 
  • Other "operator" facts: 
    • You cannot use == (equals) for array or string comparison. 
    • You cannot use the comparison operators for strings. 
    • C++ supports operator overloading. 
Example: 
#include <iostream>
using namespace std;

int main ()
{
  // Use of "sizeof" operator to get 5 int-size chunks of memory.
  int arraySize = sizeof(int) * 5;

  // Use of brackets to pass parameter "arraySize" to the keyword "new".
  int *A = new int[arraySize];

  int i, *intPtr;

  // Use of "&" operator to extract address of variable i.
  intPtr = &i;
  // Use of "*" operator to dereference "intPtr".
  *intPtr = 5;
  cout << "i=" << i << endl;

  // The ternary conditional operator. Not recommended.
  i = (i < A[0]) ? i : A[0];
}
F.  Statements 
1.  Assignment  Assignment in Java: 
  • The = operator is used for assignment. 
  • Multiple assignments can be done in a single statement. 
Example: 
public class TestAssignment {
  public static void main (String[] argv)
  {
    int i, j, k, m, n;

    // Simple assignment.
    i = 7;

    // Multiple assignment.
    j = k = m = n = i;

    // Use of assignment in an expression. 
    // Not recommended.
    boolean isLarger;
    if (isLarger = (i > 5)) {
      System.out.println ("i is larger than 5");
    }
  }
}
  
Assignment in C: 
  • The = operator is used for assignment. 
  • Multiple assignments can be done in a single statement. 
Example: 
#include <stdio.h>

int main ()
{
  int i, j, k, m, n;
  int isLarger;

  /* Simple assignment. */
  i = 7;

  /* Multiple assignment. */
  j = k = m = n = i;

  /* Use of assignment in an expression. 
     Not recommended. */
  if (isLarger = (i > 5)) {
    printf ("i is larger than 5\n");
  }

  /* Frequent error in C. Should be "i == 5". */
  if (i = 5) {
    printf ("i equals 5\n");
  }

}
  
Assignment in C++: 
  • The = operator is used for assignment. 
  • Multiple assignments can be done in a single statement. 
Example: 
#include <iostream>
using namespace std;

main ()
{
  int i, j, k, m, n;
  int isLarger;

  // Simple assignment.
  i = 7;

  // Multiple assignment.
  j = k = m = n = i;

  // Use of assignment in an expression. Not recommended.
  if (isLarger = (i > 5)) {
    printf ("i is larger than 5\n");
    cout << "i is larger than 5" << endl;
  }

  // Frequent error in C. Should be "i == 5".
  if (i = 5) {
    cout << "i equals 5" << endl;
  }

}
2.  If  "if" statements in Java: 
  • Conditionals in Java use the keywords if and else
  • Use tabbing that corresponds with structure, as the example shows. 
  • Only a boolean expression may be used in an if-clause. 
Example: 
public class TestIf {
  public static void main (String[] argv)
  {
    int i = 5;
    int j = 6;

    // Simple if statement.
    if (i < j)
      System.out.println ("i is less than j");
    
    // If statement with a block of statements.
    if (i < j) {
      System.out.println ("i is less than j");
      System.out.println ("i=" + i + " j=" + j);
    } // end of if-block.
    
    // Combination of if and else.
    if (i < j)
      System.out.println ("i is less than j");
    else if (i > j)
      System.out.println ("i is greater than j");
    else 
      System.out.println ("i is equal to j");

    // Example with nested if's
    if (i < j) {
      System.out.println ("i is less than j");
      if (i < 0) {
        System.out.println ("Careful, i is negative");
      } 
    } 
    else if (i > j) {
      System.out.println ("i is greater than j");
      if (j < 0) {
        System.out.println ("Careful, j is negative");
      }
    } 
    else {
      System.out.println ("i is equal to j");
    } // End of if-else block.
    // Use comments to clarify long blocks of code.

  }
}
  
"if" statements in C: 
  • Conditionals in C use the keywords if and else
  • Use tabbing that corresponds with structure, as the example shows. 
  • Only an integer expression may be used in an if-clause. 
Example: 
#include <stdio.h>

int main ()
{
  int i = 5;
  int j = 6;

  /* Simple if statement. */
  if (i < j)
    printf ("i is less than j\n");
    
  /* If statement with a block of statements. */
  if (i < j) {
    printf ("i is less than j\n");
    printf ("i=%d j=%d\n", i, j);
  } /* end of if-block. */
    
  /* Combination of if and else. */
  if (i < j)
    printf ("i is less than j\n");
  else if (i > j)
    printf ("i is greater than j\n");
  else 
    printf ("i is equal to j\n");

  /* Example with nested if's. */
  if (i < j) {
    printf ("i is less than j\n");
    if (i < 0) {
      printf ("Careful, i is negative\n");
    } 
  } 
  else if (i > j) {
    printf ("i is greater than j\n");
    if (j < 0) {
      printf ("Careful, j is negative\n");
    }
  } 
  else {
    printf ("i is equal to j\n");
  } /* End of if-else block. */
  /* Use comments to clarify long blocks of code. */

}
  
"if" statements in C++: 
  • Conditionals in C++ use the keywords if and else
  • Use tabbing that corresponds with structure, as the example shows. 
Example: 
#include <iostream>
using namespace std;

main ()
{
  int i = 5;
  int j = 6;

  // Simple if statement.
  if (i < j)
    printf ("i is less than j\n");
    cout << "i is less than j" << endl;
    
  // If statement with a block of statements.
  if (i < j) {
    cout << "i is less than j" << endl;
    cout << "i=" << i << " j=" << j << endl;
  } // end of if-block.
    
  // Combination of if and else.
  if (i < j)
    cout << "i is less than j" << endl;
  else if (i > j)
    cout << "is is greater than j" << endl;
  else 
    cout << "i is equal to j" << endl;

  // Example with nested if's.
  if (i < j) {
    cout << "i is less than j" << endl;
    if (i < 0) {
      cout << "Careful, i is negative" << endl;
    } 
  } 
  else if (i > j) {
    cout << "i is greater than j" << endl;
    if (j < 0) {
      cout << "Careful, j is negative" << endl;
    }
  } 
  else {
    cout << "i is equal to j" << endl;
  } // End of if-else block.
  // Use comments to clarify long blocks of code.


}
3.  Blocks  Blocks and statements in Java: 
  • Java statements are either simple statements or compound statements with code-blocks that are surrounded by braces. 
  • Simple Statements in Java end with a semi-colon. 
  • The semi-colon is not a statement separator. 
  • Semi-colons are not required at the end of a block. 
  • Every matching pair of braces constitutes a code-block. 
  • Variables declared inside a block are not visible outside the block, unless they are class variables. 
  • There are three predominant stylistic conventions in Java: 
    • A. The opening brace and closing brace of a block are always aligned, and always on lines by themselves. 
    • B. The opening brace is always at the end of the line that starts the block (e.g., at the end of the if-clause below). 
    • C. Use A for methods, and B for everything else (the convention we will use). 
Example: 
public class TestBlocks {
  public static void main (String[] argv)
  {
    // Single statements end with a semi-colon.
    int i = 5;
    
    // A block is defined by surrounding braces.
    {
      int j = 6;
      if (i < j) {  // Start of outer if-block.
        System.out.println ("i is less than j");
        // The inner-if block is not needed since there's
        // only one statement, but it improves clarity.
        if (i < 0) { 
          System.out.println ("Careful, i is negative");
        } 
      } // End of outer if-block. No semi-colon.
    }
    
    // i is available here, but not j.
    System.out.println ("End of program: i=" + i);

  } // End of block comprising the body of method "main".
} // End of block comprising the body of class "TestBlocks".
  
Blocks and statements in C: 
  • C statements are either simple statements or compound statements with code-blocks that are surrounded by braces. 
  • Simple Statements in C end with a semi-colon. 
  • The semi-colon is not a statement separator. 
  • Semi-colons are not required at the end of a block. 
  • Every matching pair of braces constitutes a code-block. 
  • In C, variables must be declared at the top of a function body. 
  • There are three predominant stylistic conventions in C: 
    • A. The opening brace and closing brace of a block are always aligned, and always on lines by themselves. 
    • B. The opening brace is always at the end of the line that starts the block (e.g., at the end of the if-clause below). 
    • C. Use A for functions, and B for everything else (the convention we will use). 
Example: 
#include <stdio.h>

int main ()
{
  /* Single statements end with a semi-colon. */
  int i = 5;
  int j = 6;

  /* A block is defined by surrounding braces. */
  {
    if (i < j) {  /* Start of outer if-block. */
      printf ("i is less than j\n");
      /* The inner-if block is not needed since there's
         only one statement, but it improves clarity. */
      if (i < 0) { 
        printf ("Careful, i is negative\n");
      } 
    } /* End of outer if-block. No semi-colon. */
  }
    
} /* End of block comprising the body of function "main". */
  
Blocks and statements in C++: 
  • C++ statements are either simple statements or compound statements with code-blocks that are surrounded by braces. 
  • Simple Statements in C++ end with a semi-colon. 
  • The semi-colon is not a statement separator. 
  • Semi-colons are not required at the end of a block. 
  • Every matching pair of braces constitutes a code-block. 
  • In C, variables must be declared at the top of a function body. 
  • There are three predominant stylistic conventions in C++: 
    • A. The opening brace and closing brace of a block are always aligned, and always on lines by themselves. 
    • B. The opening brace is always at the end of the line that starts the block (e.g., at the end of the if-clause below). 
    • C. Use A for functions, and B for everything else (the convention we will use). 
Example: 
#include <iostream>
using namespace std;

main ()
{
  // Single statements end with a semi-colon.
  int i = 5;
  int j = 6;

  // A block is defined by surrounding braces.
  {
    if (i < j) {  // Start of outer if-block.
      cout << "i is less than j\n";
      /* The inner-if block is not needed since there's
         only one statement, but it improves clarity. */
      if (i < 0) { 
        cout << "Careful, i is negative\n";
      } 
    } // End of outer if-block. No semi-colon.
  }
    
} // End of block comprising the body of function "main".
4.  While-loops 

While-loops in Java: 

  • Loop executes as long as the expression is true or non-zero
  • A while loop will evaluate the expression at the beginning of every iteration; that means it is evaulated before the first iteration through the loop
  • A do-while loop will evalulate the expression at the end of every iteration.

Example: 

public class TestWhile {
  public static void main (String[] argv)
  {
    int i = 1;
    int sum = 0;
    
    // Using a while loop.
    while (i <= 10) {
      sum += i;
      i++;
    }

    System.out.println ("Sum of first 10 integers: " + sum);

    // Using a do-while loop.
    sum = 0;
    i = 1;
    do {
      sum += i;
      i++;
    } while (i <= 10);

    System.out.println ("Sum of first 10 integers: " + sum);

  }
}
  

While-loops in C: 

  • Loop executes as long as the expression is true or non-zero
  • A while loop will evaluate the expression at the beginning of every iteration; that means it is evaulated before the first iteration through the loop
  • A do-while loop will evalulate the expression at the end of every iteration.

Example: 

#include <stdio.h>

int main ()
{
  int i = 1;
  int sum = 0;
    
  /* Using a while loop. */
  while (i <= 10) {
    sum += i;
    i++;
  }

  printf ("Sum of first 10 integers: %d\n", sum);

  /* Using a do-while loop. */
  sum = 0;
  i = 1;
  do {
    sum += i;
    i++;
  } while (i <= 10);

  printf ("Sum of first 10 integers: %d\n", sum);
}
  

While-loops in C++: 

  • Loop executes as long as the expression is true or non-zero
  • A while loop will evaluate the expression at the beginning of every iteration; that means it is evaulated before the first iteration through the loop
  • A do-while loop will evalulate the expression at the end of every iteration.
Example: 
#include <iostream>
using namespace std;

main ()
{
  int i = 1;
  int sum = 0;
    
  // Using a while loop.
  while (i <= 10) {
    sum += i;
    i++;
  }

  cout << "Sum of first 10 integers: " << sum << endl;

  // Using a do-while loop.
  sum = 0;
  i = 1;
  do {
    sum += i;
    i++;
  } while (i <= 10);

  cout << "Sum of first 10 integers: " << sum << endl;
}
5.  For-loops  Example: 
public class TestFor {
  public static void main (String[] argv)
  {
    // Straightforward version of for-loop. Notice
    // the declaration of i in the header of the loop.
    int sum = 0;
    for (int i=1; i<=10; i++) {
      sum += i;
    }
    System.out.println ("Sum of first 10 integers: " + sum);

    // Now count backwards from 10 to 1
    sum = 0;
    for (i=10; i>=1; i--) {
      sum += i;
    }
    System.out.println ("Sum of first 10 integers: " + sum);
    // A more cryptic version that makes use of multiple
    // mini-statements in the for-header. Not recommended.
    int j;
    for (sum=0, j=1; j<=10; sum+=j, j++) {
    }
    System.out.println ("Sum of first 10 integers: " + sum);
  }
}
  
Example: 
#include <stdio.h>

int main ()
{
  int i = 1, sum = 0, j = 1;
  /* Straighforward version of for-loop. Notice
     the declaration of i in the header of the loop. */
  for (i=1; i<=10; i++) {
    sum += i;
  }
  printf ("Sum of first 10 integers: %d\n", sum);

  /* Now count backwards from 10 to 1 */
  sum = 0;
  for (i=10; i>=1; i--) {
    sum += i;
  }
  printf ("Sum of first 10 integers: %d\n", sum);
  /* A more cryptic version that makes use of multiple
     mini-statements in the for-header. Not recommended. */
  for (sum=0, j=1; j<=10; sum+=j, j++) {
  }
  printf ("Sum of first 10 integers: %d\n", sum);
}
  
Example: 
#include <iostream>
using namespace std;

main ()
{
  int i = 1, sum = 0;
  /* Straighforward version of for-loop. Notice
     the declaration of i in the header of the loop. */
  for (i=1; i<=10; i++) {
    sum += i;
  }
  cout << "Sum of first 10 integers: " << sum << endl;

  /* Now count backwards from 10 to 1 */
  sum = 0;
  for (i=10; i>=1; i--) {
    sum += i;
  }
  cout << "Sum of first 10 integers: " << sum << endl;
  /* A more cryptic version that makes use of multiple
     mini-statements in the for-header. Not recommended.
     Note how variables can be declared on-the-fly in C++. */
  for (sum=0, int j=1; j<=10; sum+=j, j++) {
  }
  cout << "Sum of first 10 integers: " << sum << endl;
}
6.  Break 

Breaking in Java:

  • Causes the Java interpreter to skip immediately to the end of the iteration statement
  • Used commonly inside for loops or while loops to exit the loop if a condition is met
  • Also used with switch statements

Example:

public class TestBreak {
  public static void main (String[] argv)
  {
    // Let us make an integer array with the values
    // that increase from 0 to 9
    int[] array = new int[10];

    for(int i=0; i<10; i++) {
        array[i] = i;
    }

    // now use the break to stop when we reach 7
    for(int i=0; i<array.length; i++) {
        if(array[i] == 7) {
            break;
        }
    }

    // Program will break to here

  }

Breaking in C:

  • Causes the execution to skip the containing iteration statement
  • Used commonly inside for loops or while loops to exit the loop if a condition is met
  • Also used with switch statements

Example:

#include <stdio.h>

int main ()
{
  /* Let us make an integer array with the values
     that increase from 0 to 9 */
  int array[10];
  int i=0;
  int j=0;

  /* initialize the array to its values */
  for(i=0; i<10; i++) {
      array[i] = i;
  }

  /* Now use the break statement to stop when we reach 7 */
  for(j=0; j<10; j++) {
      if(array[j] == 7) {
          break;
      }
  }

  /* Program will break to this location and continue */

}

Breaking in C++:

  • Causes the execution to skip the containing iteration statement
  • Used commonly inside for loops or while loops to exit the loop if a condition is met
  • Also used with switch statements

Example:

#include <iostream>
using namespace std;

int main ()
{
  /* Let us make an integer array with the values
     that increase from 0 to 9 */
  int array[10];

  // initialize the array to its values
  for(int i=0; i<10; i++) {
      array[i] = i;
  }

  // Now use the break statement to stop when we reach 7
  for(int j=0; j<10; j++) {
      if(array[j] == 7) {
          break;
      }
  }

  // Program will break to this location and continue

}

 

7.  Case/Switch  Example: 
public class TestSwitch {
  public static void main (String[] argv)
  {
    int i;
    // demonstrate switch/case statement - note that the break is
    // required to exit the switch structure. If it is omitted, control 
    // will flow directly to the next case. For example, omitting the
    // last break will result in a strange message when i is 7 or 8! 
    for (i=0; i <= 19; ++i)
        switch(i)
        {
           case 1:
           case 2:
           case 3:
           case 4:
           case 9:
                System.out.println(i + "is either 1,2,3,4 or 9");
                break;
           case 5:
                System.out.println(i + "is of course 5");
                break;
           case 7:
           case 8:
                System.out.println(i + "is 7 or 8");
                break;
           default:
                System.out.println(i + "isn't 1,2,3,4,5,7,8, or 9");
        }
    }
  }
Example:
#include <stdio.h>
int main()
  {
    int i;
    /* demonstrate switch/case statement - note that the break is
       required to exit the switch structure. If it is omitted, control 
       will flow directly to the next case. For example, omitting the
       last break will result in a strange message when i is 7 or 8! */
    for (i=0; i <= 19; ++i)
        switch(i)
        {
           case 1:
           case 2:
           case 3:
           case 4:
           case 9:
                printf("%d is either 1,2,3,4 or 9\n",i);
                break;
           case 5:
                printf("%d is of course 5\n",i);
                break;
           case 7:
           case 8:
                printf("%d is 7 or 8\n",i);
                break;
           default:
                printf("%d isn't 1,2,3,4,5,7,8, or 9\n",i);
        }
  }
Example: 
#include <iostream>
using namespace std;

main()
  {
    // demonstrate switch/case statement - note that the break is     // required to exit the switch structure. If it is omitted, control      // will flow directly to the next case. For example, omitting the     // last break will result in a strange message when i is 7 or 8!      for (int i=0; i <= 19; ++i)         switch(i)         {            case 1:            case 2:            case 3:            case 4:            case 9:                 cout << i << "is either 1,2,3,4 or 9";                 break;            case 5:                 cout << i << "is of course 5";                 break;            case 7:            case 8:                 cout << i << "is 7 or 8";                 break;            default:                 cout << i << "isn't 1,2,3,4,5,7,8, or 9";         }     }   }
8.  Goto/labels 

Goto/Labelled Breaks in Java:

  • Goto is not supported by Java at all
  • A labelled break is when the program can define which iteration statement to exit from.
  • This can be useful when working with nested iteration statements (i.e. double for-loops)

Example:

 public class TestGotoLabel {
  public static void main (String[] argv)
  {
    // A simple program that will loop forever until
    // the user enters the command "quit from the screen "

    // These are the key steps in setting up the read operation.
InputStreamReader isr = new InputStreamReader (System.in);
LineNumberReader lr = new LineNumberReader (isr);
outerloop: // Label set up here, BEFORE loop starts. while (true) { // Initially an infinite loop; // Stuff // ... // Read input from user while (true) { // Read one command from the user at a time String command = lr.readLine(); if (command.equals("quit")) break outerloop; } // Other stuff // ... } // Control reaches here on break  }

 

Goto/Labelled Breaks in C:

  • Goto statements are supported, but their use is HIGHLY DISCOURAGED
  • Goto allows for an unconditional jump to another piece of code
  • Code can become harder to debug and harder to read
  • Goto statements can be used in a way to emulate labelled breaks

Example:

#include <stdio.h>
#include <string.h> /* for the string comparison function */
int main()
  {
    /* A simple program that will loop forever until
       the user enters the command quit from the screen */
    char *command = new char[80];

    while (1) { /* Initially an infinite loop */
        /* Stuff ... */

        /* Read input from user */
        while(1) {

            /* Read one command at a time from the user */
            scanf("%s", command);
            
            /* If the command is equal to "quit" */
            if (strcmp(command, "quit") == 0) {
                goto exitCondition;  /* go to code that is labelled ExitCondition */
            }
        }

        /* Other stuff ... */

    }

    exitCondition:

    /* Control reaches here on goto */
    printf("Exit condition reached. You entered \"quit\"\n");    


  }

Goto/Labelled Breaks in C++:

  • Goto statements are supported, but their use is HIGHLY DISCOURAGED
  • Goto allows for an unconditional jump to another piece of code
  • Code can become harder to debug and harder to read
  • Goto statements can be used in a way to emulate labelled breaks

Example:

#include <iostream>
using namespace std;

#include <string.h> // for the string comparison function 
int main()
  {
    /* A simple program that will loop forever until
       the user enters the command quit from the screen */
    char *command = new char[80];

    while (1) { // Initially an infinite loop
        // Stuff ... 

        // Read input from user 
        while(1) {

            // Read one command at a time from the user
            cin >> command
            
            // If the command is equal to "quit"
            if (strcmp(command, "quit") == 0) {
                goto exitCondition;  // go to code that is labelled ExitCondition
            }
        }

        // Other stuff ...

    }

    exitCondition:

    // Control reaches here on goto
    cout << "Exit condition reached. You entered \"quit\"" << endl;
  }
9.  Exceptions 

Exceptions in Java:

  • Java allows you to "catch" an unexpected event and possibly handle it
  • Improves the robustness of your program
  • The most general exception is known as Exception
  • Java has many pre-constructed Exceptions which handled most types of unexpected events, but you are welcome to create your own
  • Use try-catch statements to contain code that can "potentially" cause an exception

Example:

public class TestException {
  public static void main (String[] argv)
  {
      // Try to open a file that doesn't exist
    
      try {
          // All code that could potentially cause an exception is placed
          // in here

          FileReader f = new FileReader("fileThatDoesNotExist.txt");

      catch (FileNotFoundException e) {
          // If the file was not found, then this code will execute
          // instead of the program crashing

          System.out.println("File was not found!");
      }

  }

}

 

Exceptions in C:

  • C does not have support for exception handling

Exceptions in C++

C++ exception handling through the use of try-catch blocks

Exceptions are thrown inside a try block

Instead of specific classes as in Java, you can throw anything.

Example:

#include <iostream>
using namespace std;


int main() 
  {
    // Throw a string
    try {
        // Do stuff...

        throw "Uh oh, something went wrong!";

    } catch (char *message) {
        // catch anything that throws a string
        cout << "Exception caught, message is: " << message << endl;
    }

    // Throw an int
    try {
        // Do stuff...

        throw -5;

    } catch (int error) {
        // catch anything that throws an int
        cout << "Error code: " << error << endl;
    } 
  }

If an exception is not caught in a certain block, then it is propagated upwards to the calling function

Example:

#include <iostream>
using namespace std;

void doSomethingBad()
  {
    
    try {
        // This throw will be propagated up to the function that called it

        throw "doSomethingBad() did something bad!"
    
    } catch (int) { // try to catch an integer, not a string
        cout << "An integer was thrown" << endl;
    }
  }

int main() 
  {
    // Execute a function which will throw a string
    try {
        doSomethingBad(); // will throw a message that is caught here

    } catch (char *message) {
        // catch anything that throws a string
        cout << "Exception caught, message is: " << message << endl;
    }
  }
G.  Program units
1.  Methods

Methods in Java:

  • Methods allow you to write self-contained blocks of code which can be executed from different parts of a program.
  • This allows you to repeat many actions without having to rewrite the code.

Example:

public class TestMethods {
    // Go one-by-one and find the maximum in an array
    public static int findMax(int[] array) {
       int currentMax = array[0]; // initialize to the first
       
       for(int i=1; i<array.length; i++) {
           if(currentMax < array[i]) {
               currentMax = array[i];
           }
       }

       return currentMax;
    }

    // Recursively find the maximum in an array
    public static int findMaxRecursive(int[] array, int index) {

        if (index == 0) {
            return array[0];
        }

        int maxValueOfRemainder = findMaxRecursive(array, index-1);

        if (array[index] > maxValueOfRemainder) {
            return array[index];
        } else {
            return maxValueOfRemainder;
        }
    }
    
    public static void main(String[] args) {
        // Let us make an array and pass it to both the functions we
        // created

        int[] myNumbers = new int[50];
        // Place some random values into the array...


        int result = 0;
        
        result = findMax(myNumbers);

        System.out.println("findMax: Max value is "+result);

        result = findMaxRecursive(myNumbers, myNumbers.length);

        System.out.println("findMaxRecursive: Max value is"+result);
    }
}

Functions in C:

  • Functions allow you to write self-contained blocks of code which can be executed from different parts of a program.
  • This allows you to repeat many actions without having to rewrite the code.
  • Before a function is used in main() it must be declared using its prototype, so the compiler can make necessary checks
  • The prototype is actually just the function header which ends in a semicolon
  • By using prototypes, C programs can be divided up into multiple files, for better code organization

Example:

#include <stdio.h>

/* Go one-by-one and find the maximum in an array */
int findMax(int *array, int arrayLength) {
    int currentMax = array[0]; /* initialize to the first */
    int i;
       
    for(i=1; i<array.length; i++) {
        if(currentMax < array[i]) {
            currentMax = array[i];
        }
    }

    return currentMax;    
 }

/* Recursively find the maximum in an array */
int findMaxRecursive(int *array, int index) {
    if (index == 0) {
        return array[0];
    }

    int maxValueOfRemainder = findMaxRecursive(array, index-1);

    if (array[index] > maxValueOfRemainder) {
        return array[index];
    } else {
        return maxValueOfRemainder;
    }
}

int main() {
    /* Create an array with some numbers in it */
    int array[50];
    int result;

    /* Place some random values into the array */

    /* Now get the results of both functions */
    result = findMax(array, 50);
    printf("findMax: Max value is %d\n", result);
    result = findMaxRecursive(array, 50);
    printf("findMaxRecursive: Max value is %d\n", result);
}

Methods in C++:

  • C++ can have functions just like in C
  • However, it can also have functions embedded in a class, like Java
  • A function declared inside of a class is accessed using the . operator
  • Methods inside classes can be static or dynamic. More on this later.
  • Methods for classes can also be prototyped; First the class is declared only with prototypes

Example:

#include <iostream>
using namespace std;

// Declare the class with only prototypes
class TestMethods {
    // Go one-by-one and find the maximum in an array
    static int findMax(int *array, int arrayLength) {
        int currentMax = array[0]; // initialize to the first
        int i;
           
        for(i=1; i<array.length; i++) {
            if(currentMax < array[i]) {
                currentMax = array[i];
            }
        }

        return currentMax;    
    }

    // Recursively find the maximum in an array
    static int findMaxRecursive(int *array, int index) {
        if (index == 0) {
            return array[0];
        }
        int maxValueOfRemainder = findMaxRecursive(array, index-1);

        if (array[index] > maxValueOfRemainder) {
            return array[index];
        } else {
            return maxValueOfRemainder;
        }
    }
};

int main() {
    // Create an array with some numbers in it
    int array[50];
    int result;

    // Place some random values into the array

    // Now get the results of both functions
    result = TestMethods::findMax(array, 50);
    cout << "findMax: Max value is " << result << endl;
    result = TestMethods::findMaxRecursive(array, 50);
    cout << "findMaxRecursive: Max value is " << result << endl;
}
2.  Single file

Single Files in Java:

  • Typically, each class should be defined in its own. java file
  • It is possible to create an entire java application in a single .java file.
    • However, this is highly discouraged.
  • For example purposes, most examples in this references are provided as single file solutions.
  • Please refer to the many examples on this reference for single file programs.

 

Single Files in C:

  • Typically, each data structure and its corresponding functions should be declared in their own .h file, and the functions implemented and variables initialized in a .c file.
  • It is possible to create an entire java application in a single .c file, taking into account forward references.
    • However, this is highly discouraged.
  • For example purposes, most examples in this references are provided as single file solutions.
  • Please refer to the many examples on this reference for single file programs.

 

Single Files in C++:

  • Typically, each data structure and its corresponding functions should be declared in their own .h file, and the functions implemented and variables initialized in a .cpp file.
  • It is possible to create an entire java application in a single .cpp file, taking into account forward references.
    • However, this is highly discouraged.
  • For example purposes, most examples in this references are provided as single file solutions.
  • Please refer to the many examples on this reference for single file programs.

 

3.  Multiple files

Multiple Files in Java:

  • There must be at least one java class defined in each file.
  • If there are multiple classes defined in one file, then only one may be public, and the file must be named after it.
  • It is often practiced that each class file is defined in its own file, whether it is public or not
  • A .java file with one class defined shall compile to a .class file with the same name as the .java file
  • Multiple classes in one .java file shall compile to a .class file for each class defined in the .java file
  • If a .class file is available in your classpath or in an available .jar file, then you can use it in your code

Example (FindMax.java):

public class FindMax {
    // Go one-by-one and find the maximum in an array
    public static int findMax(int[] array) {
       // ...
       // return the max
    }

    // Recursively find the maximum in an array
    public static int findMaxRecursive(int[] array, int index) {
        // ...
        // return the max
    }
}

Example (TestMultipleFiles.java):

public class TestMultipleFiles {
    public static void main(String[] args) {
        // Let us make an array and pass it to both the functions we
        // created

        int[] myNumbers = new int[50];
        // Place some random values into the array...

        // We are using the functions, even though they are defined
        // in another file

        int result = 0;
        result = FindMax.findMax(myNumbers);
        System.out.println("findMax: Max value is "+result);

        result = FindMax.findMaxRecursive(myNumbers, myNumbers.length);
        System.out.println("findMaxRecursive: Max value is"+result);
    }
}

Mutiple Files in C:

  • Typically, program files in C are broken up into:
    • function prototypes in header files (.h)
    • function implementations in source files (.c), these files #include their corresponding .h file
  • And there is one .c file which contains the main function, int main() {...}
    • The main .c file must #include the header files that contain the functions it uses

Example (FindMaxC.h):

/* Header file for FindMax in C
 * Contains all the function prototypes
 */

/* Declare function prototypes */
int findMax(int *array, int arrayLength);
int findMaxRecursive(int *array, int index);

Example (FindMaxC.c):

/* Source file for FindMaxC.h
 * 
 * Implementation of all function proptypes in FindMaxC.h in C
 */

#include <FindMaxC.h> /* note we have to include the function prototypes */

/* Implement the functions in any order*/

/* Recursively find the maximum in an array */
int findMaxRecursive(int *array, int index) {
    /* return the max recursively */
}

/* Go one-by-one and find the maximum in an array */
int findMax(int *array, int arrayLength) 
    /* return the max */
}

Example (TestMultipleFiles.c):

#include <stdio.h>
#include "FindMaxC.h"   /* include the header for max */

int main() {
    /* Create an array with some numbers in it */
    int array[50];
    int result;

    /* Place some random values into the array */

    /* Because the prototypes have been define above,
       the compiler won't complain that we are using
       them here */
    result = findMax(array, 50);
    printf("findMax: Max value is %d\n", result);
    result = findMaxRecursive(array, 50);
    printf("findMaxRecursive: Max value is %d\n", result);
}

 

Multiple Files in C++:

  • Typically, program files in C++ are broken up into:
    • Class definitions function prototypes in header files (.h)
    • Function implementations of classes in source files (.c), these files #include their corresponding .h file
  • And there is one .c file which contains the main function, int main() {...}
    • The main .c file must #include the header files that contain the functions it uses

Example (FindMaxCPP.h):

// This is the header file for the class FindMax

// Declare the class with only prototypes
class FindMax  {
    // Go one-by-one and find the maximum in an array
    static int findMax(int *array, int arrayLength);
    // Recursively find the maximum in an array
    static int findMaxRecursive(int *array, int index);
};

Example (FindMaxCPP.cpp):

// Source file for FindMaxCPP.h

#include "FindMaxCPP.h" // note the include of the header

// Implement the functions inside the class FindMax
int FindMax::findMax(int *array, int arrayLength) {
    // return the max 
}

int FindMax::findMaxRecursive(int *array, int index) {
    // return the max recursively
}

Example (TestMultipleFiles.cpp):

#include <iostream>
using namespace std;
#include "FindMaxCPP.h"   // we need to include

int main() {
    // Create an array with some numbers in it
    int array[50];
    int result;

    // Place some random values into the array

    // Now get the results of both functions
    result = FindMax::findMax(array, 50);
    cout << "findMax: Max value is " << result << endl;
    result = FindMax::findMaxRecursive(array, 50);
    cout << "findMaxRecursive: Max value is " << result << endl;
}
4.  Libraries 
5.  Packages 

Packages in Java:

  • Java packages are libraries of code which can be distributed and used by importing them in your java code
  • Java packages are distributed as .jar files.
  • To create a package:
    • Every class that you want to be visible from the package must be public
    • Every java file should have the line package <PackageName>; on top to define that is in the package;
    • Create a directory structure that is the same as your package name
      • If your package name is com.personal.Rizwan, then create a folder called Rizwan/ inside personal/ inside com, and place your class files there
      • If your package name is just MyPackage, create a folder called MyPackage/ and place your class files there
    • Create a jar file of the directories
  • To use a package, make sure it is in your classpath

Package File (note the package directive at the top):

package MyPackage;

public class FindMax {
    // Go one-by-one and find the maximum in an array
    public static int findMax(int[] array) {
       int currentMax = array[0]; // initialize to the first
       
       for(int i=1; i<array.length; i++) {
           if(currentMax < array[i]) {
               currentMax = array[i];
           }
       }

       return currentMax;
    }

    // Recursively find the maximum in an array
    public static int findMaxRecursive(int[] array, int index) {

        if (index == 0) {
            return array[0];
        }

        int maxValueOfRemainder = findMaxRecursive(array, index-1);

        if (array[index] > maxValueOfRemainder) {
            return array[index];
        } else {
            return maxValueOfRemainder;
        }
    }
}

File that uses our new package file (note the import directive):

import MyPackage.*;

public class TestPackages {
    public static void main(String[] args) {
        int[] array = new int[50];
        for(int i=0; i<50; i++) {
            array[i] = i;
        }
        System.out.println("Max is "+FindMax.findMax(array));
    }
}

Packages in C:

  • C has no packaging support by default

Packages in C++:

  • C++ has no packaging support by default.
6.  Forward references

Forward References in Java:

  • Java functions cannot just be declared and not be implemented
  • Thus we can define the methods in our classes in any order, and not have to worry about a method not being found while writing a piece of code
  • For Java to use any libraries, these libraries must be #imported before the class is written

Example:

public class TestForwardReferences {

    public static void main(String[] args) {
        // Let us make an array and pass it to both the functions we
        // created

        int[] myNumbers = new int[50];
        // Place some random values into the array...

        // We are using the functions, even though they are defined after
        // this main() function
        int result = 0;
        result = findMax(myNumbers);
        System.out.println("findMax: Max value is "+result);
        result = findMaxRecursive(myNumbers, myNumbers.length);
        System.out.println("findMaxRecursive: Max value is"+result);
    }

    // Go one-by-one and find the maximum in an array
    public static int findMax(int[] array) {
       // ...
       // return the max
    }

    // Recursively find the maximum in an array
    public static int findMaxRecursive(int[] array, int index) {
        // ...
        // return the max
    }
}

Forward References in C:

  • C programs are centered around the main() function
    • int main() { ... }
  • For main to be able to use any functions, it must #include them in the beginning
  • All functions have to be declared before using them. The compiler goes sequentially through the code during compilation.
  • If you do not want to implement the function, you may declare it with just the function prototype. The prototype is usually just the function signature, but instead of the {...}, you place a ;
    • void doSomething(int value1, char *name);
  • Place all prototypes before they are used, and you can implement them later

Example:

#include <stdio.h>

/* Declare function prototypes */
int findMax(int *array, int arrayLength);
int findMaxRecursive(int *array, int index);

int main() {
    /* Create an array with some numbers in it */
    int array[50];
    int result;

    /* Place some random values into the array */

    /* Because the prototypes have been define above,
       the compiler won't complain that we are using
       them here */
    result = findMax(array, 50);
    printf("findMax: Max value is %d\n", result);
    result = findMaxRecursive(array, 50);
    printf("findMaxRecursive: Max value is %d\n", result);
}

/* Implement the functions in any order*/

/* Recursively find the maximum in an array */
int findMaxRecursive(int *array, int index) {
    /* return the max recursively */
}

/* Go one-by-one and find the maximum in an array */
int findMax(int *array, int arrayLength) 
    /* return the max */
}

Forward References in C++:

  • C++ allows for a class definition to be made, with no functions implemented
  • The C++ compiler will be happy with just the class definition, as long as it is #included or written before the function or class is used.
  • However, the program will need the implemented functions during linking.
  • Then, the functions can then be implemented somewhere else.

Example:

#include <iostream>
using namespace std;

/* Declare the class with only prototypes */
class TestMax  {
    // Go one-by-one and find the maximum in an array
    static int findMax(int *array, int arrayLength);
    // Recursively find the maximum in an array
    static int findMaxRecursive(int *array, int index);
};

int main()
  {
    // Create an array with some numbers in it
    int array[50];
    int result;

    // Place some random values into the array

    // Now get the results of both functions
    result = TestMax::findMax(array, 50);
    cout << "findMax: Max value is " << result << endl;
    result = TestMax::findMaxRecursive(array, 50);
    cout << "findMaxRecursive: Max value is " << result << endl;
  }

// Implement the functions inside the class TestMax
int TestMax::findMax(int *array, int arrayLength) {
    // return the max 
}

int TestMax::findMaxRecursive(int *array, int index) {
    // return the max recursively
}
7.  Variable scope

Variable Scope in Java:

  • It is possible to give the same name to variables if they are declared in different areas
  • The scope of a variable is the area in which the variable can be referred to in the program
    • Class variables can been seen anywhere, but require the class's name before it
    • Instance variables can be seen anywhere inside the class
    • Parameters are only visible inside the function
    • Local variables are only visible in the nearest containing block { ... }
  • However, Java does not allow you to have a local variable in a method with the same name as a parameter

Example (TestScope.java):

class BadlyNamedClass {
    // a is a class variable visible everywhere,
    // but requires the class name before it
    // if referred from outside
    public static int a; 
    public int x; // x is defined as a data member of the class
    
    public BadlyNamedClass() {
        x = 1;
    }

    public void methodOne (int y) {
        // Can refer to a global variable anywhere
        System.out.println("[Global Var]   A is "+a);
        // Can refer to a data member of the class anywhere in the function
        System.out.println("[Start Method] X is "+x);
        
        for(int a=0; a<1; a++) {
            int z = 3;

            System.out.println("[Inside Loop]  z is "+3);
        }
        // we can no longer refer to z anymore, as it was defined only in the block

        // We can refer to a parameter anywhere inside the function
        System.out.println("[After Loop]   y is "+y);
    }

    // x is defined also as a parameter of this function inside the class
    public void methodTwo(int x) {
        // Can refer to a global variable anywhere
        System.out.println("[Global Var]   A is "+a);

        // Scope naming resolution works by selecting the nearest and most recently
        // defined variable

        // The only way we can refer to the outside x
        // is through the 'this' pointer
        System.out.println("[Start Method] X is "+(this.x));
        for(int a=0; a<1; a++) {
            // Cannot define a local variable with the 
            // same name as a parameter in Java!
            /*
            int x = 3;
            // Refer to the x inside the loop
            System.out.println("[Inside Loop]  X is "+x);
            */
        }
        // Refer to the parameter x
        System.out.println("[After Loop]   X is "+x);
    }
};


public class TestScope {
    public static void main(String[] args) {
        
        // Refer to a class variable a
        BadlyNamedClass.a = 1;

        BadlyNamedClass b;
        b.methodOne(2);
        System.out.println();
        b.methodTwo(2);
    }
}

 

Variable Scope in C:

  • It is possible to give the same name to variables if they are declared in different areas
  • The scope of a variable is the area in which the variable can be referred to in the program
    • Global variables can be seen everywhere
    • Parameters are only visible inside the function
    • Local variables are only visible in the nearest containing block { ... }

Example (TestScope.c):

#include <stdio.h>

// Global variable
int x;

// Demonstrate where variables can be seen
void methodOne (int y) {
    // Can refer to a global variable anywhere in the function
    printf("[Start Method] X is %d\n",x);
    
    for(int a=0; a<1; a++) {
        // this variable is available only in this loop
        int z = 3;
        printf("[Inside Loop]  z is %d\n", z);
    }
    // we can no longer refer to z anymore, as it was defined only in the block

    // We can refer to a parameter anywhere inside the function
    printf("[After Loop]   y is %d\n", y);

}

// x is defined also as a parameter of this function inside the class
void methodTwo(int x) {
    
    // Scope naming resolution works by selecting the nearest and most recently
    // defined variable

    // We cannot refer to the global variable x because the scope resolution
    // will return the parameter x
    printf("[Start Method] X is %d\n", x);

    for(int a=0; a<1; a++) {
        // x is defined as local variable inside this loop
        int x = 3;
        // Refer to the x inside the loop
        printf("[Inside Loop]  X is %d\n",x);
    }
    // Refer to the parameter x
    printf("[After Loop]   X is %d\n", x);
}


int main() {
    // Refer to the global variable x, which is visible everywhere
    x=1;

    methodOne(2);
    printf("\n");
    methodTwo(2);
}

 

Variable Scope in C++:

  • It is possible to give the same name to variables if they are declared in different areas
  • The scope of a variable is the area in which the variable can be referred to in the program
    • Global variables can be seen everywhere
    • Class variables can been seen anywhere, but require the class's name before it
    • Instance variables can be see anywhere in the class
    • Parameters are only visible inside the function
    • Local variables are only visible in the nearest containing block { ... }

Example (TestScope.cpp):

#include <iostream>
using namespace std;

// Global variable - visible everywhere
int a;

class BadlyNamedClass {
public:
    // Class variable is visible everywhere, but with the help
    // of supplyng the class name: BadlyNamedClass::p
    static int p;
    int x; // x is defined as a data member of the class
    BadlyNamedClass() {
        x = 1;
    }

    void methodOne (int y) {
        // Can refer to a global variable anywhere
        cout << "[Global Var]   A is " << a << endl;
        // Can refer to a data member of the class anywhere in the function
        cout << "[Start Method] X is " << x << endl;
        
        for(int a=0; a<1; a++) {

            int z = 3;

            cout << "[Inside Loop]  z is " << 3 << endl;
        }
        // we can no longer refer to z anymore, as it was defined only in the block

        // We can refer to a parameter anywhere inside the function
        cout << "[After Loop]   y is " << y << endl;

    }

    // x is defined also as a parameter of this function inside the class
    void methodTwo(int x) {
        // Can refer to a global variable anywhere
        cout << "[Global Var]   A is " << a << endl;

        // Scope naming resolution works by selecting the nearest and most recently
        // defined variable

        // The only way we can refer to the outside x
        // is through the 'this' pointer
        cout << "[Start Method] X is " << this->x << endl;
        for(int a=0; a<1; a++) {
            // x is defined as local variable inside this loop
            int x = 3;
            // Refer to the x inside the loop
            cout << "[Inside Loop]  X is " << x << endl;
        }
        // Refer to the parameter x
        cout << "[After Loop]   X is " << x << endl;
    }
};

// initialize the class variable inside BadlyNamedClass
int BadlyNamedClass::p = -5;

int main() {
    // Refer to the global variable a
    a = 0;

    // refer to the class variable
    BadlyNamedClass::p = 5;

    BadlyNamedClass b;
    b.methodOne(2);
    cout << endl;
    b.methodTwo(2);

}
8.  Global variables

Global Variables in Java:

  • Java doesn't allow variables or objects to be declared outside of classes, so "really global" variables do not exist.
  • However we can declare static class variables inside classes which are the next best thing

Example (TestGlobalVariables.java):

// Java doesn't allow any variables to declared outside
// of classes, so the best emulation of global variables
// are static variables inside classes
class Stereo {
    // create a static (class) variable
    static int volume;

    /* Other definitions for the class */
}

class AirConditioner {
    // create a static (class) variable
    static int temperature;
    
    /* Other definitions for the class */
}

public class TestGlobalVariables {
    public static void main(String[] args) {
        // Control the stereo's global volume
        Stereo.volume = 6;

        // Control the A/C's temperature
        AirConditioner.temperature = -60;
    }
}

Global Variables in C:

C allows variables or structs to be declared outside of functions. These variables become global, as long as their file is #included or it is in the same file as the main() function

Example (TestGlobalVariables.c):

/* 
 * Control a stereo's volume and an airconditioner's temperature
 * by storing them as globals and modifying them
 */

/*
 * Declare global variables
 * Note that there is no organizational element
 * We have to implicitly know that volume is being used
 * for and what temperature is being used for
 */

int volume;
int temperature;

int main() {
    /* Control the stereo's global volume */
    volume = 6;

    /* Control the A/C's temperature  */
    temperature = -60;
}

Global Variables in C++:

  • C++ allows variables or structs to be declared outside of classes and functions. These variables become global, as long as file are #included or they are in the same file as the main() function
  • C++ also allows static members of a class, and it is often better to have these (slightly less accessible) globals than the really global variables

Example (TestGlobalVariables.cpp):

/* 
 * Control a stereo's volume and an airconditioner's temperature
 * by storing them as globals and modifying them
 */

/*
 * Declare global variables
 * Note that there is no organizational element
 * We have to implicitly know that volume is being used
 * for and what temperature is being used for
 */

int globalValue1;
int globalValue2;

// Also declare static data inside classes.
// this is a better approach, as it enforces some
// heirarchy to where variables belong

class Stereo {
public:
    static int volume;
};

// initialize the static value (required)
int Stereo::volume = 0;

class AirConditioner {
public:
    static int temperature;
};

// initialize the static value (required)
int AirConditioner::temperature = 0;

int main() {
    // Access global values
    globalValue1 = 5;
    globalValue2 = 9393;

    /* Control the stereo's global volume */
    Stereo::volume = 6;

    /* Control the A/C's temperature  */
    AirConditioner::temperature = -60;
}
9.  Method parameters

Method Parameters in Java:

  • Method parameters are variables or objects which are declared as part of a method declaration for use in the method.
  • When the method is invoked, the parameters must be supplied so that the method can correctly execute.
  • Method parameters are passed by-value, meaning that the data passed to a parameter is actually copied at run-time and the copy is used within the method, making traditional 'swap' methods impossible.
    • However, workarounds are available using object references
  • See References and Methods for examples on parameters

Method Parameters in C:

  • Function parameters are variables or objects which are declared as part of a function declaration for use in the method.
  • When the function is invoked, the parameters must be supplied so that the function can correctly execute.
  • Function parameters are passed by-value, meaning that the data passed to a parameter is actually copied at run-time and the copy is used within the function, making traditional 'swap' methods impossible.
    • However, workarounds are available using pointers
  • See References and Methods for examples on parameters

Method Parameters in C++:

  • Function parameters are variables or objects which are declared as part of a function declaration for use in the method.
  • When the function is invoked, the parameters must be supplied so that the function can correctly execute.
  • Function parameters are passed by-value, meaning that the data passed to a parameter is actually copied at run-time and the copy is used within the function, making traditional 'swap' methods impossible.
    • However, workarounds are available using pointers
  • See References and Methods for examples on parameters
H.  Objects
1.  Static objects 

Static Objects in Java:

  • A static object in Java is a class which has only static data and static methods
  • A static object never instantiated; You will never have a variable that is static object type.
  • The data and methods of a static object are accessed by the class name, since there are no instances
    • Classname.data, or Classname.method(...)
  • Since there are no instances of a static object, if you modify a static object in one piece of code, it is changed throughout the program.

Example:

// Define a static object called A
class A {
    // Static data and methods
    static int data1 = 1;
    static double data2 = 5.00;

    static void doSomething() {
        System.out.println("I am static. and my data is "+data1+" and "+data2);
    }
}

public class TestStaticObjects {
    public static void main(String[] args) {
        // A static object doesn't have to be instantiated
        // It is like it already exists, and we use its functions

        // Note that we are using the CLASS, A, and not an instance of a class
        A.doSomething();
        A.data1 = 5;
        A.data2 = 27.00;
        A.doSomething();
    }
}

Static Objects in C:

  • C has no support for classes, and so it doesn't support static objects

Static Objects in C++:

  • A static object in C++ is a class which has only static data and static methods
  • A static object never instantiated; You will never have a variable that is static object type.
  • The data and methods of a static object are accessed by the class name, since there are no instances
    • Classname::data, or Classname::method(...)
  • Since there are no instances of a static object, if you modify a static object in one piece of code, it is changed throughout the program.

Example:

#include <iostream>
using namespace std;

// Define the class prototype - usually would be done /////////////
// in another file, such as A.h and then #included in
// the main program's file
class A {
public:
    // Static data and methods
    static int data1;
    static double data2;

    static void doSomething();

};

// Implement the functions and data of the class A ////////////////
// - usually would be done in another file, such as A.cpp
// then would #include "A.h" inside it

// Must initialize a static member outside the class, such as this:
// Initialize static members of class A
int     A::data1 = 1;
double  A::data2 = 5.00;

void A::doSomething() {
    cout << "I am static. and my data is " << data1 << " and " << data2 << endl;
}

// Main program
int main() {
    // A static object doesn't have to be instantiated
    // It is like it already exists, and we use its functions

    // Note that we are using the CLASS, A, and not an instance of a class
    A::doSomething();
    A::data1 = 5;
    A::data2 = 27.00;
    A::doSomething();
}
2.  Dynamic objects 

Dynamic Objects in Java:

  • A dynamic object in Java is a class which has only dynamic data and dynamic methods
  • A dynamic object must always be instantiated to be used.
  • To use it, you have to create a variable of the dynamic object type.
  • The data and methods of a dynamic object belong to the instance of that type.
  • They are accessed by the variable's name, since there is no other way to access them
    • VariableNameofDynamicObjectType.data, or VariableNameofDynamicObjectType.method(...)
  • Since dynamic data and methods belong to the variable, if you modify a dynamic object's data in one piece of code, only that variable's data is changed.

Example:

// Define a dynamic object called A
class A {
    // Dynamic data and methods  they are not static
    int data1 = 1;
    double data2 = 5.00;

    void doSomething() {
        System.out.println("I am dynamic. and my data is "+data1+" and "+data2);
    }
}

public class TestDynamicObjects {
    public static void main(String[] args) {
        // A dynamic object must always be instantiated
        A myDynamicVariable = new A();

        // Note that we are using the Variable name, myDynamicVariable, 
        // and not the classname, A

        myDynamicVariable.doSomething();
        myDynamicVariable.data1 = 5;
        myDynamicVariable.data2 = 27.00;
        myDynamicVariable.doSomething();

        // The following will not compile
A.data1 = 30;
A.data2 = 445.00; } }

Dynamic Objects in C:

  • C has no support for classes, and so it doesn't support dynamic objects

Dynamic Objects in C++:

  • A dynamic object in C++ is a class which has only dynamic data and dynamic methods
  • A dynamic object must always be instantiated to be used.
  • To use it, you have to create a variable of the dynamic object type.
  • The data and methods of a dynamic object belong to the instance of that type.
  • They are accessed by the variable's name, since there is no other way to access them
    • VariableNameofDynamicObjectType.data, or VariableNameofDynamicObjectType.method(...)
  • Since dynamic data and methods belong to the variable, if you modify a dynamic object's data in one piece of code, only that variable's data is changed.

Example:

#include <iostream>
using namespace std;

// Define the class prototype - usually would be done /////////////
// in another file, such as A.h and then #included in
// the main program's file
class A {
public:
    // Dynamic data and methods
    int data1;
    double data2;

    A();
    void doSomething();

};

// Implement the functions of class A ////////////////
// - usually would be done in another file, such as A.cpp
// then would #include "A.h" inside it

// Implement the default constructor so that we can 
// assign default values to data1 and data2
A::A() {
    data1 = 1;
    data2 = 5.00;
}

void A::doSomething() {
    cout << "I am dynamic. and my data is " << data1 << " and " << data2 << endl;
}

// Main program
int main() {
    // A dynamic object must always be instantiated
    A myDynamicVariable;

    // Note that we are using the Variable name, myDynamicVariable, 
    // and not the classname, A

    myDynamicVariable.doSomething();
    myDynamicVariable.data1 = 5;
    myDynamicVariable.data2 = 27.00;
    myDynamicVariable.doSomething();

    
    // The following will not compile
    A::data1 = 30;
    A::data2 = 445.00;
    
}
3. Static & Dynamic Objects

Static & Dynamic Objects in Java:

  • Java can have objects that have both static and dynamic elements to them
  • The dynamic elements are known as instance variables and instance methods
  • The static elements are known as class variables and class methods
  • Memory for dynamic elements are separately allocated for each instance of the object, while static elements are created only once, and is shared between all instances of that object.
  • Each object gets its own copies of each of the ordinary data members of a class, but only one instance of each static data member exists, regardless of how many class objects have been defined.
  • Changing a variable's dynamic data results only in that variable's data being modified
  • Change a variable's static data results in the change being reflected in ALL instances of that object.
  • Confusingly, the static elements can be accessed and modified from an instance variable as well as through the classname itself.
  • A static function is independent of all dynamic data in a class. It can only see other static functions and static data on its own.

Example:

class Car {
    // Static data
    static String brandName = "Ferrari";

    // Dynamic data
    int topSpeed;
    String ownerName;

    // Static function - independent of dynamic elements of a class
    static void printCarData(Car c) {
        System.out.println("------------------------------");
        // Notice that static brandName is accessed directly
        System.out.println("Brand Name (class): "+brandName);

        // Alternatively, one can access it with instance variable c
        System.out.println("Brand Name (instance): "+c.brandName);

        // Print out the contents of instance variable c
        System.out.println("Top Speed: "+c.topSpeed);
        System.out.println("Owner: "+c.ownerName);

        // The following will not compile 
        // - which variable's topSpeed is being referred to?
        System.out.println("Top Speed: "+topSpeed);

        System.out.println("------------------------------");
    }

    // Dynamic function
    boolean isFasterThan(int speed) {
        // Notice that we can access the dynamic data directly
        return (topSpeed > speed);
    }
}

public class TestStaticDynamicObjects {
    public static void main(String[] args) {
        // Note that without instantiating, we can print out
        // the brandname variable of the Class Car
        System.out.println("Class Car's brandName: "+Car.brandName);

        // Instantiate a Car
        Car c1 = new Car();
        c1.topSpeed = 140;
        c1.ownerName = "Jack Handy";

        // Print the data out using the static function
        Car.printCarData(c1);
        // We can also use c1 to access the static function
        c1.printCarData(c1);

        Car c2 = new Car();
        c2.topSpeed = 250;
        c2.ownerName = "Bill Clinton";

        // Access a dynamic function that belongs to the instance variable
        System.out.println("Is c1 faster than c2? "+c1.isFasterThan(c2.topSpeed));
        System.out.println("Is c2 faster than c1? "+c2.isFasterThan(c1.topSpeed));
        
        // Modifying a static member
        Car.brandName = "Pontiac";
        // Print out the car data again - Pontiac has replaced Ferrari
        Car.printCarData(c2);
        // Confusingly, we can change the static data through an instance
        c2.brandName = "Kia";
        // Print out the car data again - Kia has replaced Pontiac
        Car.printCarData(c1);
    }
}

Static & Dynamic Objects in C:

  • C has no support for classes, and so it doesn't support static or dynamic objects

Static & Dynamic Objects in C++:

  • C++ can have objects that have both static and dynamic elements to them
  • The dynamic elements are known as instance variables and instance methods
  • The static elements are known as class variables and class methods
  • Memory for dynamic elements are separately allocated for each instance of the object, while static elements are created only once, and is shared between all instances of that object.
  • Each object gets its own copies of each of the ordinary data members of a class, but only one instance of each static data member exists, regardless of how many class objects have been defined.
  • Changing a variable's dynamic data results only in that variable's data being modified
  • Change a variable's static data results in the change being reflected in ALL instances of that object.
  • Confusingly, the static elements can be accessed and modified from an instance variable as well as through the classname itself.
  • A static function is independent of all dynamic data in a class. It can only see other static functions and static data on its own.

Example:

#include <iostream>
using namespace std;

class Car {
public:
    // Static data
    static char* brandName;

    // Dynamic data
    int topSpeed;
    char* ownerName;

    // Static function - independent of dynamic elements of a class
    static void printCarData(Car c) {
        cout << "------------------------------" << endl;
        // Notice that static brandName is accessed directly
        cout << "Brand Name (class): " << brandName << endl;

        // Alternatively, one can access it with instance variable c
        cout << "Brand Name (instance): " << c.brandName << endl;

        // Print out the contents of instance variable c
        cout << "Top Speed: " << c.topSpeed << endl;
        cout << "Owner: " << c.ownerName << endl;

        // The following will not compile 
        // - which variable's topSpeed is being referred to?
        cout << "Top Speed: " << topSpeed << endl;

        cout << "------------------------------" << endl;
    }

    // Dynamic function
    bool isFasterThan(int speed) {
        // Notice that we can access the dynamic data directly
        return (topSpeed > speed);
    }
};

// Initialize the static member of the class Car
char* Car::brandName = "Ferrari";


int main() {
    // Note that without instantiating, we can print out
    // the brandname variable of the Class Car
    cout << "Class Car's brandName: " << Car::brandName << endl;

    // Instantiate a Car
    Car c1;
    c1.topSpeed = 140;
    c1.ownerName = "Jack Handy";

    // Print the data out using the static function
    Car::printCarData(c1);
    // We can also use c1 to access the static function
    c1.printCarData(c1);

    Car c2;
    c2.topSpeed = 250;
    c2.ownerName = "Bill Clinton";

    // Access a dynamic function that belongs to the instance variable
    cout << "Is c1 faster than c2? " << c1.isFasterThan(c2.topSpeed) << endl;
    cout << "Is c2 faster than c1? " << c2.isFasterThan(c1.topSpeed) << endl;
    
    // Modifying a static member
    Car::brandName = "Pontiac";
    // Print out the car data again - Pontiac has replaced Ferrari
    Car::printCarData(c2);
    // Confusingly, we can change the static data through c2
    c2.brandName = "Kia";
    // Print out the car data again - the static variable has changed for c1
    Car::printCarData(c1);
}
4.  Instantiation 

Instantiation in Java:

  • To use variables, they must be declared if they are primitive types such as int
  • They must also be instantiated if they are objects
  • To instantiate an object means to define a variable with its name and type and give it memory in the heap.
  • Instantiation is done using the new keyword.
    • Usage: ObjectType variableName = new ObjectType();
  • Objects can be instantiated using different constructors. The parentheses during the declaration contain the values that are passed during the custom constructors.
    • ObjectType variableName = new ObjectType(5, "My Name is Bob");

Example:

// Define an object Person, which has an age and a name
class Person {
    int age;
    String name;
}

// Same as Person, but has custom constructors
class Person2 {
    int age;
    String name;

    public Person2(int theAge, String theName) {
        age = theAge;
        name = theName;
    }
}

public class TestInstantiation {
    public static void main(String[] args) {
        // Instantiate a Person and use it

        Person bob = new Person();  // declare memory for bob
        bob.age = 20;
        bob.name = "Bob";

        System.out.println("Hello, my name's "+bob.name+".");
        System.out.println("I'm "+bob.age+" years old");

        // Instantiate an object with a custom constructor
        Person2 shirley = new Person2(27, "Shirley");

        System.out.println("Hello, my name's "+shirley.name+".");
        System.out.println("I'm "+shirley.age+" years old");

        // Because Person2 has defined a custom constructor
        // we have to use one of the ones available,
        // so the following will not compile
        Person2 madeline = new Person2();


        // The following will not compile 
        // What is dave?
        // There is no 'dave' variable that has been instantiated

        dave.age = 24;
        dave.name = "Dave";
    }
}

Instantiation in C:

  • C has no support for classes, and so it doesn't support instantiation of objects

Instantiation in C++:

  • To use objects, they must be instantiated if they are objects.
  • To instantiate an object means to declare a variable with its name and type and give it memory in the heap.
    • ObjectType variableName;
  • Objects can be instantiated using different constructors. The parentheses during the declaration contain the values that are passed during the custom constructors.
    • ObjectType variableName(5, "My Name is Bob");

Example:

#include <iostream>
using namespace std;

// Define an object Person, which has an age and a name
class Person {
public:
    int age;
    char* name;
};

// Same as Person, but has custom constructors
class Person2 {
public:
    int age;
    char* name;

    Person2(int theAge, char* theName) {
        age = theAge;
        name = theName;
    }
};

int main() {
    // Instantiate a Person and use it

    Person bob;  // declare memory for bob
    bob.age = 20;
    bob.name = "Bob";

    cout << "Hello, my name's " << bob.name << "." << endl;
    cout << "I'm " << bob.age << " years old" << endl;

    // Instantiate an object with a custom constructor
    Person2 shirley(27, "Shirley");

    cout << "Hello, my name's " << shirley.name << "." << endl;
    cout << "I'm " << shirley.age << " years old" << endl;

    // Because Person2 has defined a custom constructor
    // we have to use one of the ones available,
    // so the following will not compile
    Person2 madeline;


    // The following will not compile 
    // What is dave?
    // There is no 'dave' variable that has been instantiated

    dave.age = 24;
    dave.name = "Dave";
}
5.  References 

References in Java:

  • References act as 'pointers' to the memory of an object.
  • Parameters in Java are passed by-value, so typical 'swap' functions don't work.
  • In Java, everything but primitives (int, double, float, etc.) are handled with references
  • Since variables representing objects are really references to them, it is possible to modify an object when it is passed as a parameter to a function.
  • This is because the reference is copied (by-value), so it can still be used to modify the object.
  • It is possible, then, to create objects such as linked lists.
  • Java does not allow operations on references, such as pointer arithmetic.

Example (TestReferences1.java):

class ThingSwapper {
    public static void swap(SomeData s1, SomeData s2) {
        // Simple s1 = s2 doesn't work, must modify the data
        // instead of swapping pointers for call-by-ref to work
        String temp = s1.s;
        s1.s = s2.s;
        s2.s = temp;
    }
}

class SomeData {
    String s;
    public SomeData(String s1) { s = s1; }
}

public class TestReferences1 {
    public static void main(String[] args) {
        SomeData s1 = new SomeData("Hello");
        SomeData s2 = new SomeData("Goodbye");

        System.out.println(s1.s + " " + s2.s);
        ThingSwapper.swap(s1,s2);
        System.out.println(s1.s + " " + s2.s);
    }
}

Example (TestReferences2.java):

class MyLinkedList {
    MyNode front;
    MyNode rear;
    int currentSize = 0;
 
    // Init. the list and references
    public MyLinkedList() {
        currentSize = 0;
        front = null;
        rear = front;
    }

    // Add data to the end of the list and
    // update the reference to the rear
    public void add(int data) {
        if(currentSize == 0) {
            // Allocate memory for the first reference and point front
            // and rear to the new memory
            front = new MyNode(data);
            rear = front;
        } else {
            // Use the reference to the rear to create a new
            // MyNode at the end
            rear.next = new MyNode(data);
            // Update the reference to 'point' to the new rear
            rear = rear.next;
        }
        currentSize++;
    }

    public void printContents() {
        // Create a temporary reference to the front
        // We will use this reference to 'walk' the list
        MyNode temp = front;
        while(temp != null) {
            System.out.println(temp.data+"");
            // Move to the next reference
            temp = temp.next;
        }
    }
}

// Represent a node in the list
class MyNode {
    // Hold some data
    int data;
    // Hold a reference to the next node in the list
    MyNode next;

    public MyNode(int data) {
        this.data = data;
        next = null;
    }
}

public class TestReferences2 {
    public static void main(String[] args) {
        // Create a (reference to a) MyLinkedList object
        MyLinkedList l = new MyLinkedList();

        l.add(5);
        l.add(2);
        l.add(23);
        l.printContents();
    }
}

References in C:

  • References are known as pointers, and they point to the memory of an object or data.
  • Pointers can be used to dynamically allocate memory when they are needed
  • Parameters in C are passed by-value, so direct 'swap' functions don't work.
  • In C, everything can have a pointer to it, using the symbol *
    • Pointer to int: int *ptr_to_an_integer;
  • When a pointer is used to represent a variable it is possible to modify it when it is passed as a parameter to a function.
  • This is because the pointer is copied (by-value), so it can still be used to modify the variable.
    • So, the pointer is copied, but since the pointer can modify the data, we are fine.
  • It is possible, then, to create linked lists, which require dynamic allocation of memory
  • C allows operations on pointers, such as pointer arithmetic.

Example (TestReferences1.c):

#include <stdio.h>

typedef struct _SomeData {
    char *s;
    _SomeData *next;
} SomeData;

// Define the function which will let us swap
void swap(SomeData *s1, SomeData *s2) {
    // We cannot just assign a new reference
    // (since s1 and s2 are really COPIES of the pointers)
    // so we have to modify the values
    char *temp = s1->s;
    s1->s = s2->s;
    s2->s = temp;
}

int main() {
    // Create pointers to SomeData and allocate memory for them
    SomeData *s1 = (SomeData *) malloc(sizeof(SomeData));
    SomeData *s2 = (SomeData *) malloc(sizeof(SomeData));

    printf("%s %s\n", s1->s, s2->s);
    swap(s1,s2);
    printf("%s %s\n", s1->s, s2->s);
}

Example (TestReferences2.c):

#include <stdio.h>

// Define a struct that represents a node in the list
typedef struct _MyNode {
    int data;
    _MyNode *next;
} MyNode;

// Represent a linked list as struct
typedef struct {
    // Pointers for the front and back of the list
    MyNode *front;
    MyNode *rear;
    int currentSize;
} LinkedList;

void initLinkedList(LinkedList *l) {
    // initialize the variables
    l->currentSize = 0;
    l->front = NULL;
    l->rear = l->front;
}

// Add an int to the list using pointers
void add(int t, LinkedList *l) {
    if(l->currentSize == 0) {
        // Allocate memory for the first pointer and point front
        // and rear to the new memory
        l->front = (MyNode *) malloc(sizeof(MyNode));
        l->front->data = t;
        l->rear = l->front;
    } else {
        // Use the pointer to the rear to create a new
        // MyNode at the end
        l->rear->next = (MyNode *) malloc(sizeof(MyNode));
        
        // Update the pointer to 'point' to the new rear
        l->rear = l->rear->next;
        // Set the data for the rear
        l->rear->data = t;
    }
    l->currentSize++;
}

void printContents(LinkedList *l) {
    // Create a temporary pointer to the front
    // We will use this pointer to 'walk' the list
    MyNode *temp = l->front;
    while(temp != NULL) {
        printf("%d\n",temp->data);
        // Move to the next pointer
        temp = temp->next;
    }
}   

int main() {
    // Create a (pointer to a) MyLinkedList object
    // Note that we could have just used a regular variable
    // but it is done as a pointer to show that it can be used
    // as a regular variable
    LinkedList *l = (LinkedList *) malloc(sizeof(LinkedList));
    initLinkedList(l);
    add(5 , l);
    add(28, l);
    add(32, l);
    printContents(l);
}

References in C++:

  • References are known as pointers, and they point to the memory of an object or data.
  • C++ pointers work the same way as C pointers
  • Pointers can be used to dynamically allocate memory when they are needed
  • Parameters in C++ are passed by-value, so direct 'swap' functions don't work.
  • In C++, everything can have a pointer to it, using the symbol *
    • Pointer to int: int *ptr_to_an_integer;
  • When a pointer is used to represent an object or variable it is possible to modify it when it is passed as a parameter to a function.
  • This is because the pointer is copied (by-value), so it can still be used to modify the object.
    • So, the pointer is copied, but since the pointer can modify the data, we are fine.
  • It is possible, then, to create objects such as linked lists.
  • C++ allows operations on pointers, such as pointer arithmetic.

Example (TestReferences1.cpp):

#include <iostream>
using namespace std;

class SomeData {
public:
    char *s;
    SomeData(char *s1) { s = s1; }
};

class ThingSwapper {
public:
    static void swap(SomeData *s1, SomeData *s2) {
        // We cannot just assign a new reference
        // (since s1 and s2 are really COPIES of the pointers)
        // so we have to modify the values
        char *temp = s1->s;
        s1->s = s2->s;
        s2->s = temp;
    }
};


int main() {
    // Create pointers to SomeData and allocate memory for them
    SomeData *s1 = new SomeData("Hello");
    SomeData *s2 = new SomeData("Goodbye");

    cout << s1->s <<  " " <<  s2->s << endl;
    ThingSwapper::swap(s1,s2);
    cout << s1->s <<  " " <<  s2->s << endl;
}

Example (TestReferences2.cpp):

#include <iostream>
using namespace std;

// Define a class that represents a node in the list
class MyNode {
public:
    int data;
    MyNode *next;
    
    // Declare 3 types of constructors
    MyNode() {
        data = NULL;
        next = NULL;
    }
    
    MyNode(int t) {
        data = t;
        next = NULL;
    }

    MyNode(int t, MyNode *n) {
        data = t;
        next = n;
    }
};

// Linked List using pointers
class LinkedList {
private:
    // Pointers for the front and back of the list
    MyNode *front;
    MyNode *rear;
    int currentSize;

public:
    LinkedList() {
        // Init. the list and pointers
        currentSize = 0;
        front = NULL;
        rear = front;
    }
    
    // Add an int to the list using pointers
    void add(int t) {
        if(currentSize == 0) {
            // Allocate memory for the first pointer and point front
            // and rear to the new memory
            front = new MyNode(t);
            rear = front;
        } else {
            // Use the pointer to the rear to create a new
            // MyNode at the end
            rear->next = new MyNode(t);
            // Update the pointer to 'point' to the new rear
            rear = rear->next;
        }
        currentSize++;
    }

    void printContents() {
        // Create a temporary pointer to the front
        // We will use this pointer to 'walk' the list
        MyNode *temp = front;
        while(temp != NULL) {
            cout << temp->data << endl;
            // Move to the next pointer
            temp = temp->next;
        }
    }       
};

int main() {
    // Create a (pointer to a) MyLinkedList object
    // Note that we could have just used a regular variable
    // but it is done as a pointer to show that it can be used
    // as a regular variable
    LinkedList *l = new LinkedList();
    l->add(5);
    l->add(28);
    l->add(32);
    l->printContents();
}
6.  Constructors 

Constructors in Java:

  • In Java, classes can be instantiated with different "constructors"
  • When a class is instantiated, one can use a constructor to give it some default data or information
  • If no constructor is defined for a class, then Java will use the default constructor
  • The default constructor of a class only allocates memory for that class, and does not initialize anything inside the class
  • The default constructor can also be overloaded, so even though you are not giving it any default data, you can at least initialize your data to certain values
  • If you write custom constructors for your class, then that class cannot use the default constructor, unless you also define that.

Example:

public class TestConstructors {

    int x;

    double y;


    // No parameters constructor (default constructor overloaded)
    public TestConstructors() {
        // set some default values for x and y
        x = 0;
        y = 0.0;
    }


    // Constructor which only sets the x value (y is set to some default)
    public TestConstructors(int valueX) {
        x = valueX;
        y = 0.0; // we didn't get a value for y, so set it to default

    }


    // Constructor which sets both variables
    public TestConstructors(int valueX, double valueY) {
        x = valueX;
        y = valueY;
    }


    // Main function to test different constructors
    public static void main(String[] args) {
        // Use the default constructor and print out the values
        TestConstructors A = new TestConstructors();
        System.out.println("X = "+A.x+", Y = "+A.y);


        // Use the one parameter constructor
        TestConstructors B = new TestConstructors(5);
        System.out.println("X = "+B.x+", Y = "+B.y);

        // Use the 2 parameter constructor
        TestConstructors C = new TestConstructors(5, 7.0);
        System.out.println("X = "+C.x+", Y = "+C.y);
    }

}    
        

Constructors in C:

  • C does not support classes, and so constructors are not used.

Constructors in C++:

  • In C++, classes can be instantiated with different "constructors"
  • When a class is instantiated, one can use a constructor to give it some default data or information
  • If no constructor is defined for a class, then C++ will use the default constructor
  • The default constructor of a class only allocates memory for that class, and does not initialize anything inside the class
  • The default constructor can also be overloaded, so even though you are not giving it any default data, you can at least initialize your data to certain values
  • If you write custom constructors for your class, then that class cannot use the default constructor, unless you also define that.

Example:

#include <iostream>
using namespace std;

class TestConstructors {
public:
    int x;
    double y;

    // No parameters constructor (default constructor overloaded)
    TestConstructors() {
        // set some default values for x and y
        x = 0;
        y = 0.0;
    }

    // Constructor which only sets the x value (y is set to some default)
    TestConstructors(int valueX) {
        x = valueX;
        y = 0.0; // we didn't get a value for y, so set it to default

    }

    // Constructor which sets both variables
    TestConstructors(int valueX, double valueY) {
        x = valueX;
        y = valueY;
    }
};


// Main function to test different constructors
int main() {
    // Use the default constructor and print out the values
    TestConstructors A;
    cout << "X = " << A.x << ", Y = " << A.y << endl;


    // Use the one parameter constructor
    TestConstructors B(5);
    cout << "X = " << B.x << ", Y = " << B.y << endl;

    // Use the 2 parameter constructor
    TestConstructors C(5, 7.0);
    cout << "X = " << C.x << ", Y = " << C.y << endl;
}
7.  Name overloading 

Name overloading in Java:

  • Overloading allows you to use the same name in different functions and, in each instance, to have the compiler choose the correct version for the job.
  • In Java we overload the names of methods in classes, so that even though they may have the same name, they take different parameters. The compiler will know which one we want to use based on the parameters we pass it.
  • If we try to use a method with parameters that we did not define, then the compiler will complain
  • Can make code easier to read and understand

Example:

public class TestOverloading {
	String concat(int i, int j) {
		// convert i, j to strings and concatenate
		String s = ""+i+j; // concatenate, not add
		return s;
	}

	String concat(String s1, String s2) {
		return s1+s2;
	}

	String concat(double x, double y) {
		String s = ""+x+y; // concatenate, not add
		return s;
	}

	String concat(int i, double y) {
		String s = ""+i+y; // concatenate, not add
		return s;
	}

	String concat(double x, int j) {
		String s = ""+x+j; // concatenate, not add
		return s;
	}

	String concat(String s1, double y) {
		String s = ""+s1+y;
		return s;
	}

	public static void main(String[] args) {
		TestOverloading t = new TestOverloading();

		// Note that the function called is the same for each
		// test int, int
		System.out.println(t.concat(5,7));
		// test string, string
		System.out.println(t.concat("heli","copter"));
		// test double, double
		System.out.println(t.concat(7.0,5.0));
		// test int, double
		System.out.println(t.concat(20,0.5));
		// test double, int
		System.out.println(t.concat(4.6984, 200));
		// test string, double
		System.out.println(t.concat("Hello", 3.1415));
	}
}

Name overloading in C:

  • Since C doesn't support objects, name overloading is not supported.

Name overloading in C++:

  • Overloading allows you to use the same name in different functions and, in each instance, to have the compiler choose the correct version for the job.
  • In C++ we overload the names of methods in classes, so that even though they may have the same name, they take different parameters. The compiler will know which one we want to use based on the parameters we pass it.
  • If we try to use a method with parameters that we did not define, then the compiler will complain
  • Can make code easier to read and understand

Example:

#include <iostream>
using namespace std;
#include <string.h>
class TestOverloading {
public:
    char* concat(int i, int j) {
        // convert i, j to strings and concatenate
        // function sprintf converts formatted data into a string
        char *s = new char[20]; // declare some memory for the concatenated string
        sprintf(s,"%d%d",i,j);
        return s;
    }
    char* concat(char* s1, char* s2) {
         // use the function strcat to concatenate two strings
         char *s = new char[strlen(s1)+strlen(s2)+1]; // +1 for null terminated character
         sprintf(s,"%s%s",s1,s2);
         return s;
    }
         
    char* concat(double x, double y) {
         char *s = new char[20]; // declare some memory for the concatenated string
         sprintf(s,"%f%f",x,y);
         return s;
    }
    char* concat(int i, double y) {
         char *s = new char[20]; // declare some memory for the concatenated string
         sprintf(s,"%d%f",i,y);
         return s;
    }
    char* concat(double x, int j) {
         char *s = new char[20]; // declare some memory for the concatenated string
         sprintf(s,"%f%d",x,j);
         return s;
    }
    char* concat(char* s1, double y) {
         char *s = new char[20]; // declare some memory for the concatenated string
         sprintf(s,"%s%f",s1,y);
         return s;
    }
};
int main() {
    TestOverloading t;
    // Note that the function called is the same for each
    // test int, int
    cout << t.concat(5,7) << endl;
    // test string, string
    cout << t.concat("heli","copter") << endl;
    // test double, double
    cout << t.concat(7.0,5.0) << endl;
    // test int, double
    cout << t.concat(20,0.5) << endl;
    // test double, int
    cout << t.concat(4.6984, 200) << endl;
    // test string, double
    cout << t.concat("Hello", 3.1415) << endl;
}
8.  Inheritance 

Inheritance in Java:

  • To provide a hierarchical representating of objects, Java allows objects to "extend" other objects
  • The new object "inherits" all of the public elements of the base object.
  • To make an object extend another, use the keyword extends
    • class NewClass extends BaseClass {....}

Example:

class A {
    // data:
    int data1 = 1;
    int data2 = 2;

    // methods:
    void methodOne () {
        System.out.println ("method one: data1=" + data1);
    }

    void methodTwo () {
        System.out.println ("method two: data2=" + data2);
    }
}

// B inherits all the data members and functions from A
class B extends A {
    // B's own data, not in A:
    int data3 = 3;

    // B's own method, not in A:
    void methodThree () {
        System.out.println ("method three: data3=" + data3);
    }
}

public class TestInheritance {
    public static void main (String[] argv) {
        A a = new A();
        B b = new B();

        // We can call "methodOne" from A, since it belongs to A anyway
        a.methodOne();

        // Then, B inherits everything from A. For example, it inherits
        // "methodOne", that we can call in an instance variable of B:
        b.methodOne ();

        // First, we'll access B's own newly created methods (not in A):
        b.methodThree ();

        // A does not have any of the new elements of B
        // The following will not compile because it is of type A
        a.methodThree();
    }
}

Inheritance in C:

  • C has no support for classes, and so it doesn't support inheritance.

Inheritance in C++:

  • C++ allows objects to "extend" other objects
  • The new object"inherits" all of the public elements of the base object.
  • To make an object extend another, use the symbol : when you declare the class
    • class NewClass : <access_specification> BaseClass {....}
  • The access specification determines the highest permissions that the inherited elements can be
  • By default, the access specification is private, meaning that all public elements of the Baseclass will be private elements of the NewClass. To change this, set the specification to public when declaring the new class.

Example:

#include <iostream>
using namespace std;

class A {
public:
    // data:
    int data1;
    int data2;

    // override the default constructor to initialize data1 and data2
    A() {
        data1 = 1;
        data2 = 2;
    }

    // methods:
    void methodOne () {
        cout << "method one: data1=" << data1 << endl;
    }

    void methodTwo () {
        cout << "method two: data2=" << data2 << endl;
    }
};


// B inherits all the data members and functions from A
class B: public A {
public:
    // B's own data, not in A:
    int data3;

    // override the default constructor to initialize data1 and data2
    B() {
        data3 = 3;
    }

    // B's own method, not in A:
    void methodThree () {
        cout << "method three: data3=" << data3 << endl;
    }
};

int main () {
    A a;
    B b;

    // We can call "methodOne" from A, since it belongs to A anyway
    a.methodOne();

    // Then, B inherits everything from A. For example, it inherits
    // "methodOne", that we can call in an instance variable of B:
    b.methodOne ();

    // First, we'll access B's own newly created methods (not in A):
    b.methodThree ();

    // A does not have any of the new elements of B
    // The following will not compile because it is of type A
    a.methodThree();
}
9.  Method overriding 

Method Overriding in Java:

  • Objects that extend others can not only inherit the base object's elements, it can also "override" them
  • The new method is used when it is called from the new class, instead of the older inherited one
  • Keep the same signature, but modify the actions in the methods

Example:

class A {
    // data:
    int data1;
    int data2;

    public A() {
        data1 = 1;
        data2 = 2;
    }

    // methods:
    void methodOne () {
        System.out.println ("A's method one: data1=" + data1);
    }

    void methodTwo () {
        System.out.println ("A's method two: data2=" + data2);
    }
}

// B inherits all the data members and functions from A
class B extends A {
    
    // Override (shadow) data2 from the base class
    int data2;

    // set the default constructor to initialize the inherited elements
    public B() {
        // different values of data1 and data2
        data1 = 3;
        data2 = 4;
    }

    // Override A's methodTwo to make our own
    void methodTwo () {
        System.out.println ("B's method two: data2=" + data2);
    }
}

public class TestMethodOverriding {
    public static void main (String[] argv) {
        A a = new A();
        B b = new B();

        // Run both "methodOne" and "methodTwo" of A
        a.methodOne();
        a.methodTwo();

        System.out.println();

        // Run both "methodOne" and "methodTwo" of B
        b.methodOne(); // Will display "A's method one: data1=3"

        // Then, execute B's overridden method "methodTwo"
        b.methodTwo();
    }
}

Method Overriding in C:

  • C has no support for classes, and so it doesn't support method overriding.

Method Overriding in C++:

  • Objects that extend others can not only inherit the base object's elements, it can also "override" them
  • The new method is used when it is called from the new class, instead of the older inherited one's
  • Keep the same signature, but modify the actions in the methods

Example:

#include <iostream>
using namespace std;

class A {
public:
    // data:
    int data1;
    int data2;

    // override the default constructor to initialize data1 and data2
    A() {
        data1 = 1;
        data2 = 2;
    }

    // methods:
    void methodOne () {
        cout << "A's method one: data1=" << data1 << endl;
    }

    // method is virtual to force dynamic linkage
    virtual void methodTwo () {
        cout << "A's method two: data2=" << data2 << endl;
    }
};


// B inherits all the data members and functions from A
class B: public A {
public:
    // B overrides (overshadows) A's instance variables
    int data1;
    int data2;

    // set the default constructor to initialize the inherited elements
    B() {
        // different values of data1 and data2
        data1 = 100;
        data2 = 200;
    }

    // Override A's methodTwo to make our own
    // method is virtual to force dynamic linkage
    virtual void methodTwo () {
        cout << "B's method two: data2=" << data2 << endl;
    }
};

int main () {
    A a;
    B b;

    // Run both "methodOne" and "methodTwo" of A
    a.methodOne();
    a.methodTwo();

    cout << endl;

    // Run both "methodOne" and "methodTwo" of B
    b.methodOne(); // Will display "A's method one: data1=3"

    // Then, execute B's overridden method "methodTwo"
    b.methodTwo();
}
10.  Polymorphism 

Polymorphism in Java:

  • Polymorphism is, generally, the ability to appear in many forms
  • Polymorphism allows an object of type A represent all objects of types that extend from A
  • The compiler correctly determines which methods to call, if derived classes override the base class methods
  • It is a powerful tool that can improve the scalability and extendability of programs

Example:

class A {
    // data:
    int data1;
    int data2;

    public A() {
        data1 = 1;
        data2 = 2;
    }

    // methods:
    void methodOne () {
        System.out.println ("A's method one: data1=" + data1);
    }

    void methodTwo () {
        System.out.println ("A's method two: data2=" + data2);
    }
}

// B inherits all the data members and functions from A
class B extends A {

    // B overrides (overshadows) A's instance variables
    int data1;
    int data2;

    // set the default constructor to initialize the overridden elements
    public B() {
        // different values of data1 and data2
        data1 = 100;
        data2 = 200;
    }

    // Override A's methodTwo to make our own
    void methodTwo () {
        System.out.println ("B's method two: data2=" + data2);
    }
}

class FancyDataStructure {
    public static void doSomethingWithA(A a) {
        /* do something, it's not important what */
        a.methodTwo();
    }
}

public class TestPolymorphism {
    public static void main (String[] argv) {
        A a = new A();
        B b = new B();

        System.out.println("Executing A methods:");
        // Run both "methodOne" and "methodTwo" of A
        a.methodOne();
        a.methodTwo();

        System.out.println("\nExecuting B methods:");
        // Run both "methodOne" and "methodTwo" of B
        b.methodOne(); // Will display "A's method one: data1=1"

        // Then, execute B's overridden method "methodTwo"
        b.methodTwo();

        
        // Now for polymorphism. Here, we are declaring a variable "a" of type "A".
        // To this variable, we are assigning a "B" instance so that "a" points
        // to the B instance that "b" is also pointing to. What this really means
        // is that the blob contains the method "methodTwo()" in class B.
        System.out.println("\nNow A points to B");
        a = b;

        // This calls "methodTwo()" in the class B, because the blob contains 
        // that method.
        a.methodTwo();

        // Here's a surprise: data is treated differently.
        System.out.println("A's data2 = "+a.data2+", B's data2 = "+b.data2);

        // This prints different variables for data2. Why? Because data2 is "shadowed"
        // rather than overridden. By casting, we remove the shadow.

        // Why is it called polymorphism? Because, in the above example, the
        // variable "a" is really pointing to something that's at least of
        // of type A. It happens to be a "B" object, but every "B" object is
        // an "A" object because it inherits everything from "A" (and maybe 
        // overrides some things in it). Thus, the B instance is a "morph"
        // of the A instance.

        // Because and data type for A can hold types of B, other programs
        // that were meant only for types A can accept types B
        A newA = new A();
        B newB = new B();
        FancyDataStructure.doSomethingWithA(newA);
        FancyDataStructure.doSomethingWithA(newB);
    }
}

Polymorphism in C:

  • C has no support for classes, and so it doesn't support polymorphism.

Polymorphism in C++:

  • Polymorphism is, generally, the ability to appear in many forms
  • Polymorphism allows an object of type A represent all objects of types that extend from A
  • The compiler correctly determines which methods to call, if derived classes override the base class methods
  • In order to make the compiler determine the correct method to call, functions must be resolved dynamically at run-time, and not statically at compile-time.
    • Use virtual keyword in front of functions you want to be resolved at run-time
  • It is a powerful tool that can improve the scalability and extendability of programs

Example:

#include <iostream>
using namespace std;

class A {
public:
    // data:
    int data1;
    int data2;

    // override the default constructor to initialize data1 and data2
    A() {
        data1 = 1;
        data2 = 2;
    }

    // methods:
    void methodOne () {
        cout << "A's method one: data1=" << data1 << endl;
    }

    virtual void methodTwo () {
        cout << "A's method two: data2=" << data2 << endl;
    }
};


// B inherits all the data members and functions from A
class B: public A {
public:
    // B overrides (overshadows) A's instance variables
    int data1;
    int data2;

    // set the default constructor to initialize the inherited elements
    B() {
        // different values of data1 and data2
        data1 = 100;
        data2 = 200;
    }

    // Override A's methodTwo to make our own
    virtual void methodTwo () {
        cout << "B's method two: data2=" << data2 << endl;
    }
};

class FancyDataStructure {
public:
    static void doSomethingWithA(A *a) {
        /* do something, it's not important what */
        a->methodTwo();
    }
};

int main () {
    A *a = new A();
    B *b = new B();

    cout << "Executing A methods:" << endl;
    // Run both "methodOne" and "methodTwo" of A
    a->methodOne();
    a->methodTwo();

    cout << endl;

    cout << "Executing B methods:" << endl;
    // Run both "methodOne" and "methodTwo" of B
    b->methodOne(); // Will display "A's method one: data1=3"

    // Then, execute B's overridden method "methodTwo"
    b->methodTwo();

    cout << endl;

    // Now for polymorphism. Here, we are declaring a variable "a" of type "A".
    // To this variable, we are assigning a "B" instance so that "a" points
    // to the B instance that "b" is also pointing to. What this really means
    // is that the blob contains the method "methodTwo()" in class B.
    cout << "Now A points to B" << endl;
    a = b;

    // This calls "methodTwo()" in the class B, because the blob contains 
    // that method.
    a->methodTwo();

    // Here's a surprise: data is treated differently.
    cout << "A's data2 = " << a->data2 << ", B's data2 = " << b->data2 << endl;

    // This prints different variables for data2. Why? Because data2 is "shadowed"
    // rather than overridden. By casting, we remove the shadow.

    // Why is it called polymorphism? Because, in the above example, the
    // variable "a" is really pointing to something that's at least of
    // of type A. It happens to be a "B" object, but every "B" object is
    // an "A" object because it inherits everything from "A" (and maybe 
    // overrides some things in it). Thus, the B instance is a "morph"
    // of the A instance.

    // Because and data type for A can hold types of B, other programs
    // that were meant only for types A can accept types B
    A newA;
    B newB;
    FancyDataStructure::doSomethingWithA(&newA);
    FancyDataStructure::doSomethingWithA(&newB);
}
11.  Multiple inheritance 

Multiple Inheriance in Java:

  • Multiple inheritance is the ability for a derived class to have multiple base classes to extend from
  • Java does not support multiple inheritance, but allows classes to implement multiple interfaces

Multiple Inheritance in C:

  • C has no support for classes, and so it doesn't support multiple inheritance.

Multiple Inheritance in C++:

  • C++ allows a derived class to extend multiple classes.
  • This can allow for great flexibility and reduce code duplication.
  • Suppose you have a class Car and a class Aircraft, and you want to make a flying car. You could potentially subclass both Car and Aircraft to get a derived class that has both properties of a Car and an Aircraft
    • class FlyingCar : public Car, public Aircraft {...}
  • Can have problems in ambiguity if parent classes have members that look the same.

Example:

#include <iostream>
using namespace std;

class A {
public:
    int numberA;
    // Also exists in B
    char *data;

    A() {
        cout << "A constructor called" << endl;
        data = "I am A";
        numberA = 1;
    }

    // Also exists in B
    virtual int getAValue() {    return 5;    }
};

class B {
public:
    int numberB;
    // Same looking data member as in A
    char *data;

    B() {
        cout << "B constructor called" << endl;
        data = "I am B";
        numberB = 2;
    }
    // Same looking function as in A
    virtual int getAValue() {    return 10;   }
};

// C inherits from both A and B
class C : public A, public B {
public:
    void doSomething() {
        cout << "Hello, I am C and I'm doing something" << endl;
    }
};

int main() {
    cout << "Creating A: " << endl;
    A a;

    cout << "Creating B: " << endl;
    B b;

    cout << "Creating C: " << endl << endl;
    C c; // Calls both constructors of A and B

    cout << "A's value:  " << a.getAValue() << endl;
    cout << "A's data:   " << a.data << endl;
    cout << "A's number: " << a.numberA << endl;

    cout << "B's value:  " << b.getAValue() << endl;
    cout << "B's data:   " << b.data << endl;
    cout << "B's number: " << b.numberB << endl;

    // Will cause compiler error
    // Both getAValue() and data are ambigious
    // They exist in both A and B
    cout << "C's value: " << c.getAValue();
    cout << "C data: " << c.data;

    // These values have been inherited from A and B and work fine
    cout << "C's inherited value from A: " << c.numberA << endl;
    cout << "C's inherited value from B: " << c.numberB << endl;
    c.doSomething();
}
12.  Cloning 

Cloning in Java:

  • Java's highest class, Object, supports a protected clone() method, which makes a bitwise copy of one object
  • For an object to be cloneable, it must implement the tag interface, Cloneable
  • This allows a programmer to select the exact copy process of a class, so if there is something which should NOT be copied, it can be controlled by the programmer by overriding Object's clone() method.

Example (TestCloning.java):

class Copyable implements Cloneable {
    int data = 5;
    
    // Overrides Object's clone()
    public Object clone () {
        System.out.println("Clone function called");
        // Must catch exception.
        try {
            // Use object's clone
            return super.clone();
        }
        catch (CloneNotSupportedException e)
        {
            System.out.println (e);
            return null;
        }
    }
}

public class TestCloning {
    public static void main(String[] args) {
        Copyable a = new Copyable();
        a.data = 16;
        // Clone 'a'
        Copyable b = (Copyable) a.clone();

        System.out.println(a.data);
        System.out.println(b.data);
        // print memory locations
        System.out.println(a);
        System.out.println(b);
    }
}

 

Cloning in C:

  • C does not have any formal cloning mechanism

Cloning in C++:

  • C++ allows 'cloning' by allowing users to create a copy constructor
  • A copy constructor is a special constructor
  • If the class is Telephone the copy constructor syntax: Telephone(const Telephone t) { ... }

Example (TestCloning.cpp):

#include <iostream>
using namespace std;

class Copyable {
public:
    int data;
    
    Copyable() {
        data = 5;
    }
    // Override the default copy constructor
    Copyable(const Copyable& c) {
        cout << "Copy constructor called" << endl;
        data = c.data;
    }
};

int main() {
    Copyable a;
    a.data = 16;
    // Clone 'a'
    Copyable b = a;

    cout << a.data << endl;
    cout << b.data << endl;
    // print memory locations
    cout << &a << endl;
    cout << &b << endl;
}
13.  Visibility modifiers 

Visibility modifiers in Java:

  • Java supports three modes of visibility: public, private, and protected, and (blank)
  • Public allows that data member or function to be accessed from anywhere
  • Private only allows that data member or function to be seen from inside the object
  • Protected only allows that data member or function to be seen by that class, subclasses, or inside the package
  • (Blank) only allows that data member or function to be seen as public, but only inside the package (if any). If it isn't inside a package, it dealt with as public

Example (TestVisibility.java):

class A {
    public int x;
    protected int y;
    private int z;

    public A() {
        // all variables are visible
        x = 0;
        y = 0;
        z = 0;
    }

    public void methodOne() { /* */ }
    protected void methodTwo() { /* */ }
    private void methodThree() { /* */ }
}

class B extends A {
    public B() {
        // x and y are visible by z is not
        x = 5;
        y = 5;
        z = 5; // compiler error - no permission
    }
}

public class TestVisibility {
    public static void main(String[] args) {
        A a = new A();

        // access public - VISIBLE
        a.x = 10;
        // access protected - VISIBLE (A is not in a package)
        a.y = 10;
        // access private - ERROR
        a.z = 10;
    }
}

Visibility Modifiers in C:

  • C does not support visibility modifiers

Visibility Modifiers in C++:

  • C++ has a more comprehensive selection of choices for controlling visibility than Java
    • public allows that data member or function to be accessed from anywhere
    • private only allows that data member or function to be seen from inside the object, or by friend functions
    • protected only allows that data member or function to be seen by that class or its subclasses, or inside the package
    • C++ by default has all of its members declared private.
  • Instead of defining visibilty per member, C++ lets you create "sections" of the class which declare as public, private or protected. Any variables or functions declared inside that section get the visibility of that section.
  • In addition, C++ classes can control the visibility of inherited members if they are extending a base class, by supplying the visibility keyword during declaration:
    • class Something : <visibility> Anything { ... }
    • public: Inherited members retain their original visibility
    • protected: All inherited members get a max visibility of protected All public elements are now protected
    • private: All inherited members get a max visibility of private; All public or protected elements are now private

Example:

class A {
public:
    int x;
    void methodOne() { /* */ }

    A() {
        // all variables are visible
        x = 0;
        y = 0;
        z = 0;
    }

protected:
    int y;
    void methodTwo() { /* */ }
private:
    int z;
    void methodThree() { /* */ }
};


// B inherits of A's members with their original visibility
class B : public A {
public:
    B() {
        // x and y are visible but z is not
        x = 5;
        y = 5;
        z = 5; // compiler error - no permission
    }
};


// C inherits A's members with max visibility = protected
// public ==> protected
// protected stays same
// private stays same
class C : protected A {
public:
    C() {
        // x and y are visible but z is not
        x = 5;
        y = 5;
        z = 5; // compiler error - no permission
    }
};


// D inherits A's members with max visibility = private
// public ==> private
// protected ==> private
// private stays same
class D : private A {
public:
    D() {
        // x and y are visible but z is not
        x = 5;
        y = 5;
        z = 5; // compiler error - no permission
    }
};

// E has a friend function for A, so
// it can access A's private functions and members
class E {
    friend void A::methodThree();
    // E can call A's private methodThree() with no problem now
};

// F is declared as a friend of A, so it has COMPLETE access to 
// A's members (data and functions)
class F {
    friend A;
    // Now F has an all-access pass to A
};

int main() {
    A a;

    // access public - VISIBLE
    a.x = 10;
    // access protected - ERROR (we are not a subclass of A)
    a.y = 10;
    // access private - ERROR
    a.z = 10;
}

 

14.  Abstract objects 

Abstract Objects in Java:

  • Sometimes it make sense to only describe the properties of a set of objects without knowing the actual behaviour beforehand
  • If you declare a class as abstract, it cannot be used on its own. You must subclass it and implement all the methods described as abstract
  • Using the power of polymorphism, a function meant for an abstract class A will accept all of A's subclasses

Example:

abstract class A {
    // An abstract class can have non-abstract methods.
    void methodOne () {
        // ...
    }
    // If even one method is abstract, the class is abstract.
    abstract void methodTwo ();
}

class B extends A {
    // Inherits the non-abstract methods in A.

    // MUST implement the abstract method if you want to
    // create instances of B.
    void methodTwo () {
        // ...
    }
}

class FancyDataStructure {
    // This data structure has been written for objects of type "A".
    static void insertStuff (A x) {
        // This method expects an "A" type object coming in.
        x.methodOne();
        x.methodTwo();
    }
}

public class TestAbstract {
    public static void main (String[] args) {
        B b = new B ();
        // Call an inherited method.
        b.methodOne ();
        // Call an implemented method that was abstract.
        b.methodTwo ();
        // Use the extended class in a data structure meant for A
        FancyDataStructure.insertStuff(b); // works fine
    }
}

Abstract Classes in C:

  • C has no support for classes, and so it doesn't support abstract classes.

Abstract Classes in C++:

  • C++ doesn't any keyword to declare a class as abstract
  • However, the virtual keyword, used for specifying dynamic linkage, is used to define a function as abstract
  • To define a function as abstract:
  • virtual <return_type> <function_name>(<params>) = 0;
  • virtual double getVolume() = 0;
  • The '= 0' after the function, makes the function purely virtual, which is the same as abstract
  • If a class has even one pure virtual function, then the class is abstract.
  • All classes must implement the pure virtual function, or redefine it as pure virtual

Example:

class A {
public:
    // An abstract class can have non-abstract methods.
    void methodOne () {
        // ...
    }
    // If even one method is pure virtual, the class is abstract.
    // Note the '= 0' makes the function a pure virtual function
    virtual void methodTwo () = 0;
};

class B : public A {
public:
    // Inherits the non-abstract methods in A.

    // MUST implement the abstract method if you want to
    // create instances of B.
    virtual void methodTwo () {
        // ...
    }
};

class FancyDataStructure {
public:
    // This data structure has been written for objects of type "A".
    static void insertStuff (A *x) {
        // This method expects an "A" type object coming in.
        x->methodOne();
        x->methodTwo();
    }
};

int main () {
    // Must use pointers when using polymorphism to enforce dynamic linkage
    B *b = new B ();
    // Call an inherited method.
    b->methodOne ();
    // Call an implemented method that was abstract.
    b->methodTwo ();
    // Use the extended class in a data structure meant for A
    FancyDataStructure::insertStuff(b); // works fine
}
15. Interfaces

Interfaces in Java:

  • An interface is an "advertisement" of capability, a promise to implement defined methods.
  • Alternatively, an interface is a purely abstract class. (All methods are abstract).
  • The idea is, a class can implement an interface by implementing all the methods advertised in the interface.
  • Java can only extend one class, but it can implement multiple interfaces.

Example:

interface A {
    public void methodOne ();
}

interface B {
    public void methodTwo ();
}

class C {
    void methodThree () {
        // ...
    }
}

// Class D implements 2 interfaces.
class D implements A, B {
    public void methodOne () {
        // ...
    }

    public void methodTwo (){
        // ...
    }
}

// Class E can only extend one other class, but
// can implement many interfaces.
class E extends C implements A, B {
    public void methodOne () {
        // ...
    }

    public void methodTwo (){
        // ...
    }
    // methodThree is inherited
}

public class TestInterfaces {
    public static void main (String[] argv) {
        D d = new D ();
        d.methodOne ();
        d.methodTwo ();

        E e = new E();
        e.methodOne();
        e.methodTwo();
        e.methodThree();
    }
}

Interfaces in C:

  • C does not support interfaces

Interfaces in C++:

  • An interface is an "advertisement" of capability, a promise to implement defined methods.
  • C++ does not have a special interface definition
  • Interfaces can be created using purely abstract classes
  • A purely abstract class has no data members and has only pure virtual functions (See multiple inheritance)
  • Since C++ allows multiple inheritance, a class can 'implement' as many interfaces as desired.
  • The problem of ambiguity still exists, as in Java (if two base classes have the same function, data member, etc.)
16.  Operator overloading

Operator Overloading in Java:

  • Java does not support operator overloading.

Operator Overloading in C:

  • C does not support operator overloading

Operator Overloading in C++:

  • C++ supports operator overloading in its classes
  • Allows a programmer to define operations such as:
+
-
*
/
%
^
&
|
~
!
=
<
>
+=
-=
*=
/=
%=
^=
&=
|=
<<
>>
>>=
<<=
==
!=
<=
>=
&&
||
++
--
->*
,
->
[]
()
new
new[]
delete
delete[]
  • Can simplify operations between objects.
  • Can simplify mathematical operations with complex structures such as math vectors

Example:

#include <iostream>
using namespace std;

// Define an object for a 3d vector
class Vector {
public:
double x, y, z;
    // To add to Vectors together
    Vector operator+(const Vector &V) const {
         return Vector3D(x+V.x, y+V.y, z+V.z);
    }
    // To subract Vectors together
    Vector operator-(const Vector &V) const {
         return Vector3D(x-V.x, y-V.y, z-V.z);
    }
    // To divide the vector values by a constant double
    Vector operator/(const double& d) const {
         return Vector3D(x/d,y/d,z/d);
    }
    // To multiply the vector values by a constant double
    Vector operator*(const double& d) const {
         return Vector3D(x*d,y*d,z*d);
    } 
};


int main() {
    Vector A;
    A.x = 5.0;
    A.y = 7.0;
    A.z = 2.0;

    Vector B;
    B.x = 3.0;
    B.y = 6.0;
    B.z = 4.0;

    // Add two vectors together the old way:
    Vector C;
    C.x = A.x + B.x;
    C.y = A.y + B.y;
    C.z = A.z + B.z;

    // Using the overloaded operator +
    Vector D = A + B;

    // More examples:
    // Operator -
    A = B - C;
    // Operator /:  Divide all the vector's fields by a double
    B = B / 4.0;
    // Operator *:  Multiple all the vector's fields by a double
    C = A * 60.0;
}
17.  Self-reference 

Self-Reference in Java:

  • Java objects can refer to themselves using the keyword this
  • In reality, all data members inside a class are prefixed with this at compile-time. This helps resolve the scope of the data being used.
  • The this keyword can also be used to pass yourself to as a parameter to a method.

Example:

class Box {
    double length;
    double width;
    double height;
    double volume;

    public Box(double length, double width, double height) {
        // Resolve scope ambiguity with keyword 'this'
        this.length = length;
        this.width = width;
        this.height = height;

        // Pass yourself as a parameter in a function
        volume = Box.calcVolume(this);
    }

    // Static functions are independent of any dynamic data
    public static double calcVolume(Box b) {
        return (b.length * b.width *b.height);
    }
}


public class TestSelfReference {
    public static void main(String[] args) {
        Box b = new Box(4.0,6.0,2.0);
    }
}

Self-Reference in C:

  • C has no support for classes, and so it has no mechanism for self-reference.

Self-Reference in C++:

  • C++ classes can refer to themselves using the pointer this
  • In reality, all data members inside a class are prefixed with this at compile-time. This helps resolve the scope of the data being used.
  • The this keyword can also be used to pass yourself to as a parameter to a method.

Example:

class Box {
public:
    double length;
    double width;
    double height;
    double volume;

    Box(double length, double width, double height) {
        // Resolve scope ambiguity with keyword 'this'
        this->length = length;
        this->width = width;
        this->height = height;

        // Pass yourself as a parameter in a function
        volume = Box::calcVolume(this);
    }

    // Static functions are independent of any dynamic data
    static double calcVolume(Box *b) {
        return (b->length * b->width *b->height);
    }
};


int main() {
    Box b(4.0,6.0,2.0);
}
18.  Templates 

Templates in Java:

  • Templates are not currently supported in Java, but they will soon be in the forthcoming Java 1.5

Templates in C:

  • C has no support for templates.

Templates in C++:

  • Templates allow one to write a class or function which can be used for multiple types of data, instead of one.
  • Example: A linked-list class can be used to store double or char *'s or even classes, without requiring a new LinkedList for every kind of object
  • Note how the class definition has a prefix <class T>
  • T is replaced by whatever type is given to it during object creation

Example:

#include <iostream>
using namespace std;

// Define a class that represents a node in the list
// This node had a data of type T, which can be whatever
// when it is created
template<class T> class node {
public:
    T data;
    node *next;
    
    // Declare 3 types of constructors
    node() {
        data = NULL;
        next = NULL;
    }
    
    node(T t) {
        data = t;
        next = NULL;
    }

    node(T t, node *n) {
        data = t;
        next = n;
    }
};

// Linked List using Templates to hold whatever
template<class T> class LinkedList {
private:
    // Declare a node of type <T>
    node<T> *front;
    node<T> *rear;
    int currentSize;

public:
    LinkedList() {
        currentSize = 0;
        front = NULL;
        rear = front;
    }
    
    // Add a node<T> to the list
    void add(T t) {
        if(currentSize == 0) {
            front = new node<T>(t);
            rear = front;
        } else {
            rear->next = new node<T>(t);
            rear = rear->next;
        }
        currentSize++;
    }

    void printContents() {
        node<T> *temp = front;
        while(temp != NULL) {
            cout << temp->data << endl;
            temp = temp->next;
        }
    }       
};

int main() {
    LinkedList<int> l;
    l.add(5);
    l.add(28);
    l.add(32);
    l.printContents();


    LinkedList<double> l2;
    l2.add(5.2);
    l2.add(3.1415);
    l2.add(345.545);
    l2.printContents(); 

    LinkedList<char *> l3;
    l3.add("Hello");
    l3.add("Rizwan");
    l3.add("C++ is cool");
    l3.printContents(); 
}
19.  Inner classes 

Inner Classes in Java:

  • Can be useful especially during GUI programming to create listeners for certain actions in your window. Instead of declaring a whole new .java file for a Listener which is used only once, it is sometimes more efficient to just declare an inner class for use

Example:

class SomeClass {

    // Declare an inner class
    class MyInnerClass {
        int data1;
        double data2;
    }

    // Declare variable of the inner class type
    MyInnerClass inner;

    public SomeClass() {
        System.out.println("Hello, I have an inner class!");
        inner = new MyInnerClass();
        inner.data1 = 5;
        inner.data2 = 1348.898324;
    }
}

public class TestInnerClasses {
    public static void main(String[] args) {
        SomeClass something = new SomeClass();
    }
}

Inner Classes in C:

  • C does not support inner classes.

Inner Classes in C++:

  • C++ does not allow a class to be defined inside another class
20.  Components 

Components in Java:

  • Java can be distributed in components which are known as Java Beans.

Components in C:

  • C does not have any support for components

Components in C++:

  • C++ has no standard way of distribution as components
I. Standard libraries 
1.  Math 

Java Math Library:

  • Java has a built-in static math class, java.lang.Math

Example (TestMathLibrary.java):

// No import required because it is part of java.lang

public class TestMathLibrary {
    public static void main(String[] args) {

        // Get absolute value
        int x = Math.abs(-6);

        // Get the cosine of an angle in radians
        double cosine = Math.cos(Math.PI); // Use Pi representation from Math

        // Round a float to an int
        long roundedNum = Math.round(47.359);

        // Get the square root
        double root = Math.sqrt(16.0);

        // Multiply 2 to the 10rd power
        double powered = Math.pow(2, 10);
    }
}

C Math Library:

Example (TestMathLibrary.c):

#include <math.h>

int main() {

    // Get absolute value
    int x = abs(-6);

    // Get the cosine of an angle in radians
    double cosine = cos(3.1415);

    // Round a float to an int (must do manually)
    // use the floor function and add 0.5 to acheive rounding
    long roundedNum = (long) floor(47.359 + 0.5);

    // Get the square root
    double root = sqrt(16.0);

    // Multiply 2 to the 10rd power
    double powered = pow(2, 10);
}

C++ Math Library:

Example (TestMathLibrary.cpp):

#include <cmath>
using namespace std;

int main() {

    // Get absolute value
    int x = abs(-6);

    // Get the cosine of an angle in radians
    double cosine = cos(3.1415);

    // Round a float to an int (must do manually)
    // use the floor function and add 0.5 to acheive rounding
    long roundedNum = (long) floor(47.359 + 0.5);

    // Get the square root
    double root = sqrt(16.0);

    // Multiply 2 to the 10rd power
    double powered = pow(2, 10);
}
2.  I/O 

Java I/O Library:

  • Java has an extensive I/O library, known as java.io

C I/O Library:

  • By default C's standard I/O library, <stdio.h>, provides basic support for streams, particularly standard streams (for screen I/O) and file streams (for File I/O using the pointer to FILE data type)

 

C++ I/O Library:

  • C++ supports the standard library capabilities of the C standard I/O library, and expands on the idea of streams with its <iostream> library
3.  Third-party libraries 

Third-party Libraries for Java:

  • Java is supported by a very extensive network of developers who have made various libraries for almost anything that is programmable.
  • For example, there are many libraries that exist for interfacing with databases, controlling 3D video cards, etc.

Third-party Libraries for C:

  • C has various libraries written for it for programming many things, although it is not as extensive as Java or C++
  • For example, there are many libraries that exist for interfacing with databases, controlling 3D video cards, etc.

Third-party Libraries for C++:

  • C++ has had many libraries written for it, and since it is the primary language behind the Windows operating system, there are constant new libraries being develope for programming virtually anything.
  • For example, there are many libraries that exist for interfacing with databases, controlling 3D video cards, etc.
  • A very common 3rd-party library is the Standard Template Library, which adds a host of reusable datatypes, components and design patterns which can be used to extend the capability of a C++ application.
J.  I/O
1.  Screen output

Java Screen Output:

  • Java's built-in System class has a Printstream called out
  • Print just text: System.out.print("text");
  • Print text and a new line: System.out.println("text")

Example:

public class TestPrint {
  public static void main (String[] argv)
  {

    // Print text and a new line every time
    System.out.println("This line will have a return after it");
    System.out.println("So this line shows up on a new line");

    // Print just one line of text (no carriage return)
    System.out.print("This line does not have a return after it");
    System.out.print(" so this line will come right after it");
  }
}

 

C Screen Output:

  • By default, C has no "built-in" screen output function
  • The common library, stdio.h, has screen output commands
  • Use the command printf to output text
  • Printf stands for "Print formatted"
  • Must use escape characters to format text.
  • Newlines are done by the escape character \n

Example:

#include <stdio.h>

int main() {

   /* Now that we have #included stdio.h, we can use
      screen output commands: */

   /* Print lines of text with newlines at the end */
   printf("This line has a return after it\n");
   printf("so this line shows up on a new line\n");

   /* Print just lines of text, no carraige returns */
   printf("This line does not have a return after it");
   printf(" so this line will come right after it");
}

C++ Screen Output:

  • By default, C++ has no "built-in" screen output function
  • Screen output is provided by the common library iostream
  • Can use escape characters to format text
  • Newlines are done by the keyword endl

Example:

#include <iostream>

using namespace std;


int main () {
  // Now that we've included iostream, we can use
  // screen output commands
  
   // Print lines of text with newlines at the end
   cout << "This line has a return after it" << endl;
   cout << "so this line shows up on a new line" << endl;

   // Print just lines of text, no carraige returns
   cout << "This line does not have a return after it";
   cout << " so this line will come right after it";
}
2.  Keyboard input

Java Keyboard Input:

  • Although screen output is very easy using System.out.print and System.out.println, it is not as easy to perform screen input
  • The only thing you can do is read a whole line of input from the screen as a String.
  • To read int's or double's, one needs to parse the input String.

Example:

import java.io.*;

public class TestKeyboardInput {
    public static void main (String[] argv) {
        
        // We have to have a try clause because
        // the method readLine throws an exception.
        try {
            // These are the key steps in setting up the read operation.
            InputStreamReader isr = new InputStreamReader (System.in);
            LineNumberReader lr = new LineNumberReader (isr);

            // READ A STRING //////////////////////////
            // Put out a prompt.
            System.out.print ("Enter string: ");
            // Now read the input line.
            String input_line = lr.readLine ();

            // Echo it.
            System.out.println ("Echo: " + input_line);



            // READ A NUMBER /////////////////////////
            System.out.print("Enter an integer: ");
            input_line = lr.readLine();

            // Parse for an integer.
            int i = 0;
            try {
                i = Integer.parseInt (input_line);
            } catch (NumberFormatException e) {
                System.out.println ("You did not enter a number");
                System.exit (0);
            }

            // Echo it.
            System.out.println ("The integer you entered: " + i);

        } catch (IOException e) {
            // If there was a problem...
            System.out.println (e);
        }
    }
}

C Keyboard Input

  • Input is done in the same library as output: stdio.h
  • Instead of printf, we use scanf
  • Use escape character to define what kind of input you are receiving

Example:

#include <stdio.h>

int main() {
    /* Now that we have #included stdio.h, we can use
       screen io commands: */
    char *aString = (char *) malloc(sizeof(char) * 80);
    int anInteger;

    /* Give the user a message to provide information */
    printf("Enter a string: ");
    scanf("%s", &aString);
    printf("Echo: %s\n", aString);

    printf("Please enter an int: ");
    scanf("%d", &anInteger);
    printf("You entered: %d\n", anInteger);
}

C++ Keyboard Input

  • Input is done in the same library as output: iostream
  • Instead of cout, use cin
  • There are other functions available to interpret more complicated input

Example:

#include <iostream>
using namespace std;

int main() {
    // GET A STRING /////////////////
    cout << "Enter string: ";

    char *input = new char[80];
    // use getline instead of >> operator, for multiple words
    cin.getline(input, 80); 
    
    cout << "Echo: " << input << endl;

    // GET A NUMBER ////////////////
    cout << "Enter an integer: ";
    int i = 0;
    cin >> i;

    cout << "You entered " << i << endl;
}
3.  File output

File Output in Java:

  • File output is acheived most easily by using FileWriter in java's io library java.io
  • FileWriter lets us write basic bytes, so we can chain it to a PrintWriter, which allows us formatted output
  • PrintWriter is for writing text files

Example:

import java.io.*;

public class TestFileOutput {
    public static void main (String[] args) {
        try {
            // Need to associate a file with a PrintWriter.
            // The last parameter is set to "true" to indicate
            // auto-flush should be activated.
            FileWriter fr = new FileWriter ("myOutput.txt");
            PrintWriter pw = new PrintWriter (fr, true);

            // Now we're ready for writing.
            pw.println ("Hello");
            pw.println ("Hello again");

            // Done.
            pw.close();
        }
        catch (IOException e) {
            System.out.println (e);
        }
    }
}

File Output in C:

  • The common library stdio.h has a FILE structure.
  • To write to a file, create a file pointer with the filename and the open mode
  • Use the function fprintf just like printf for screen output

Example:

#include <stdio.h>

int main() {
    // Open a file and get the file pointer
    // "wt" means the file is for writing and it is a text file
    FILE *file = fopen("myOutput.txt", "wt");
    
    // Instead of printf, we use fprintf and use the same format
    fprintf(file, "Hello\n");
    fprintf(file, "Hello Again\n");

    fclose(file);
}

File Output in C++:

  • File output is done in streams, just like screen output, but requires the library fstream
  • Use << to determine what is getting written
    • File << data;
  • Note how "<<" is like an arrow pointing to the File object, indicating the direction of data transfer

Example:

#include <iostream>
#include <fstream> // for file i/o
using namespace std;

int main() {
    // Create an output stream and use it for output
    // ofstream = Output File STREAM
    ofstream file("myOutput.txt", ios::out);
    
    file << "Hello" << endl;
    file << "Hello Again" << endl;
    
    file.close();
}
4.  File input 

File Input in Java:

  • File reading is done similar to file writing. Use the FileReader object
  • FileReader allows us to read raw bytes, so use a LineNumberReader object to read line-by-line

Example:

import java.io.*;

public class TestFileInput {
    public static void main (String[] argv) {
        try {
            // These are the key steps in setting up the read operation.
            FileReader fr = new FileReader ("testdata.txt");
            LineNumberReader lr = new LineNumberReader (fr);

            // Now read the input lines
            boolean over = false;         
            int i = 1;
            do {
                // Get a line from the file.
                String input_line = lr.readLine ();
                if (input_line != null) {
                    System.out.println ("Line " + i + ": " + input_line);
                    i++;
                }
                else
                over = true;
            } while (! over);

            // Done.
            lr.close();

        } catch (IOException e) {
            // If there was a problem...
            System.out.println (e);
        }
    }
}

File Input in C:

  • File input is done using the FILE pointer used for writing to a file
  • We use the command fgets() to extract information from a text file

Example:

#include <stdio.h>

int main() {
    FILE * file;
    char inputLine [256];
    int i = 1;
    int over = 0; // false

    // Open a file for reading
    file = fopen ("testdata.txt" , "r");

    // Now read the input lines
    do {
        // Get a line from the file.
        fgets (inputLine , 256 , file);
        printf("%d: %s", i, inputLine);
        i++;

        if(feof(file)) {
            over = 1;
        }

    } while(!over);

    // Done
    fclose (file);
}

File Input in C++:

  • File input is done using streams, similar to screen i/o and file output, using the library fstream
  • Can use ">>" to get data, or can use the function getLine() to retrieve a line of text from the file

Example:

#include <iostream>
#include <fstream> // for file i/o
using namespace std;

int main() {
    
    char *inputLine = new char[256]; // hold a line of text

    // Create an input stream
    // ifstream = Input File STREAM
    ifstream file("testdata.txt", ios::in);
    
    // Now read the input lines
    int i = 1;
    bool over = false;
    do {
        // Get a line from the file.
        file.getline(inputLine, 256);
        cout << i << ": " << inputLine << endl;
        i++;

        if(file.eof()) {
            over = true;
        }

    } while(!over);
    
    // Done
    file.close();
}
K.  Strings 
L.  Math 
M.  Other comparisons 
N.  Further information 

Java Links:

C Links:

Links: