Red Hat Linux: Programming In C++What Is C++? C++ is an object-oriented extension to the C programming language. It was
developed at Bell Labs in the early 1980s and is quickly becoming the language
of choice in the computer industry. Dozens of C++ compilers are available on the
market today. The most common of these for PC-based systems are Borland C++,
Microsoft's Visual C++, Symantec C++, and Watcom C++. These compilers can
compile MS-DOS, MS Windows, OS/2, and Windows NT programs. In addition to the
number of C++ compilers that are available on DOS-based machines, a great number
are also based on other hardware architectures. Most UNIX systems have C++ compilers available from the system vendor. Linux
also comes with a C++ compiler. This is the GNU C++ compiler. The GNU C++
compiler is very closely related to the GNU C compiler (GCC). In fact, since
Release 2.0 of GCC, the GNU C++ compiler has been integrated with GCC. Previous
to Release 2.0 of GCC, the GNU C++ compiler was a separate program known as g++.
One of the major enhancements in Release 2.0 of GCC was merging these two
compilers. GCC now incorporates a C compiler, a C++ compiler, and an
Objective C compiler, although you will still find the g++ executable on your
system. Why C++? C++ and object-oriented programming (OOP) did not just
happen. There were many fundamental reasons for the shift from structured
programming to OOP. In the early days of computer programming, back when PDP-8s
still roamed the earth in great numbers, there was a shift from machine language
coding to assembler language coding. This was done because the computers of the
day were a little more powerful than their predecessors. Programmers wanted to
make their lives easier by moving some of the burden of programming onto the
computer. As the years went by and computers got even more powerful, new, higher-level
languages started to appear. Examples of these languages are FORTRAN, COBOL,
Pascal, and C. With these languages came a programming methodology known as
structured programming. Structured programming helped to simplify the systems
being designed by enabling programmers to break the problem into small pieces
and then implement these pieces as functions or procedures in whatever language
was being used. The structured programming approach worked well for small to medium-sized
software applications, but it started to fall apart as systems reached a certain
size. OOP tried to solve some of the problems that structured programming was
causing. It did this by extending some of the structured programming concepts
and by introducing some of its own. The main concepts that OOP focuses on are the following:
Data Encapsulation In structured programming, problems often arose where there was a data
structure that was common to several different pieces of code. One piece of code
could access that data without the other piece of code being aware that anything
was happening. Data encapsulation is a process of grouping common data together, storing it
into a data type, and providing a consistent interface to that data. This
ensures that no one can access that data without going through the user
interface that has been defined for that data. The biggest benefit that this kind of mechanism provides is that it protects
code outside the code that is directly managing this data from being affected if
the structure of the data changes. This greatly reduces the complexity of large
software systems. C++ implements data encapsulation through the use of classes. Inheritance Inheritance is a form of code reuse in which you can inherit or use the data
and behavior of other pieces of code. Inheritance is typically used only when a
piece of software logically has many of the same characteristics as another
piece of software, such as when one object is a specialization of another
object. Inheritance is implemented in C++ by allowing objects to be subclassed by
other objects. Polymorphism Polymorphism occurs when a language allows you to define functions that
perform different operations on objects depending on their type. The true power
of this lies in the fact that you can send a message to a base class and that
message can be passed down to each of its subclasses and mean different things
to each of them. Polymorphism is implemented in C++ using virtual functions. Classes of Objects and Methods In C++, classes can be thought of as C structures that contain not only the
data fields but also operations that can be performed on those data fields. A
simple example of this concept is a geometric shape. A geometric shape can be
many things, such as a rectangle, a triangle, or a circle. All geometric shapes
have certain attributes in common, including area and volume. You could define a
structure in C called shape in the following way: struct shape{ If you added some common behavior to this structure, you would have the
equivalent of a C++ class. This would be written as follows: class shape {
You have now defined a C++ class. The calc_area and calc_volume items are
known as methods of the class (instead of functions, as in C). If you were to
define a variable that was of type shape as you would have created a circle object. An object is an instance of a class,
or a variable that is defined to be of the type of a class. GCC Options This section describes some of the GCC options that are most commonly used. I
will first talk about some of the options that can be used both with C and C++
and then talk about C++ specific options. Any of the compiler options that you
use with C you can use with C++ as well, but some of them may not make any sense
in the context of a C++ compile. If you specify options that don't make sense,
the compiler just ignores them.
A great number of compiler options can be passed to GCC. Many of these
options are specific to a certain hardware platform or are for making
fine-tuning adjustments to the code that is produced. You will probably never
use any of these kinds of options. The options covered in this chapter are those
that you will use on a regular basis. Many of the GCC options consist of more than one character. For this reason,
you must specify each option with its own hyphen and not group options after a
single hyphen as you can with most Linux commands. When you compile a program using GCC without any command-line options, it
creates an executable file (assuming that the compile was successful) and calls
it a.out. For example, the following command would create a file named a.out in
the current directory: gcc test.C To specify a name other than a.out for the executable file, you can use the
-o compiler option. For example, to compile a C++ program file named count.C
(the capital C is used to show C++ code, as opposed to a small c for C code)
into an executable file named count, you would type the following command:
Other compiler options allow you to specify how far you want the compile to
proceed. The -c option tells GCC to compile the code into object code and skip
the assembly and linking stages of the compile. This option is used quite often
because it makes the compilation of multifile C++ programs faster and easier to
manage. Object code files created by GCC have an .o extension by default. The -S compiler option tells GCC to stop the compile after it has generated the assembler files for the C code. Assembler files generated by GCC have an .s extension by default. The -E option instructs the compiler to perform only the preprocessing compiler stage on the input files. When this option is used, the output from the preprocessor is sent to the standard output rather than being stored in a file. Debugging and Profiling Options GCC supports several debugging and profiling options. Of these options, the
two that you are most likely to use for C++ programs are the -gstabs+ option and
the -pg option. The -gstabs+ option tells GCC to produce stabs format debugging information
that the GNU debugger (gdb) can use to help you debug your program. For more
information on debugging your C++ programs, refer to the "Debugging C++
Applications" section later in this chapter. The -pg option tells GCC to add extra code to your program that will, when
executed, generate profile information that can be used by the gprof program to
display timing information about your program. GCC C++ Specific Options The GCC options that control how a C++ program is compiled are listed in
Table 28.1.
Debugging C++ Applications A very important part of developing C++ programs is being able to debug
them efficiently. The GNU debug application can be used to debug C++
applications. This section describes some of the differences between debugging C
applications and debugging C++ applications.
From the programmer's perspective, you have more details to be aware of when
debugging C++ code than when you are debugging C code. This is because of the
C++ features such as virtual functions and exception handling. gdb has added
features to support debugging both of these C++ specific features. Debugging Virtual Functions As described in the "Polymorphism" section of this chapter, virtual functions
are C++'s way of implementing polymorphism. This means that there may be more
than one function in a program with the same name. The only way to tell these
functions apart is by their signatures. The signature of a function is composed
of the types of all the arguments to the function. For example, a function with
the prototype has a signature of int,real. You can see how this could cause gdb a few problems. For example, if you had
defined a class that had a virtual function called calculate, and two objects
with different definitions for this function were created, how would you set a
breakpoint to trigger on this function? You set breakpoints in C by specifying
the function name as an argument to the gdb break command, as follows: This does not work in the case of a virtual function because the debugger
would not be able to tell which calculate you wanted the breakpoint to be set
on. gdb was extended in a few ways so that it could handle virtual functions.
The first way to solve the problem is to enter the function name by specifying
its prototype as well. This would be done in the following way: break 'calculate (float)' This would give gdb enough information to determine which function the
breakpoint was meant for. A second solution that gdb supports is using a
breakpoint menu. Breakpoint menus allow you to specify the function name of a
function. If there is more than one function definition for that function, it
gives you a menu of choices. The first choice in the menu is to abort the break
command. The second choice is to set a breakpoint on all the functions that the
break command matches. The remaining choices correspond to each function that
matches the break command. The following code shows an example of a breakpoint
menu: (gdb) break shape::calculate Debugging Exception Handlers Exceptions are errors that occur within your program. Exception handlers are
pieces of code that are written to handle errors and potential errors. For
example, if you were writing a C program and calling the malloc function to get
a block of memory, you would typically check malloc's return code to make sure
the memory allocation was successful. If C supported exception handling, you
could specify a function that would receive or catch exceptions, and the malloc
function would send or throw an exception to your function if one occurred. The gdb added two new commands to support C++ exception handling: the catch
command and the catch info command. The catch command is used to set a
breakpoint in active exception handlers. The syntax of this command is as
follows: exceptions is a list of the exceptions to catch. The catch info command is used to display all the active exception handlers.
Summary of gdb C++ Specific Commands In addition to the gdb commands that have been added to support some of the
new language features contained in C++, there are also some new set and show
options. These options are listed in Table 28.3.
GNU C++ Class Libraries GNU C++ comes packaged with an extensive class library. A class library is a
reusable set of classes that can be used to perform a specified set of
functions. Some typical examples of class libraries are class libraries that
handle database access, class libraries that handle graphical user interface
programming, and class libraries that implement data structures. Examples of graphical user interface class libraries include the Microsoft
Foundation Classes and Borland's Object Windows Library, both of which are class
libraries that are used for developing Windows applications. This section introduces several of the features that are offered by the GNU
C++ class library. Streams The GNU iostream library, called libio, implements GNU C++'s standard input
and output facilities. This library is similar to the I/O libraries that are
supplied by other C++ compilers. The main parts of the iostream library are the
input, output, and error streams. These correspond to the standard input,
output, and error streams that are found in C and are called cin, cout, and cerr
respectively. The streams can be written to and read from using the << operator
for output and the >> operator for input. The following program uses the iostream library to perform its input and
output: #include <iostream.h> Strings The GNU string class extends GNU C++'s string manipulation capabilities. The
stringclass essentially replaces the character array definitions that existed in
C and all the stringfunctions that go along with the character arrays. The string class adds UNIX shell type string operators to the C++ language,
as well as a large number of additional operators. Table 28.4 lists many of the
operators that are available with the string class.
A number of other operators are available in the string class for performing
different types of string comparisons, concatenations, and substring extraction
and manipulation. Random Numbers Classes are provided in the GCC C++ class library that allow you to generate
several different kinds of random numbers. The classes used to generate these
numbers are the Random class and the RNG class. Data Collection The class library provides two different classes that perform data collection
and analysis functions. The two classes are SampleStatistic and SampleHistogram.
The SampleStatistic class provides a way of collecting samples and also provides
numerous statistical functions that can perform calculations on the collected
data. Some of the calculations that can be performed are mean, variance,
standard deviation, minimum, and maximum. The SampleHistogram class is derived from the SampleStatistic class and
supports the collection and display of samples in bucketed intervals. Linked Lists The GNU C++ library supports two kinds of linked lists: single linked lists,
implemented by the SLList class, and doubly linked lists, implemented by the
DLList class. Both of these types of lists support all the standard linked list
operations. A summary of the operations that these classes support is shown in
Table 28.5.
Doubly linked lists also support the operations listed in Table 28.6. Table 28.6. Doubly linked list operators.
Plex Classes Plex classes are classes that behave like arrays but are much more powerful.
Plex classes have the following properties:
Four different types of Plexes are defined: the FPlex, the XPlex, the RPlex,
and the MPlex. The FPlex is a Plex that can grow or shrink only within declared
bounds. An XPlex can dynamically grow in any direction without any restrictions.
An RPlex is almost identical to an XPlex, but it has better indexing
capabilities. Finally, the MPlex is the same as an RPlex except that it allows
elements to be logically deleted and restored. Table 28.7 lists some of the operations that are valid on all four of the
Plexes.
Plexes are a very useful class on which many of the other classes in the GNU
C++ class library are based. Some of the Stack, Queue, and Linked list types are
built on top of the Plex class. Stacks The stacks class implements the standard version of a last-in-first-out
(LIFO) stack. Three different implementations of stacks are offered by the GNU
C++ class library: the VStack, the XPStack, and the SLStack. The VStack is a
fixed-size stack, meaning that you must specify an upper bound on the size of
the stack when you first create it. The XPStack and the SLStack are both
dynamically sized stacks that are implemented in a slightly different way. Table 28.8 lists the operations that can be performed on the Stack classes.
Queues The Queue class implements
a standard version of a first-in-first-out (FIFO) queue. Three different kinds
of queue are provided by the GNU C++ class library: the VQueue, the XPQueue, and
the SLQueue. The VQueue is a fixed-size queue, so you must specify an upper
bound on the size of this kind of queue when you first create it. The XPQueue
and the SLQueue are both dynamically sized queues, so no upper bound is
required. The operations supported by the Queue classes are listed in Table
28.9.
In addition to the normal kind of queue that is discussed in this section,
the GNU C++ class library also supports double-ended queues and priority queues.
Both of these types of queues have similar behavior to the regular queue. The
double-ended queue adds operators for returning a pointer to the rear of the
queue and deleting elements from the rear of the queue. The priority queues are
arranged so that a user has fast access to the least element in the queue. They
support additional operators that allow for searching for elements in the queue.
Sets The Set class is used to store groups of information. The only restriction on
this information is that no duplicate elements are allowed. The class library
supports several different implementations of sets. All of the implementations
support the same operators. These operators are shown in Table 28.10.
The class library contains another class that is similar to sets. This class
is known as the bag. A bag is a group of elements that can be in any order (just
as is the case with sets) but in which there can also be duplicates. Bags use
all the operators that sets use except for the ==, !=, |=, <=, |=, -=, and &=
operators. In addition, bags add two new operators for dealing with elements
that are in the bag more than once. These new operators are shown in Table
28.11.
Many other classes available in the GNU C++ class library provide functions other than those listed here. In addition to what comes with the compiler, many other freely available class libraries can be useful as well. |