Before we start to look in detail at C++, you might find it interesting to read the following two paragraphs from the Microsoft web page https://learn.microsoft.com/en-us/cpp/cpp/welcome-back-to-cpp-modern-cpp:
Since its creation, C++ has become one of the most widely used programming languages in the world. Well-written C++ programs are fast and efficient. The language is more flexible than other languages: It can work at the highest levels of abstraction, and down at the level of the silicon. C++ supplies highly optimized standard libraries. It enables access to low-level hardware features, to maximize speed and minimize memory requirements. C++ can create almost any kind of program: Games, device drivers, HPC, cloud, desktop, embedded, and mobile apps, and much more. Even libraries and compilers for other programming languages get written in C++.
One of the original requirements for C++ was backward compatibility with the C language. As a result, C++ has always permitted C-style programming, with raw pointers, arrays, null-terminated character strings, and other features. They may enable great performance, but can also spawn bugs and complexity. The evolution of C++ has emphasized features that greatly reduce the need to use C-style idioms. The old C-programming facilities are still there when you need them. However, in modern C++ code you should need them less and less. Modern C++ code is simpler, safer, more elegant, and still as fast as ever.
There are many similarities between Java and C++, but also enough
differences to make the transition in either direction potentially
frustrating and confusing. Here we list a number of "talking point"
categories that we need to explore in making our transition from Java
to C++. Those already familiar with C++ should take the opportunity for a brief review.
Some history and philosophy of C++
- Who is responsible for C++? Ans: Bjarne Stroustrup
- How long has C++ been around? Ans: Since the early 1980s.
- What were the design goals of C++? Ans: To be backward compatible
with C, to be as efficient as C where possible, and to provide the
object-oriented programming paradigm in addition to the legacy
procedural paradigm of C.
Can we get a "big picture" view of C++?
- What about "core language" vs. libraries? Ans: C++ consists of a relatively
small "core" language, and a very large collection of library facilities,
much like Java.
- What libraries are part of the C++ Standard? Ans: Its "standard"
library, which includes the legacy C libraries and the Standard Template
Library (STL).
- What libraries become part of the C++ standard over time? Ans:
As of the C++11 standard (approved in 2011), quite a
number of new features were added to both the language itself
and its libraries. Many of the new library features were taken/adapted
from the Boost library, an independently-developed, highly-regarded,
third-party library of C++ code and as time goes on more and more
of the facilities from that library will likely end up as part of
the standard. C++ generally gets a new standard every three years,
so C++14, C++17, C++20 and so on.
A peek at the usual "Hello, world!" program in C++
[See hello1.cpp,
hello2.cpp and
hello3.cpp.]
- What kinds of comments does C++ have? Ans: It has
//
comments and /* ... */
comments, as in Java. Analogous to
javadoc comments /** ... */
, it also has these
/** ... */
comments, and the /**< ... */
variation, but in C++ these are "doxygen" comments, not Javadoc
comments.
- Do we always need a class like we do in Java? Ans: No
- Do we have to be careful what we call the file that contains our
program? Ans: No. We can call our file whatever we like, since it does
not have to match a class name as in Java, but we should strive to
give our files meaningful names nonetheless.
- Is there a main function like there is in Java? Ans: Yes
- How do we get access to things that we want to use but that are
not part of the "core language"? Ans: By using the
#include
"compiler directive", which is analogous to, but not the same as, the
Java "import" mechanism.
- How do we display some simple text on the standard output? Ans:
By using the
cout
"stream object" and the "insertion
operator" <<
like this:
cout << stuff_to_output;
cout << stuff_to_output << endl;
The second line above uses the endl
"manipulator" to
terminate the output line and "flush the output buffer".
What are the simple data types and operators in C++?
- Six are the same as in Java: short, int,
long, float, double and char.
However, their sizes are implementation-dependent, not fixed across
all platforms as in Java.
- bool in C++ is just like boolean in Java.
However, in C++ a value of 0 (zero) is interpreted as false,
and any non-zero value is interpreted as true, which is not
the case in Java.
- C++ does not have the byte data type found in Java.
- But, C++ does have other simple data types which you need not
worry about on a first pass.
- Casting values of simple types can use the same syntax as in
Java, and you can expect pretty much the same results. [Note, though,
that Java is somewhat more type-safe in this regard than C++. For
example, in C++ you can cast a bool to an int,
something you cannot do in Java.]
- Testing for equality and inequality of simple values is done with
the == and != operators, and C++ users (like Java
users) are also advised not to test real number values for
equality.
- Literal values like 123 are assumed to be values of type
int, while literal values of the form 123.45 are assumed to
be values of type double.
- The usual arithmetic and conditional expressions are pretty much
the same in C++ as they are in Java, and the common operators have
the same precedence in both languages.
- Operators can be overloaded in C++, unlike in Java where they
cannot be overloaded. Functions, on the other hand, can be overloaded
in both languages.
How are strings handled in C++?
Strings in C++ are a potential source of difficulty for programmers
(especially beginning programmers), largely because there are two
distinct types of strings, and one has to be careful to use the right
one in certain situations:
- The first is the so-called C-string, a legacy item from the C
programming language. A C-string is just an array of type
char with the special property that it contains a null
character ('\0') which indicates the end of the data
characters in the array. (That is, the array of characters may or may
not be full of actual data, and the string-handling functions from
the legacy C-language that deal with C-strings need this character to
tell them where the end of the data is located.) [Check out the program misc/array_out.cpp in this context.]
- The second is a full-fledged object of the string class,
a class from the Standard Library. Since these are class objects,
they have an interface containing (a large number of) member
functions that allow programmers to manipulate them in many useful
ways.
When dealing with strings in C++, keep in mind the following:
- You need to know when you have to use a C-string rather
than a C++ string object. The most obvious and common case is command-line
parameters, which are C-strings.
- When you don't have to use a C-string it is (probably)
better to use a C++ string object.
How is (text) I/O handled in C++?
- C++ makes use of "stream objects" to deal with input and output,
and in particular with text I/O (as well as binary I/O, which we may
or may not encounter later).
-
The standard input (keyboard) object is cin, which permits
input from the keyboard via statements like this:
cin >> someVariable;
cin >> variable1 >> variable2;
The way this works (by default) is that (in the first line above,
for example) cin first ignores any leading whitespace,
then reads as many characters as make sense as a valid value of the
data type of someVariable, finally stopping at the first
character that does not make sense as part of that value,
and leaving that character in the input stream.
-
The standard output (screen) object is cout, which permits
output to the screen via statements like this:
cout << someVariable;
cout << variable1 << variable2;
cout << setw(10) << someVariable << endl;
The way this works (by default) is that (in the first line above,
for example) cout (by default) simply sends the characters
representing the value to the screen, with no leading or trailing
spaces. Exactly what characters are sent depend, of course, on both
the data type of the value, and the actual value of that type. The
default behavior may be modified with the use of
manipulators, like setw(10) and endl
shown in the last line above. The setw(10) manipulator
causes the next value output to be placed right-justified in 10
spaces, while the endl manipulator causes the "output
buffer" to be "flushed" and the current output line to be
terminated, so that the next value output will appear on a new
line.
-
Input of text information from a textfile to a variable in memory
works in a manner completely analogous to the behavior of
cin, once a connection has been established between a file
variable (also a stream object), and a physical file on disk. Thus
input of a value from a textfile on disk to a variable in memory
called someVariable would take place like this:
ifstream inFile(fileName_as_a_string);
inFile >> someVariable;
-
Output of text information from a variable in memory to a textfile
works in a manner completely analogous to the behavior of
cout, once a connection has been established between a
file variable (also a stream object), and a physical file on disk.
Thus output of a value from a variable called someVariable to a
textfile on disk would take place like this:
ofstream outFile(fileName_as_a_string);
outFile << someVariable;
- One has to distinguish between the input of a string delimited
by whitespace, and the input of a complete line of text, when reading
string data. The former is read with the >> operator in the
same way as any other data, as described above. But ... when reading
a full line of data into a C++ string variable (from the keyboard,
for example) you should use the getline function in a statement like
getline(cin, string_variable);
and an analogous statement if reading from an input file, say inFile,
rather than from standard input.
What are the C++ "flow of control" constructs?
- For decision making we have the if-statement, the
if...else-statement, and the switch-statement.
These have the same syntax and behave essentially the same way in C++
as in Java.
- For looping there are three statements: the for-loop,
the while-loop, and the do...while-loop. These too
have the same syntax and behave essentially the same way in C++ as in
Java.
- Because in C++ any non-zero value is interpreted as true
and 0 is interpreted as false, you will often see
expressions that do not have type bool used as conditions in
flow-of-control constructs.
- C++ also has the break and continue statements,
whose "everyday" uses are the same in both languages.
- C++ has a "comma operator", which is much more flexible than in
Java.
- Both Java and C++ now have a "range for-loop" (also called an "enhanced" for-loop or a "for-each loop"), which simplifies the
processing of an entire "container".
How are arrays handled in C++?
- C++ arrays are not objects like arrays are in Java, so they do
not know their own length, for example, and have no automatic
out-of-bounds checking. Thus the programmer is responsible for making
sure array indices are valid.
-
C++ arrays are declared like this:
int a[10]; //An integer array of size 10
And if you want to initialize the array at the same time, you can
do it like this:
int a[10] = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};
int a[10] = { 0 }; //initializes the array to all 0 values
- C++ arrays are zero-based, just like Java arrays.
-
Here is the definition (declaration plus initialization) of a
two-dimensional array of integers having two rows and three
columns:
int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
- Nowadays STL vectors are often used (and recommended for use) in
many situations where formerly simple arrays would have been used
(because there was no alternative).
What about C++ functions?
- C++ has "free" functions that belong to no class, as well as
member functions of classes.
- The general syntax for a function is the same in C++ as it is in
Java.
- In C++ the default parameter-passing mechanism is "call by
value", just as it is in Java. However, C++ also provides "call by
reference", in which an "alias" for a value outside the function is
given to the function to manipulate.
- Class methods (member functions) do not behave polymorphically by
default in the context of inheritance the way they do in Java, but
they can be made to do so by making the "virtual" functions.
- In C++ functions can be overloaded, just as they can in Java.
[Note that in C++, unlike in Java, operators can also be
overloaded.]
- C++ allows a function parameter to have a "default value".
What more can we learn about C++ from a searching and sorting
program?
[See search_and_sort_demo.cpp.
To run this program you will also need the file
search_and_sort_demo.txt.]
Study this program to see C++ in action actually doing something.
The program illustrates many of the features we have mentioned above.
Note in particular the overall structure and organization of the code,
especially the comments (both doxygen-style and "ordinary" C++
comments), the order of includes, constant and type
definitions, function prototypes, the main function, and function
definitions corresponding to the function prototypes.
What about C++ classes?
This is a subject we will need to explore at some length as the
course progresses. In the meantime, let's highlight a few similarities
and differences.
-
A C++ class is very similar in overall appearance to a Java class,
but
- In C++ we do not need a class to have a program, since we can
have "free" functions (functions that do not belong to any
class).
- In C++ there is no required relationship between class names
and names of files that contain them.
- In C++ a class definition must be terminated by a semi-colon
(;).
- A typical class in C++ will have a public: section for
methods (member functions) and a private: section for data
(data members). Note the colon (:) following each access keyword
(public or private), and note too that every item
following either public: or private: has the
indicated access level until another such "section" of code with the
other access-level indicator is encountered.
- The default access level in a C++ class is private.
- C++ permits multiple class inheritance, while Java only allows
single class inheritance.
- In Java all methods are fully defined in the class to which they
belong, while in C++ class methods are often (though not always)
separated into function prototypes (a function header followed by a
semi-colon instead of a body), and functions definitions, and placed
in different files. One file (the one containing the prototypes and
probably other information as well) is called the specification
file for the class, while the file containing the member
function definitions is called the class implementation
file. This structure may allow classes to be separately compiled
and used with different client programs, in addition to helping with
code maintenance.
-
The following statement means something quite different in C++ from
what it means in Java:
MyClass myObject;
In C++ the default constructor for MyClass will be
invoked, and the constructed object will itself be stored in
myObject. In Java, on the other hand, myObject
can only hold a reference to an object of type MyClass,
and not an actual object of that type.
- In both C++ and Java one has to be very careful when testing for
equality, particularly when objects are involved, and one should
always think twice when tempted to use the double equals operator
(==) for testing equality of anything but values of simple (and
non-floating point) types.
- Both C++ and Java will define a constructor for your class if you
do not define any yourself.
- If a C++ class involves dynamic data, it must have a
destructor, a copy constructor, and an
overloaded assignment operator. These are sometimes referred
to as "the big three", and they are a new concept for programmers
coming to C++ from Java. Java does not need destructors because it
has automatic garbage collection, and does not need the other two
because it does not have variables that can hold objects.
What can we learn about C++ classes from a Time class?
[See
time.h and
time.cpp and
test_time.cpp.]
This class illustrates quite a bit about C++ classes in general.
You will see a single constructor that actually gives you several
constructors from the one definition, via default parameters (a very
convenient feature available in C++ but not in Java). You will see
"friend functions". You will see overloaded operators. You will see
C++ "getters" and "setters". You will see how a class is (typically)
separated into two files, the specification file and the
implementation file. You will see how the specification
file is protected from "multiple inclusions". And you will see
quite a bit of doxygen-style documentation.
What about pointers, dynamic data and the free store?
This is a large and potentially difficult topic for programmers
coming from Java, since much is possible in C++ for which Java does not
have any comparable facilities. We will study this C++ material in some
detail as the course progresses. In the meantime, let's give a few
highlights.
- Both C++ and Java allow the programmer to obtain dynamic storage
from the "free store" (also called the "heap") via the new
operator.
- Java has automatic "garbage collection", while in C++ returning
dynamic storage to the free store when it is no longer needed is the
programmer's responsibility.
-
Here is some equivalent code for C++ and Java. The following C++
code declares a pointer to a class object, creates an object of the
class type using the default constructor, and then causes the
method named doIt of the class to be called on that object:
MyClass* myObjectPtr;
myObjectPtr = new MyClass();
myObjectPtr->doIt();
The equivalent code in Java looks like this:
MyClass myObject;
myObject = new MyClass();
myObject.doIt();
In both of the above cases, the actual object is dynamically
created on the heap. The C++ code shown below, in which an object
is (non-dynamically) created on the stack (not the heap), and then
object itself is used to call the doIt() method, has no counterpart
in Java:
MyClass myObject;
myObject.doIt();
- C++ pointers can point at many different things (not just
objects), including values of simple types and also at arrays, which
turns out to be especially useful.
What else do we need to know?
- Many keywords in C++ are the same as those in Java, but there are
several that differ as well (
bool
vs. boolean
,
const
vs. final
).
- C++ and Java share the same multi-line comments and single-line
comments, as well as documentation comments, but the tools used to
generate the documentation differ (doxygen for C++,
javadoc for Java).
- Coding style in C++ will be very familiar to Java programmers,
but of course there are a few differences with which you will need to
become familiar.
- Scope is a major topic in any language. The concept of block
scope is similar in both languages.
- Exceptions are somewhat analogous in the two languages, though
they are much more an integral part of the language in Java than in
C++.
- The keyword static has several different meanings in C++
for the different contexts in which you might find it.
- The keyword const in C++ is analogous to final
in Java, and it has several different uses, just like
final
in Java.
- The keyword typedef permits us to give our own name to a
previously existing type, which can help to condense our code and
serve as an aid to readability.
- The struct and the union are legacy data structures
from the C language and may be regarded as special "old-fashioned"
forms of the class data type that still have their uses.
- In C++ enumerated types are very simple, integer-based types, not
classes like they are in the latest version of Java.
- The sizeof operator can be very useful for determining
and using the size of a data value or data type. This operator is not
available in Java, and the
instanceof
operator from Java
is not available in C++.
- The keyword
auto
in C++ has for a long time not been
used, because the situation for which it would "normally" be used was
the default in any case. This has allowed this keyword to be given
a whole new meaning in the new C++11 standard: If the keyword
auto is used as the type when you declare a variable, and you
initialized the variable at the same time, C++ can now infer the
type of the variable from the value used to initialize it.