/* A "QUICK AND DIRTY" JAVA TO C++ TUTORIAL Chuck Liang Hofstra University Computer Science First Drafted April 1998, Revised January 2005 This short tutorial is intended to help intermediate-level computer science students who've taken a programming course in Java to quickly begin writing programs in C++. It is not intended as a comprehensive guide to the C++ language. There are several available books helping C++ programmers adopt to Java, but scarsely any going in the other direction. This document attempts to address this problem, as more and more programmers are being trained with Java as their first language. Students who wish to write substantial C++ programs should only use this as a starting point, and would need to consult full-scale C++ guides. I address mainly the intersection (featurewise) of Java and C++ here. The C++ language is undergoing changes. We will use the standard ANSI version and the Gnu C++ compiler. Other versions of C++ may be significantly different. In fact, Microsoft's "Visual C++ .Net" is actually closer to Java than C++ as presented here. ( This document contains real C++ source code. You can run the last sample program by compiling this file. On Unix workstations with the GNU C++ compiler installed, you should first save this file under a name with a ".C" or ".cpp" or ".cc" suffix, such as "tutorial.C". Compile the program with "g++ tutorial.C". This will produce a file named "a.out", which can be run by "./a.out". You can then rename "a.out" to something more meaningful. This document is available electronically at http://www.cs.hofstra.edu/~cscccl/csc155/quick.cpp ) FIRST EXAMPLE The Java programming language was invented as a simplification, or "cleaning up" of C++. In many cases, only minor syntactic changes are needed to get a C++ compiler to accept a Java program. Let's start by looking at a simple C++ program, with number lines in comments on the right side of each line (comments are inserted the same way as in Java). using namespace std; #include // 0. int factorial(int n) // 1. { int i; // 2. int answer; // 3. answer = 1; // 5. for(i=2;i<=n;i++) // 6. { answer = answer*i; } // 7. return answer; // 8. } // 9. int rfact(int n) // 10. { if (n<2) return 1; // 11. else return n*rfact(n-1); // 12. } // 13. int main() // 14. { int m; // 15. cin >> m; // 16. cout << "The factorial of " << m << " is " << factorial(m); // 17. cout << "\nWith the recursive version it's still " << rfact(m); // 18. cout << "\n"; // 19. return 0; // 20. } // 21. The first thing you should notice about this program is that there is no "class" anywhere! Indeed, this program is essentially a C program. C++ is backwards compatible with C, which does not use classes. The "include" statement on line 0 of the program corresponds to "import" in Java, which allows one program to use classes from another program. In C++, methods (functions) need not be inside classes, and therefore "include" may also use stand-alone functions from other programs. "iostream" is for basic input/output and is needed by most programs. The definition of the functions "factorial" and "rfact" (iterative and recursive versions of the n! function) are exactly the same as they would be in Java except that no "public" or "private" modifier can occur. "public" and "private" may only characterize functions inside classes. Stand-alone functions are globally visible. In particular, "main" must ALWAYS be a stand-alone function. Simple text I/O is available with the "cout" and "cin" commands. Line 17 in Java would be: System.out.print("The factorial of " + m + " is " + factorial(m)); You can think of "cout" as a sink or receptor of incomming items to print. The items are sent to it by "<<". The special character "\n" starts a new line. The corresponding command to input something is "cin". Line 16 asks the user to type in something on the keyboard, hit return, and assigns the value typed in to the variable m. By convention, Gnu C++ requires the main function to return an integer. A return value of 0 (line 20) indicates normal termination of the program. CLASSES Let's now look at how classes are defined in C++: using namespace std; #include class account { // bank accounts, of course! private: // private elements int balance; public: // public elements account(int initial) // constructor { balance = initial; } void deposit(int ammount) { balance = balance + ammount; } void withdraw(int ammount) { if (balance-ammount >= 0) balance = balance - ammount; } int inquiry(); // this method will be defined outside of the class }; // end of class definition (NOTE EXTRA ;) int account::inquiry() // implements "inquiry" method in class "account" { return balance; } int main() { account myaccount(500); account youraccount(200); myaccount.withdraw(30); youraccount.deposit(40); cout << "My balance is " << myaccount.inquiry() << "\n"; cout << "Your balance is " << youraccount.inquiry() << "\n"; return 0; } Notice that the account class definition is divided into two parts, headed by "private:" and "public:". In Java you would need to put "private" or "public" infront of everything you define. You may also have a "protected:" section. The meanings of "private", "protected", and "public" are the same in C++ as in Java. You do not have to declare the sections in any order. I.e, you may put the "public:" section first if you want. It's possible in C++ to define a method of a class OUTSIDE of the class definition. This is illustrated by how the "inquiry" method was defined. You need only declare a prototype "header" within the class (similar to an abstract method declaration in Java). You can then implement the method elsewhere in the program by preceding the name of method with the name of the class it should belong to, followed by "::". The prototyping of functions is also required if you are to refer to a method (or class) at a point before its defined. That is, in C++ the definition of a method is usually placed before the code where it's called (Unlike Java). You may define a subclass in C++ with the statement class savings_account : account {... Whereas in Java you would have written: class savings_account extends account {... Note also the EXTRA ";" needed after the closing "}" of the class definition. A very important difference between C++ and Java is in how new objects are declared. The line account myaccount(500); would be written in Java as: account myaccount = new account(500); Addressing this difference fully would require a discussion of how pointers are handled in C++. POINTERS C++ has a much more sophisticated set of features regarding pointers. You will recall that in Java, all variables of class type are pointers, and all variables of primitive type are non-pointers. In C++, you can declare a class type variable that's not a pointer as well as a pointer to a primitive type datum. In the above example we did not use pointers to creat accounts, and therefore the "new" imperative was not needed. The variable "myaccount" refers directly to the object: it's not a pointer! In general, however, pointers should be used to refer to objects for efficiency reasons. It is slightly more difficult to use pointers to objects in C++ than in Java. The pointer version of the above "main" program would be as follows: int main() { account* myaccount; // 1. Note "*" account* youraccount; // 2. myaccount = new account(500); // 3. Note "new" youraccount = new account(200); // 4. myaccount->withdraw(30); // 5. Note "->" youraccount->deposit(40); // 6. cout << "My balance is " << myaccount->inquiry() << "\n"; // 7. cout << "Your balance is " << youraccount->inquiry() << "\n"; // 8. delete(myaccount); // 9. Note "delete" delete(youraccount); // 10. return 0; } The "*" construct in line 1 declares that "myaccount" is to be a POINTER variable to an object of type "account". To actually allocate the memory needed for an account object, you need to use the "new" imperative, as on lines 3 and 4. To access the contents of a pointer to an object, you use "->" instead of ".". This is illustrated on lines 5-8. Using "account* myaccount" and "myaccount->withdraw(30)" more closely matches "account myaccount" and "myaccount.withdraw(30)" in Java. Furthermore, in order to pass an object as a parameter to a method, you should only use pointers. That is, methods should not be declared as in "void f(account a)" is not allowed. Instead, you should use "void f(account* a)". A major programming language feature missing in C++ is dynamic storage deallocation. In Java, once you no longer need an object, it's automatically "garbage collected" by the system. However, whenever you no longer need an object in C++, you need to explicitly "delete" the object from memory. Otherwise, there could be dangling objects taking up valuable memory space for no good reason. The "delete" statement is illustrated on lines 9 and 10. When "delete" is called on an object, a "destructor" method is executed to destroy the object. The "destructor" is the opposite of the "constructor", which is executed when "new" is called. The class "account" above includes an implicit, default destructor method, which is equivalent to ~account() { } In this case the destructor does nothing more than deallocate memory reserved for a given account object (just as the default constructor does nothing more than allocate memory). The explicit definition of non-trivial destructors will be illustrated in the sample program at the end of this tutorial. You should also be aware that instead of using "null" as the empty pointer, a pointer variable in C++ is considered null if it's equal to 0. You also can NOT assume that a pointer is automatically intialized to 0 when it's declared. Pointers to primitive type data is accomplished as in the following example: int x; // regular integer variable int *y; // declares y to be a pointer to an integer (equivalently int* y) x = 4; // assigns 4 to x y = &x; // assigns the ADDRESS of x to y *y = *y + 1; // increment the VALUE pointed to by y (same as x = x+1) // y = y + 1 // this line would increment the address, not the value cout << "the value of *y == x == " << *y; // should print 5 That is, the "&" operator takes a variable and returns its address, effectively forming a pointer to that variable. The "*" operator is used both to declare variables to be of pointer type (as on the second line), and to "de-reference" a pointer to return the value stored at the location it's pointing to (as on the last line). For example, given an object (accout* A), the expression (A->balance) is equivalent to (*A).balance. The * operator dereferences the pointer A into an actual object, with which we can use "." instead of "->" to access its contents. Pointers can be a source of confusion in C/C++ programming, and I will not go beyond this brief explanation here. TYPES A major improvement of Java over C++ is that Java is "type safe". This means, for example, that a value of type "char[]" will never end up as a value of type "int". In C++ this is unfortunately not true and is a primary reason why the language is messy. This is illustrated in how booleans, arrays and strings are used in C++: BOOLEANS: There is no separate boolean type in C++. Instead, integers are used for boolean values. "false" is represented by 0 and "true" is represented by anything non-zero. For example, (5 && 4) is a valid "boolean" expression in C++ and would evaluate to true. ARRAYS: There are two types of arrays in C++: statically and dynamically allocated. Java only have dynamically allocated arrays, which means that the memory allocated for the array is always done at runtime. On the other hand, he memory for a statically allocated array is reserved at compile time. This means that the size (not contents) of a static array must be known at compile time, and cannot change. We first show how to use static arrays as they are easier: The statement int myarray[5]; would declare an array of 5 integers in C++ (array indexing works the same way as in Java). This array also exists on the stack, not heap. You can use this array as you would an array in Java, but you cannot say "myarray.Length" - myarray is not an object. You must keep the size of the array in a separate variable. For example, the following function takes an array of integers and returns their sum: int sum(int A[], int size) { int ax = 0; for(int i=0;i from the C++ "standard template library". This type of string does resemble the String class of Java. The following fragment (assuming #include at the top) should explain how these strings can be used: string a = "bcd"; string b = "cd"; b = "b"+b; // string concatenation cout << (a==b) << endl; // == can be used (UNLIKE Java!) cout << b[1] << endl; // same as b.charAt(1) in Java cout << b.length()<< endl; // length of string - note, b is an object Although these strings are easier to use, it is best to be familiar with the char* form as well. CONCLUSION I stress again that this is only meant as a quick introduction. Do not assume that these examples represent the only way to accomplish something in C++. The SOLE purpose of this tutorial is to allow the initial transition from Java to C++ to be as painless as possible. There are, however, a few useful features of C++ which a Java programmer should be aware of. One of these is C++'s ability to pass a POINTER TO A FUNCTION as an argument. Another is the presence of "templates" in C++. Templates are a much easier way to achieve polymorphism than the abstract-class inheritance technique in Java. Look for future updates of the Java language to contain these new features. In C++ there is no such class as "Object", so inheritance will be less effective as a way to achieve polymorphism. There is also no definitive C++ equivalent of the Java graphical API (Swing). C++, unlike Java, is not platform independent. Each system must provide a library of functions to perform graphics. In Microsoft Windows operating systems, this is called the WIN32 API. There is also a more high-level interface called "MFC", and now .Net Windows Forms. On Linux systems the most commonly used graphical APIs and Qt and Gnu's Gtk+. I conclude this tutorial with a sample C++ program that inputs integers into an array and inserts every element of the array into a linked list. Note in particular the presence of the "destructor" method "~list". The destructor method is called when you "delete" an object. If an object contains pointers to inner objects, then the destructor method for the outer object must explicitly delete all the inner objects as well. Otherwise the inner objects would be left dangling. If an object does not contain inner objects, then the implicit default destructor (see "~node" in the program) would suffice. */ using namespace std; #include class cell { // list of integers public: int head; // head is NOT initially 0 cell* tail; cell(int h, cell* t) // constructor { head = h; tail = t; } ~cell() { } // destructor (this is actually the default) }; // note again extra ";" class list { // a list of integers private: cell* front; // can't assume front will be initialized to 0. public: void insert(int x) // inserts new cell to front of list { front = new cell(x,front); /* equivalently: cell* newcell; newcell = new cell(x,0); // tail intially set to null newcell->tail = front; front = newcell; */ } // end insert void print() // prints data in list { cell* current; current = front; while (current != 0) // note "0" instead of "null" { cout << current->head << "\n"; current = current->tail; } } list() { front = 0; } // constructor ~list() // destructor : must erase all cells too! { cell* temp; cell* current; current = front; cout << "Garbage collecting the list cells...\n"; while (current != 0) { temp = current; current = current->tail; delete(temp); // memory deallocation } } }; // end of class list int main() { int A[5]; // array of 5 integers list* L; // a list L = new list(); int i; // loop counter for (i=0;i<5;i++) { cout <<"Enter number: "; cin >> A[i]; // read input into A[i]; } cout << "\nInserting numbers into a list."; for (i=0;i<5;i++) L->insert(A[i]); cout << "\nAnd these are the contents of the list:\n"; L->print(); delete(L); // memory deallocation return 0; } // end of main /* This document may be freely distributed as long it's unmodified and used for academic purposes. */