Linux 版 (精华区)
发信人: netiscpu (说不如做), 信区: Linux
标 题: Linux Programming in C++ (Chapter 28)
发信站: 紫 丁 香 (Thu Jul 23 09:08:19 1998), 转信
o What Is C++?
# Why C++?
@ Data Encapsulation
@ Inheritance
@ Polymorphism
# Classes of Objects and Methods
# GCC Options
# Debugging and Profiling Options
# GCC C++ Specific Options
o Debugging C++ Applications
# Debugging Virtual Functions
# Debugging Exception Handlers
# Summary of gdb C++ Specific Commands
o GNU C++ Class Libraries
# Streams
# Strings
# Random Numbers
# Data Collection
# Linked Lists
# Plex Classes
# Stacks
# Queues
# Sets
o Summary
_________________________________________________________________
28
Programming in C++
Chapter 27, "Programming in C," introduced you to the C programming
environment and C programming tools that come with Linux. This chapter
describes the same kinds of information for C++. This chapter covers
the following topics:
* What C++ is
* Why to use C++
* The GNU C++ compiler
* Debugging C++ applications
In addition to these topics, this chapter also looks at some of the
C++ programming tools and class libraries that are included on the
Linux CD.
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
* Inheritance
* Polymorphism
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{
float area;
float volume;
}
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 {
public:
float area;
float volume;
float calc_area();
float calc_volume():
};
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
shape circle;
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.
______________________________________________________________
NOTE: When you are compiling C++ programs, it is easiest to use the
g++ script. This sets all the default C++ options so you don't have
to.
______________________________________________________________
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:
gcc -o count count.C
______________________________________________________________
NOTE: When you are using the -o option, the executable filename
must occur directly after the -o on the command line.
______________________________________________________________
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. For
more information on gprof, refer to the "gprof" section in Chapter 27.
GCC C++ Specific Options
The GCC options that control how a C++ program is compiled are listed
in Table 28.1.
Table 28.1. GCC options.
Option Meaning
-fall-virtual Treats all possible member functions as virtual. This
applies to all functions except for constructor functions and new or
deleted member functions.
-fdollars-in-identifiers Accepts $ in identifiers. You can also
prohibit the use of $ in identifiers by using the
-fno-dollars-in-identifiers option.
-felide-constructors Tells the compiler to leave out constructors
whenever possible.
-fenum-int-equiv Permits implicit conversion of int to enumeration
types.
-fexternal-templates Produces smaller code for template declarations.
This is done by having the compiler generate only a single copy of
each template function where it is defined.
-fmemoize-lookups Uses heuristics to compile faster. These heuristics
are not enabled by default because they are effective only for certain
input files.
-fno-strict-prototype Treats a function declaration with no arguments
the same way that C would treat it. This means that the compiler
treats a function prototype that has no arguments as a function that
will accept an unknown number of arguments.
-fnonnull-objects Assumes that objects reached through references are
not null.
-fsave-memoized Same as -fmemorize-lookups.
-fthis-is-variable Permits assignment to "this."
-nostdinc++ Does not search for header files in the standard
directories specific to C++.
-traditional This option has the same effect as -fthis-is-variable,
but also attempts to support some aspects of traditional C compilers.
-fno-default-inline Does not assume that functions defined within a
class scope are inline functions.
-Wenum-clash Warns about conversion between different enumeration
types.
-Woverloaded-virtual Warns when derived class function declaration may
be an error in defining a virtual function. When you define a virtual
function in a derived class, it must have the same signature as the
function in the base class. This option tells the compiler to warn you
if you have defined a function that has the same name and a different
signature as a function that is defined in one of the base classes.
-Wtemplate-debugging If you are using templates, this option warns you
if debugging is not yet available.
-gstabs+ Tells the compiler to generate debugging information in stabs
format, using GNU extensions understood only by the GNU debugger. The
extra information produced by this option is necessary to ensure that
gdb handles C++ programs properly.
Debugging C++ Applications
A very important part of developing C++ programs is being able to
debug them efficiently. The GNU debug application that was introduced
in Chapter 27 can also be used to debug C++ applications. This section
describes some of the differences between debugging C applications and
debugging C++ applications.
The basic gdb commands that were introduced in Chapter 27 are listed
again for your convenience in Table 28.2.
Table 28.2. Basic gdb commands.
Command Description
file Loads the executable file that is to be debugged.
kill Terminates the program you are currently debugging.
list Lists sections of the source code used to generate the executable
file.
next Advances one line of source code in the current function, without
stepping into other functions.
step Advances one line of source code in the current function, and
does step into other functions.
run Executes the program that is currently being debugged.
quit Terminates gdb.
watch Enables you to examine the value of a program variable whenever
the value changes.
break Sets a breakpoint in the code; this causes the execution of the
program to be suspended whenever this point is reached.
make This command enables you to remake the executable program without
quitting gdb or using another window.
shell Enables you to execute UNIX shell commands without leaving gdb.
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
void func(int, real);
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:
(gdb) break calculate
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
[0] cancel
[1] all
[2] file: shapes.C: line number: 153
[3] file: shapes.C: line number: 207
[4] file: shapes.C: line number: 247
> 2 3
Breakpoint 1 at 0xb234: file shapes.C, line 153
Breakpoint 2 at 0xa435: file shapes.C, line 207
Multiple breakpoints were set
Use the "delete" command to delete unwanted breakpoints
(gdb)
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:
catch exceptions
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.
Table 28.3. gdb's C++ set and show options.
Command Description
set print demangle Prints C++ names in their source form rather than
in the encoded or mangled form that is passed to the assembler.
show print demangle Shows whether print demangle is on or off.
set demangle-style Sets the style of demangled output. The options are
auto, gnu, lucid, and arm.
show demangle-style Shows which demangle style is being used.
set print object When displaying a pointer to an object, identifies
the actual type of the object.
show print object Shows whether print object is turned on or off.
set print vtbl Pretty prints C++ virtual function tables.
show print vtbl Shows whether print vtbl is turned on or off.
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>
int main ()
{
char name[10];
cout << "Please enter your name.\n";
cin >> name;
cout << "Hello, " << name << ", how is it going?\n";
}
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.
Table 28.4. String class operators.
Operator Meaning
str1 == str2 Returns TRUE if str1 is equal to str2
str1 != str2 Returns TRUE if str1 is not equal to str2
str1 < str2 Returns TRUE if str1 is less than str2
str1 <= str2 Returns TRUE if str1 is less than or equal to str2
str1 > str2 Returns TRUE if str1 is greater than str2
str1 >= str2 Returns TRUE if str1 is greater than or equal to str2
compare(str1,str2) Compares str1 to str2 without considering the case
of the characters
str3 = str1 + str2 Stores the result of str1 concatenated with str2
into str3
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.
Table 28.5. List operators.
Operator Description
list.empty() Returns TRUE if list is empty
list.length() Returns the number of elements in list
list.prepend Places a at the front of list
list.append Places a at the end of list
list.join(list2) Appends list2 to list, destroying list2 in the
process
a = list.front() Returns a pointer to the element that is stored at
the head of the list
a = list.rear() Returns a pointer to the element that is stored at the
end of the list
a = list.remove_front() Deletes and returns the element that is stored
at the front of the list
list.del_front() Deletes the first element without returning it
list.clear() Deletes all items from list
list.ins_after(i, a) Inserts a after position i in the list
list.del_after(i) Deletes the element following position i in the list
Doubly linked lists also support the operations listed in Table 28.6.
Table 28.6. Doubly linked list operators.
Operator Description
a = list.remove_rear() Deletes and returns the element stored at the
end of the list
list.del_real() Deletes the last element, without returning it
list.ins_before(i, a) Inserts a before position i in the list
list.del(i, dir) Deletes the element at the current position and then
moves forward one position if dir is positive and backward one
position if dir is 0 or negative
Plex Classes
Plex classes are classes that behave like arrays but are much more
powerful. Plex classes have the following properties:
* They have arbitrary upper and lower index bounds.
* They can dynamically expand in both the lower and upper bound
directions.
* Elements may be accessed by indices. Unlike typical arrays, bounds
checking is performed at runtime.
* Only elements that have been specifically initialized or added can
be accessed.
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.
Table 28.7. Operations defined for Plexes.
Operation Description
Plex b Assigns a copy of Plex a to Plex b
b = a Copies Plex a into b
a.length() Returns the number of elements in a
a.empty() Returns TRUE if a has no elements
a.full() Returns TRUE if a is full
a.clear() Removes all the elements from a
a.append Appends Plex b to the high part of a
a.prepend Prepends Plex b to the low part of a
a.fill(z) Sets all elements of a equal to z
a.valid(i) Returns TRUE if i is a valid index into a
a.low_element() Returns a pointer to the element in the lowest
position in a
a.high_element() Returns a pointer to the element in the highest
position in a
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.
Table 28.8. Stack class operators.
Operator Description
Stack st Declares st to be a stack
Stack st(sz) Declares st to be a stack of size sz
st.empty() Returns TRUE if stack is empty
st.full() Returns TRUE if stack is full
st.length() Returns the number of elements in stack
st.push(x) Puts element x onto the top of the stack
x = st.pop() Removes and returns the top element from the stack
st.top() Returns a pointer to the top element in the stack
st.del_top() Deletes the top element from the stack without returning
it
st.clear() Deletes all elements from stack
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.
Table 28.9. Queue class operators.
Operator Description
Queue q Declares q to be a queue
Queue q(sz) Declares q to be a queue of size sz
q.empty() Returns TRUE if q is empty
q.full() Returns TRUE if q is full
q.length() Returns the number of elements in q
q.enq(x) Adds the x element to q
x = q.deq() Removes and returns an element from q
q.front() Returns a pointer to the front of q
q.del_front() Removes an element from q and does not return the result
q.clear Removes all elements from the queue
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.
Table 28.10. Set operators.
Operator Description
Set s Declares a set named s that is initially empty
Set s(sz) Declares a set named s that is initially empty and has a set
maximum size of sz
s.empty() Returns TRUE if s is empty
s.length() Returns the number of elements in s
i = s.add(z) Adds z to s, returning its index value
s.del(z) Deletes z from s
s.clear() Removes all elements from s
s.contains(z) Returns TRUE if z is in s
s.(i) Returns a pointer to the element indexed by i
i = a.first() Returns the index of the first item in the set
s.next(i) Makes i equal to the index of the next element in s
i = s.seek(z) Sets i to the index of z if z is in s, and 0 otherwise
set1 == set2 Returns TRUE if set1 contains all the same elements as
set2
set1 != set2 Returns TRUE if set1 does not contain all the same
elements as set2
set1 <= set2 Returns TRUE if set1 is a subset of set2
set1 |= set2 Adds all elements of set2 to set1
set1 -= set2 Deletes all the elements that are contained in set2 from
set1
set1 &= set2 Deletes all elements from set1 that occur in set1 and not
in set2
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.
Table 28.11. Additional operators for bags.
Operator Description
b.remove(z) Deletes all occurrences of z from b
b.nof(z) Returns the number of occurrences of z that are in b
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.
Summary
C++ offers many advantages over C. Some of these advantages come from
the concepts of object-oriented programming, and others come from the
highly flexible class libraries that are available to C++ programmers.
This chapter gave a brief introduction to object-oriented programming
and also talked about the C++ features that exist in the GNU C
compiler and the GNU debugger.
--
Enjoy Linux!
-----It's FREE!-----
※ 来源:.紫 丁 香 bbs.hit.edu.cn.[FROM: mtlab.hit.edu.cn]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:612.420毫秒