Introduction to C++: Elementary Concepts

Java and C++ are very similar

Java and C++ both share a common heritage in the C language. C++ is an object-oriented extension of the C language, while Java was designed as a simplified successor for C++.

All of these languages share the same core language features, including the following

  1. Basic data types are largely the same: int, char, float, long, double. The only significant difference here is that in Java the char data type is a 16 bit data type, while the C++ char is an 8 bit type.
  2. Both languages have a boolean data type for storing true/false values. In Java the type is called a boolean, in C++ a bool.
  3. Syntax for assignment, initialization of primitive types, and arithmetic are identical.
  4. All decision structures, including if...else, while, for, and switch are identical. (Although C++ does not have a for-each style loop.)

Syntax for functions, including declaring return types and parameter types and the use of the return statement largely carries over from Java to C++. C++ has some additional features, as we shall see below.

A first program in C++

The program shown here reads two integers that the user has typed in from the console, adds the numbers and prints the result back to the console.

#include <iostream>

int main (int argc, const char * argv[])
{
  int a,b,c;
    
  std::cout << "Enter two integers: ";
  std::cin >> a >> b;
    
  c = a + b;
    
  std::cout << "The sum of " << a << " and "
            << b << " is " << c << std::endl;

  return 0;
}

The structure of C++ programs

The first major syntactical difference between Java and C++ is that in Java everything appears within the context of a class. C++ is an object-oriented language like Java, but not everything in C++ is required to be object oriented.

In Java, the main method appears as a static method in a particular class. In C the main function is always a free function that appears outside the context of any class. Throughout this entire first set of notes I am only going to be working with free functions. A later lecture will introduce classes in C++.

Include statements

The C++ equivalent of the Java import statement is the #include statement. Includes come in two different varieties. System includes are denoted by the use of angle brackets around the included file name and are used to import declarations related to the C++ standard library and other resources. User includes are denoted by quote marks around the included file name are used to import declarations stored in header files that you have created as part of your project.

#include <iostream> // Used to import C++ input/output streams
#include <fstream> // Used to import C++ file streams
#include <string> // Used to import the string class
#include "Example.h" // Used to import a header file you have written

The first few examples we are going to see will only make use of system includes. When we look at our first example of a multiple source file program in C++, I will revisit the use of user includes.

Namespaces

Java uses the package mechanism to reduce the potential for name conflicts. All classes are required to belong to a package. Two classes with the same name can coexist, as long as the two classes belong to separate packages.

C++ namespaces are the rough equivalents of Java packages and serve the same purpose. To create a namespace and put some items in the namespace you use a namespace declaration.

namespace MyStuff {
  // Declare classes, functions, and variables in here
  }

Since we are mostly going to be writing small programs in this course we won't need to create namespaces frequently.

Items that are not explicitly declared in a namespace land in the global namespace.

If you want to use something that was declared inside a namespace you have to do one of two things. Your first option is to use the qualified name which includes the name of the namespace. For example, if you want to use the string class that comes with the C++ standard library you have to use its fully qualified name.

std::string str = "Some text";

In the example above I used some objects that I imported from the std namespace. You can easily distinguish these by their std:: prefixes.

Your second option is to import an item from a namespace with a using declaration.

using std::string; // Import string from the std namespace
string str = "Some text"; // Now we can use string without std::

This kind of using declaration typically appears at the top of a source file, right after the #include statements.

A third option is to import everything from a particular namespace:

using namespace std; // Imports names from the entire std space

This option is something of a blunt instrument, in that it pulls everything from that other namespace into the current namespace. If you are not careful, this can lead to name conflicts. For example, the std namespace contains a number of common utility functions, such as min(). If you try to declare your own function with that name you may then get a compiler error saying that the function is already declared.

A somewhat safer way to use the using declaration above is to limit its scope by using it only where you need it. For example, here is a version of our first sample program that follows this strategy to limit the use of the std namespace to only two functions where we need to input or output.

#include <iostream>

