C++ Overview & Comparison to Java

Basic Syntax and Structure

Input/Output

C++ input and output is done using objects and operators in the C++ library. For standard I/O the functions are in the iostream library files.
  • File I/O is similar but you define your own file stream object. As in Java, you must open the file and associate the file stream object with the specific file. Examples are in the mm1 program files.

    References and Pointers

    Recall that in Java when you declare a variable to be some object type then the variable is actually a reference to the object, that is, it contains the address of the object rather than the object itself. So for example, if the simNode class in the mm1 program were a Java class, then the declaration
        simNode myNode;
    
    would declare myNode to be a reference (currently null) to a simNode object. The actual object would be created using the new operator. In C++, the above declaration would create the actual simNode (no new would be needed). In either case to access the data in the node or to invoke a function (method) to operate on the node you would use the dot operator -- for example, myNode.time or myNode.getTime().

    In C++ when you declare an object as above, the default constructor (with no parameters) is invoked to create the object. If you want to use a different constructor, one with parameters, to construct the object you use the parameters in the declaration. For example, in the simNode class has several different constructors. The following declaration creates a simNode object named arrival using the constructor with two parameters (the first parameter is the time for the event and the second is the type - 0 means arrival).

         simNode arrival (45.3, 0);
    

    Often in C++ we want to declare a reference (pointer) to an object. The following declaration declares myNode as a pointer to a simNode:

         simNode * myNode;
    
    The actual node would be constructed using the new operator - for example,
         myNode = new simNode(23.3);
    
    creates a new simNode with time of 23.3.

    In this case to access data in the node or invoke a function you use the -> operator as in myNode->time or myNode->getTime(). (An alternate, which is not used in the example program, is to use *myNode.time or *myNode.getTime() -- *myNode is the actual object pointed to by myNode.)

    Parameter Passing

    The default mode of parameter passing in C++, as in Java, is pass by value. Parameters passed this way are not changed by the function (method). But in Java because the "value" of an object variable is a reference, the reference isn't changed but the object it refers to can be changed. To do the same thing in C++ your parameter must be a reference (a pointer). So, for example if you want to pass a simNode object to a function so it can change the object you need to pass a pointer to the object - thus the declaration (signature) of the function would be
        returnType functionName (simNode * theNode);
    
    or
    
        returnType functionName (simNode *);
    
    Note: It is standard practice to just list the type of each parameter in the declaration; it isn't necessary at that point to have a formal parameter name.

    The call of the function would need to send a pointer to a simNode as the actual parameter. Two examples are:

         simNode * nodePtr;
         simNode actualNode;
    
         ...
         ... functionName(nodePtr) ....
         ...
         ... functionName(&actualNode)
    
    The & operator gives the address of an object so &actualNode is a pointer to (or reference for) the object actualNode.

    Inheritance

    Java and C++ both support inheritance - the ability to derive a new class from another class (usually called the base class). The new class inherits the data and methods of the base class. In the queuing system program, the base class is the System class which contains data and methods common to simulating any queuing system using the next event approach. Any specific system can be derived from this class. In particular the mm1System is a derived class. The syntax for this is as follows:
      Java:  public mm1System extends System
    
      C++:   public mm1System: public System
    
    In C++ the base class often has virtual functions that are not defined in the base class. Each derived class must define the functions. See the functions updateState and continueSim in the System declaration.

    Enumerated Types

    C++ provides the enum statement to define a collection of related symbolic constants and a typedef statement to let the programmer define his/her own types. The mm1System class uses these statements to define a type called eventType with the symbolic constants ARRIVAL and DEPARTURE and a type called statusType with the symbolic constants IDLE and BUSY. The list of constants can be as long as you wish. When you use the enum, C++ associates an integer value with each constant (0 with the first one in the list, 1 with the next, and so on). Using the symbolic constants is of course preferable to using the integers since the program is easier to read and modify.

    Makefiles, Compiling, and Linking

    Generally, you need to compile each class in your program, and then link them together (the linking process also links the library functions in). The result of each compile command is an object file which the compiler puts in a file with a .o file extension (and the same name as the file you are compiling). The compiler we use is g++. For example, the following command
       g++ -c myClass.cc
    
    compiles the class defined in the file myClass.cc and puts the object code in myClass.o. After compiling all your files you can then link of the object files together and create an executable file as follows:
       g++ -o executableName mainProg.o myClass.o
    
    To run the program type
       ./executableName
    
    When a program uses lots of files it is easier to "automate" this process using a makefile. Each line of the makefile contains the commands one needs and information about which files each command depends on (so that if you want to compile the main program all other files that it depends on are checked to see if they need to be recompiled). Each line of the makefile has the following syntax:
       target:    a list of dependencies
                  the command
    
    (TABs must be used to space over to the command). The target is generally the file created by the command. Then to execute the command all you need to do is type
            make target
    
    Study the makefile for the mm1 queuing system. Note that there is a line for compiling each file in the program plus one that links all together.