void inputNumbers(int& one,int& two) {
  using namespace std;
  
  cout << "Enter two integers: ";
  cin >> one >> two;
}

void outputNumbers(int one,int two,int three) {
  using namespace std;
  
  cout << "The sum of " << one << " and "
            << two << " is " << three << endl;
}

int main (int argc, const char * argv[])
{
  int a,b,c;
    
  inputNumbers(a,b);
    
  c = a + b;
    
  outputNumbers(a,b,c);

  return 0;
}

Note that since I did not use a namespace declaration for this example, all three of the functions defined here are considered to be members of the global namespace. For example, the qualified name of the first function above is ::inputNumbers. Note that if one function in a given namespace wants to call another function in that same namespace it does not have to use a qualified name for the function it is calling.

cin, cout, and file streams

Java was designed with the expectation that most programs written in the Java language would use a graphical user interface. Indeed, GUI applications are much easier to write in Java than in C++. The expectation in Java was that relatively few applications would use text input and output through a console. In C++ the expectation is that programmers will frequently write applications that use text input and output in a console window. Consequently, C++ makes it much easier to write console applications.

The basic mechanism for doing text input and output is the iostreams facility. To use this facility, you place the include statement

#include <iostream>

at the top of any source file where you want to do text input and/or output.

To do text output, use the std::cout object in combination with the stream injection operator <<. The endl output manipulator causes a line break in the output, so that the next thing that gets output appears on the following line in the output.

int x = 5;
float y = 6.3;
std::cout << "x is " << x << " and y is " << y << std::endl;

Compare this with the Java equivalent:

System.out.println("x is " + x + " and y is " + y);

To do text input from the console, use the std::cin object in combination with the stream extraction operator >>. Here is a typical example.

int s;
float t;
std::cout << "Enter an integer and a float: ";
std::cin >> s >> t;

Upon encountering a statement involving cin program execution will pause and await appropriate input from the user. Once the user has typed in the data requested by the cin statement execution will continue.

Input and output from text files uses a similar syntax. To use the file streams facility, use the include statement

#include <fstream>

Here is an example showing how to open and use a file stream for output to a text file.

std::ofstream out; // Create an output file stream object
out.open("numbers.txt"); // Associate the stream with a file
out << "Hello, world!" << std::endl;
out.close();

Using a text file for input is similar.

int x, y;
std::ifstream in; // Input file stream object
in.open("data.txt"); // Open the data file
in >> x >> y; // Read two ints
in.close();

Arrays in C++

Arrays in C++ come in two varieties: automatic arrays and dynamic arrays. An automatic array is fixed in size and is created with a declaration like

int A[100];

A dynamic array is allocated with new. Here is the syntax used to allocate a dynamic array.

int *B = new int[100];

The array variable in this case is an example of a pointer variable. A pointer variable contains information about where other things are located. In this case, the pointer variable B will contain the location information for the array we created with new: the pointer points to the first element in the array.

The primary advantage that dynamic arrays offer is that they allow you to specify the size of the array at run-time. Automatic arrays must have sizes that are determined at compile time.

cout << "How many numbers do you need to store? ";
int n;
cin >> n;

int A[n]; // Illegal - automatic arrays must have sizes 
          // fixed at compile time.
int *B = new int[n]; // Legal, and preferred.

Despite the fact that these arrays are set up in different ways they both work exactly the same. In both cases you can use the bracket notation to access individual elements of the array.

A[0] = 2; // Standard array notation
B[0] = 2; // Same notation works with a dynamic array

You can pass both of these arrays to functions. For example, here is a function that will print the contents of an array of integers to cout.

void printArray(int X[],int N)
{
  for(int k = 0;k < N;k++)
    std::cout << X[k] << std::endl;
}

Note that since C++ does not allow you to ask an array its length via the X.length syntax, we have to explicitly pass the size of the array as a parameter to the function. To call this function with the array B we created above we would do

printArray(B,n);

When you are done using an array that was created with new, you will have to destroy it with the delete[] operator:

delete[] B;