Vous êtes sur la page 1sur 23

The C++ Programming Inheritance Preview

Language Inheritance Example: Ada-style Vectors


Dynamic Binding Preview
Overloading
A Tour Through C++ New-Style Comments
Type-Safe Linkage
Inline Functions
Dynamic Memory Management
Outline Const Type Quali er
Stream I/O
C++ Overview Boolean Type
C++ Design Goals References
Major C++ Enhancements Type Cast Syntax
Other Enhancements Default Parameters
Language Features Not Part of C++ Declaration Statements
Function Prototypes Abbreviated Type Names
C++ Classes User-De ned Conversions
Class Vector Example Static Initialization
C++ Objects Miscellaneous Di erences
C++ Object-Oriented Features 1

C++ Overview C++ Design Goals


 C++ was designed at AT&T Bell Labs by As with C, run-time eciency is important
Bjarne Stroustrup in the early 80's 

{ The original cfront translated C++ into C for { e.g., unlike Ada, complicated run-time libraries
portability have not traditionally been required for C++
 However, this was dicult to debug and po-  Note, that there is no language-speci c sup-
tentially inecient port for concurrency, persistence, or distri-
bution in C++
{ Many native host machine compilers now exist
 e.g., Borland, DEC, GNU, HP, IBM, Microsoft,
Sun, Symantec, etc.  Compatibility with C libraries and UNIX
tools is emphasized, e.g.,
 C++ is a mostly upwardly compatible ex- { Object code reuse
tension of C that provides:  The storage layout of structures is compat-
1. Stronger typechecking ible with C
2. Support for data abstraction  Support for X-windows, standard ANSI C li-
brary, UNIX system calls via extern block
3. Support for object-oriented programming
{ C++ works with the make recompilation utility
{ C++ supports the Object-Oriented paradigm
but does not require it
2 3
C++ Design Goals (cont'd) Major C++ Enhancements
1. C++ supports object-oriented program-
 \As close to C as possible, but no closer" ming features
{ i.e., C++ is not a proper superset of C, so that  e.g., single and multiple inheritance, abstract
backwards compatibility is not entirely main- base classes, and virtual functions
tained
 Typically not a problem in practice:::
2. C++ facilitates data abstraction and en-
capsulation that hides representations be-
hind abstract interfaces
 Note, certain C++ design goals con ict  e.g., the class mechanism and parameterized
with modern techniques for: types
1. Compiler optimization
{ e.g., pointers to arbitrary memory locations 3. C++ provides enhanced error handling ca-
complicate register allocation and garbage pabilities
collection
 e.g., exception handling
2. Software engineering
{ e.g., separate compilation complicates inlin- 4. C++ provides a means for identifying an
ing due to diculty of interprocedural anal- object's type at runtime
ysis
 e.g., Run-Time Type Identi cation (RTTI)
4 5

Other Enhancements
 C++ enforces type checking via function
Other Enhancements (cont'd)
prototypes
 References provide \call-by-reference" pa-
rameter passing
 Allows several di erent commenting styles

 Provides type-safe linkage  Declare constants with the const type qual-
i er
 Provides inline function expansion
 New mutable type quali er
 Built-in dynamic memory management via
new and delete operators  New bool boolean type

 Default values for function parameters  New type-secure extensible I/O interface
called streams and iostreams
 Operator and function overloading
6 7
Other Enhancements (cont'd)
 A new set of \function call"-style cast no- Language Features Not Part of
tations
C++
 Variable declarations may occur anywhere
statements may appear within a block 1. Concurrency
 See \Concurrent C" by Nehrain Gehani
 The name of a struct, class, enum, or
union is a type name 2. Persistence
 Allows user-de ned conversion operators  See Exodus system and E programming lan-
guage

 Static data initializers may be arbitrary ex-


pressions 3. Garbage Collection
 See papers in USENIX C++ 1994
 C++ provides a namespace control mech-
anism for restricting the scope of classes,
functions, and global objects
8 9

Function Prototypes (cont'd)


Function Prototypes
 Proper prototype use detects erroneous
 C++ supports stronger type checking via parameter passing at compile-time, e.g.,
function prototypes
#if de ned ( STDC ) jj de ned ( cplusplus)
{ Unlike ANSI-C, C++ requires prototypes for extern int freopen (const char *nm,
both function declarations and de nitions const char *tp,
FILE *s);
{ Function prototypes eliminate a class of com- extern char *gets (char *);
mon C errors extern int perror (const char *);
#else /* Original C-style syntax. */
 e.g., mismatched or misnumbered parameter extern int freopen (), perror ();
values and return types extern char *gets ();
#endif /* de ned ( STDC ) */
/* */:::

int main (void) f


 Prototypes are used for external declara- char buf[80];
tions in header les, e.g.,
if (freopen ("./foo", "r", stdin) == 0)
extern char *strdup (const char *s); perror ("freopen"), exit (1);
extern int strcmp (const char *s, const char *t);
FILE *fopen (const char * lename, const char *type); while (gets (buf) != 0)
extern void print error msg and die (const char *msg); /* ::: */;
g
10 11
Function Prototypes (cont'd) Overloading
The preceeding program fails mysteriously  Two or more functions or operators may

if the actual calls are: be given the same name provided the type
signature for each function is unique:
/* Extra argument, also out-of-order! */ 1. Unique argument types:
freopen (stdin, "new le", 10, 'C'); double square (double);
Complex &square (Complex &);
/* Omitted arguments. */ 2. Unique number of arguments:
freopen ("new le", "r");
void move (int);
void move (int, int);
 A \Classic C" compiler would generally
not detect erroneous parameter passing at
compile time (though lint would)  A function's return type is not considered
when distinguishing between overloaded in-
{ Note, C++ lint utilities are not widely avail- stances
able, but running GNU g++ -Wall provides
similar typechecking facilities { e.g., the following declarations are ambiguous
to the C++ compiler:
extern double operator / (Complex &, Complex &);
 Function prototypes are used in both def- extern Complex operator / (Complex &, Complex &);
initions and declarations
{ Note, the function prototypes must be consis-  Note, overloading is really just \syntactic
tent!!! sugar!"
12 13

C++ Classes
C++ Classes (cont'd)
 The class is the basic protection and data
abstraction unit in C++
 For eciency and C compatibility reasons,
{ i.e., rather than \per-object" protection C++ has two type systems
1. One for built-in types, e.g., int, oat, char,
double, etc.
 The class mechanism facilitates the cre-
ation of user-de ned Abstract Data Types 2. One for user-de ned types, e.g., classes, structs,
(ADTs) unions, enums etc.
{ A class declarator de nes a type comprised of
data members, as well as method operators
 Data members may be both built-in and user-  Note that constructors, overloading, in-
de ned heritance, and dynamic binding only apply
to user-de ned types
{ Classes are \cookie cutters" used to de ne ob- { This minimizes surprises, but is rather cumber-
jects some to document and explain :::

 a.k.a. instances

14 15
C++ Classes (cont'd) C++ Classes (cont'd)
 A class is a \type constructor"  General characteristics of C++ classes:
{ e.g., in contrast to an Ada package or a Mod- { Any number of class objects may be de ned
ula 2 module  i.e., objects, which have identity, state, and
 Note, these are not types, they are \encap- behavior
sulation units"
{ Class objects may be dynamically allocated and
{ Until recently, C++ did not have a higher-level deallocated
modularization mechanism :: :

{ Passing class objects, pointers to class objects,


 This was a problem for large systems, due and references to class objects as parameters
to lack of library management facilities and to functions are legal
visibility controls
{ Vectors of class objects may be de ned
{ Recent versions of the ANSI C++ draft stan-
dard include mechanisms that addresses names-
pace control and visibility/scoping, e.g.,
 A class serves a similar purpose to a C
 Name spaces struct
 Nested classes { However, it is extended to allow user-de ned
behavior, as well

16 17

Class Vector Example


 There are several signi cant limitations with Class Vector Example (cont'd)
built-in C and C++ arrays, e.g.,
1. The size must be a compile-time constant,
e.g.,  We can write a C++ class to overcome
some of these limitations, i.e.,
void foo (int i)
f { (1) compile-time constant size
int a[100], b[100]; // OK
int c[i]; // Error! { (4) lack of range checking
g
2. Array size cannot vary at run-time
3. Legal array bounds run from 0 to size , 1  Later on we'll use inheritance to nish the
job, i.e.,
4. No range checking performed at run-time, e.g., { (2) resizing
f { (3) non-zero lower bounds
int a[10], i;
for (i = 0; i <= 10; i++)
a[i] = 0; { (5) array assignment
g
5. Cannot perform full array assignments, e.g.,
a = b; // Error!
18 19
Class Vector Example (cont'd)
 /* File Vector.h (this ADT is incomplete Class Vector Example (cont'd)
wrt initialization and assignment !) */ :::

#if !de ned ( VECTOR H) // Wrapper section  /* File Vector.C */


#de ne VECTOR H
#include "Vector.h"
typedef int T; bool Vector::set (size t i, T item) f
class Vector f if (this->in range (i)) f
public: this->buf [i] = item;
Vector (size t len = 100) f return true;
this->size = len; g
this->buf = new T[len]; else
g return false;
~Vector (void) f delete [] this->buf ; g g
size t size (void) const f return this->size ; g
bool set (size t i, T item); bool Vector::get (size t i, T &item) const f
bool get (size t i, T &item) const; if (this->in range (i)) f
item = this->buf [i];
private: return true;
size t size ; g
T *buf ; else
bool in range (size t i) const f return false;
return i >= 0 && i < this->size (); g
g
g;
#endif /* VECTOR H */
20 21

Class Vector Example (cont'd)


 // File test.C
Class Vector Example (cont'd) #include <libc.h>
#include "Vector.h"
void foo (size t size) f
Vector user vec (size); // Call constructor
int c vec[size]; // Error, no dynamic range
len dynamically allocated memory of size len
c vec[0] = 0;
buf user vec.set (0, 0);
for (int i = 1; i < user vec.size (); i++) f
int t;
user vec.get (i , 1, t);
user vec.set (i, t + 1);
 The control block that represents an ob- c vec[i] = c vec[i , 1] + 1;
ject of class Vector g
{ Note, the control block may be allocated o // Error, private and protected data inaccessible
the stack, the global data segment, or the heap size = user vec.size , 1;
user vec.buf [size] = 100;
{ However, the buf eld always points to mem- // Run-time error, index out of range
if (user vec.set (user vec.size (), 1000) == false)
ory allocated o the heap err ("index out of range");
// Index out of range not detected at runtime!
c vec[size] = 1000;
// Destructor called when user vec leaves scope
g
22 23
Class Vector Example (cont'd) Class Vector Example (cont'd)
 /* File Vector.h */
 Note that this example has several unnec-
essary limitations that are addressed by // typedef int T;
additional C++ features, e.g., template <class T>
class Vector f
public:
{ set/get paradigm di ers from C's built-in sub- struct RANGE ERROR fg;
script notation Vector (size t len = 100): size (len) f
if (this->size <= 0)
{ Error checking via return value is somewhat throw Vector<T>::RANGE ERROR ();
awkward else this->buf = new T[this->size ];
g
~Vector (void) f delete [] this->buf ; g
{ Only works for a vector of ints size t size (void) const f return this->size ; g
T &operator[] (size t i) f
{ Classes that inherit from Vector may not al- if (this->in range (i))
ways want the extra overhead of range checking return this->buf [i];
:::
else throw Vector<T>::RANGE ERROR ();
g
protected:
 The following example illustrates several T &elem (size t i) f return this->buf [i]; g
more advanced C++ features private:
size t size ;
T *buf ;
{ Don't worry, we'll cover these features in much bool in range (size t i) f
greater detail over the course of the class!!!! return i >= 0 && i < this->size ;
g
g;
24 25

Class Vector Example (cont'd)


 // File test.C
#include <libc.h> C++ Objects
#include "Vector.h"
void foo (size t size) f
try f // Illustrates exception handling A C++ object is an instance of a class (or
Vector<int> user vec (size); // Call constructor
:::

int c vec[size]; // Error, no dynamic range any other C++ type for that matter ) :::

c vec[0] = user vec[0] = 0;


for (int i = 1; i < user vec.size (); i++) f An object can be instantiated or disposed
user vec[i] = user vec[i , 1] + 1; 
c vec[i] = c vec[i , 1] + 1; either implicitly or explicitly, depending on
g
its life-time
// Error, private and protected data inaccessible
size = user vec.size , 1;
user vec.buf [size] = 100;
user vec.elem (3) = 120;  As with C, the life-time of a C++ object
is either static, automatic, or dynamic
// Run-time error, RANGE ERROR thrown
user vec[user vec.size ()] = 1000; { C and C++ refer to this as the \storage class"
// Index out of range not detected at runtime! of an object
c vec[size] = 1000;
// Destructor called when user vec leaves scope
g
catch (Vector<int>::RANGE ERROR) f /* */ g
g
:::

26 27
C++ Objects (cont'd)
C++ Objects (cont'd)
 Life-time or \storage class:"
1. Static
{ i.e., it lives throughout life-time of process
High Stack Automatic
{ static can be used for local, global, or class- Addresses Variables
speci c objects (note, their scope is di er-
ent) Heap
Dynamic
Variables

2. Automatic Uninitialized
Global Data Static
{ i.e., it lives only during function invocation, Initialized Variables
on the \run-time stack" Low
Global Data
Read-Only
Addresses Text Code and
3. Dynamic Data

{ i.e., it lives between corresponding calls to


operators new and delete
 Or malloc and free  Typical layout of memory objects in the
{ Dynamic objects have life-times that extend process address space
beyond their original scope
28 29

C++ Objects (cont'd)


C++ Objects (cont'd)  Several workarounds exist, however, e.g.,
{ Use Ei el or LISP ;-)
 Most C++ implementations do not sup-
port automatic garbage collection of dy- { Use inheritance to derive from base class Col-
namically allocated objects lectible
{ In garbage collection schemes, the run-time  However, this only works then for a sub-
system is responsible for detecting and deal- set of classes (i.e., doesn't work for built-in
locating unused dynamic memory types )
:::

{ Note, it is very dicult to implement garbage { Use the class-speci c new and delete opera-
collection correctly in C++ due to pointers and tors to de ne a memory management facility
unions using reference counts to reclaim unused mem-
ory

 Therefore, programmers must explicitly deal- { Adapt Hans Boehm's conservative garbage col-
locate objects when they want them to go lector for C to C++ :::

away
{ C++ constructors and destructors are useful
for automating certain types of memory management :::  No solution is optimal, however, so stor-
age management is often performed \by
hand" (ugh ;-))
30 31
C++ Object-Oriented Features C++ Object-Oriented Features
 C++ provides three characteristics gen-
erally associated with object-oriented pro- (cont'd)
gramming:
1. Data Abstraction  C++'s object-oriented features encourage
designs that
{ Package a class abstraction so that only the 1. Explicitly distinguish general properties of re-
public interface is visible and the implemen- lated concepts from
tation details are hidden from clients
{ Allow parameterization based on type 2. Speci c details of particular instantiations of
these concepts
2. Single and Multiple Inheritance
{ A derived class inherits operations and at-
tributes from one or more base classes, pos-  e.g., an object-oriented graphical shapes
sibly providing additional operations and/or
attributes library design using inheritance and dy-
3. Dynamic Binding namic binding
{ The actual type of an object (and thereby
its associated operations) need not be fully
known until run-time  This approach facilitates extensibility and
 Compare with C++ template feature, which reusability
are instantiated at compile-time
32 33

C++ Object-Oriented Features C++ Object-Oriented Features


(cont'd) (cont'd)
Rectangle  Inheritance and dynamic binding facilitate
Circle Triangle
the construction of \program families" and
frameworks
{ Program families are sets of programs whose
common properties are so extensive that it is
advantageous to study the common proper-
Color ties of the programs before analyzing individual
Shape members
1 1 A
{ A framework is an integrated set of compo-
Point
1 nents that collaborate to product a reuseable
1 architecture for a family of related applications

 It also supports the open/closed principle


 Note, the \OOD challenge" is to map ar-
bitrarily complex system architectures into { i.e., open with respect to extensibility, closed
with respect to stability
inheritance hierarchies
34 35
Inheritance Example: Ada-style
Inheritance Preview Vectors
 A type can inherit or derive the character-
istics of another base type. These derived  /* File Ada Vector.h (still incomplete wrt
types act just like the base type, except assignment and initialization) */
for an explicit list of:
1. Operations that are implemented di erently, #if !de ned ( ADA VECTOR H)
i.e., overridden #de ne ADA VECTOR H
#include "Vector.h"
template <class T>
2. Additional operations and extra data members class Ada Vector : private Vector<T>
f
3. Modi ed method access privileges public:
Ada Vector (int l, int h);
T &operator() (int i);
 C++ supports both single and multiple // extend visibility from class Vector
inheritance, e.g., Vector::size;
Vector::RANGE ERROR;
class X f /* */ g;
::: // Note, destructor is not inherited:::

class Y : public X f /* */ g;
::: private:
class Z : public X f /* */ g;
::: int lo bnd ;
class YZ : public Y, public Z f /* ::: */ g; g;
#endif /* ADA VECTOR H */
36 37

Inheritance Example: Ada-style


Vectors (cont'd)
Inheritance Example: Ada-style
 Example Ada Vector Usage
Vectors (cont'd) { // File main.C
/* File Ada Vector.C */ #include <stream.h>
 #include "Ada Vector.h"
extern "C" int atoi (const char *);
template <class T>
Ada Vector<T>::Ada Vector (int l, int h) int main (int argc, char *argv[]) f
: lo bnd (l), Vector<T> (h , l + 1) fg try f
int lower = atoi (argv[1]);
int upper = atoi (argv[2]);
template <class T> Ada Vector<int> ada vec (lower, upper);
T &Ada Vector<T>::operator() (int i) f ada vec (lower) = 0;
if (this->in range (i , this->lo bnd ))
// Call inherited operation, no range checking
return this->elem (i , this->lo bnd ); for (int i = lower + 1; i <= ada vec.size (); i++)
else ada vec (i) = ada vec (i , 1) + 1;
throw Ada Vector<T>::RANGE ERROR (); // Run-time error, index out of range
/* or ada vec (upper + 1) = 100;
(*this)[i , this->lo bnd ]; */
g // Vector destructor called when
// ada vec goes out of scope
g
catch (Ada Vector<int>::RANGE ERROR) f /* *
g
:::

38 39
Dynamic Binding Preview Dynamic Binding Preview
(cont'd)
 Dynamic binding is a mechanism used along
with inheritance to support a form of poly-  e.g.,
morphism
struct X f /* Base class */
int f (void) f puts ("X::f"); g // Non-virtual
 C++ uses virtual functions to implement virtual int vf (void) f puts ("X::vf"); g // Virtual
dynamic binding: g;
struct Y : public X f /* Derived class */
{ The actual method called at run-time depends int f (void) f puts ("Y::f"); g // Non-virtual
on the class of the object used when invoking virtual int vf (void) f puts ("Y::vf"); g // Virtual
the virtual method g;
void foo (X *x) f /* Note, can also use references */ :::

 C++ allows the class de ner the choice x->f (); /* direct call: f 1X (x); */
of whether to make a method virtual or x->vf (); /* indirect call: (*x->vptr[1]) (x) */
not g
{ This leads to time/space performance vs. ex- int main (void) f
ibility tradeo s X x;
Y y;
 Virtual functions introduce a small amount foo (&x); // X::f, X::vf
of overhead for each virtual function call foo (&y); // X::f, Y::vf
g
40 41

Dynamic Binding Preview New-Style Comments


(cont'd)  C++ allows two commenting styles:
 Each class with 1 or more virtual func- 1. The traditional C bracketed comments, which
tions generates one or more virtual tables may extend over any number of lines, e.g.,
(vtables) /*
This is a multi-line C++ comment
{ Note, multiple inheritance creates multiple vta- */
bles 2. The new \continue until end-of-line" comment
style, e.g.,
// This is a single-line C++ comment
 A vtable is logically an array of pointers
to methods  Note, C-style comments do not nest
{ A vtable is typically implemented as an array /*
of pointers to C functions /* Hello world program */
int main (void) f
printf ("hello world\n");
g
 Each object of a class with virtual func- */
tions contains one or more virtual point-
ers (vptrs), which point at the appropriate  However, these two styles nest, so it is
vtable for the object possible to comment out code containing
{ The constructor automatically assigns the vp-
other comments, e.g.,
trs to point to the appropriate vtable /* assert (i < size) // check index range */
// if (i != 0 /* check for zero divide */ && 10 / i)
42 43
New-Style Comments (cont'd)
Type-Safe Linkage
 Naturally, it is still possible to use C/C++
preprocessor directives to comment out Type-safe linkage allows the linker to de-
blocks of code: 
tect when a function is declared and/or
#if 0
used inconsistently, e.g.,:
/* Make sure only valid C++ code goes here! */ // File abs.c
/* i.e., don't use apostrophes! */
#endif long abs (long arg)
f
return arg < 0 ? -arg : arg;
 Beware of subtle whitespace issues ::: g
int b = a //* divided by 4 */4; // File application.c
-a; #include <stdio.h>
/* C++ preprocessing and parsing. */ int abs (int arg);
int b = a -a; int main (void) f printf ("%d\n", abs (,1)); g
/* C preprocessing and parsing. */
int b = a/4; -a;
 Without type-safe linkage, this error would
Note, in general it is best to use whites- remain hidden until the application was

pace around operators and other syntactic ported to a machine where ints and longs
elements, e.g., were di erent sizes
{ e.g., Intel 80286
char *x;
int foo (char * = x); // OK
int bar (char*=x); // Error
44 45

Type-Safe Linkage (cont'd) Type-Safe Linkage (cont'd)


 Type-safe linkage encodes all C++ func-
tion names with the types of their argu-  Name mangling was originally created to
ments (a.k.a. \name mangling"!) support overload resolution

 e.g.,  Only function names are mangled


{ i.e., variables, constants, enums, and types are
long abs (long arg) ! abs Fl not mangled :: :

int abs (int arg) ! abs Fi

 Therefore, the linker may be used to de-  On older C++ compilers, diagnostic mes-
sages from the linker are sometimes rather
tect mismatches between function proto- cryptic!
types, function de nitions, and function { See the c++filt program
usage
:: :

46 47
Typesafe Linkage (cont'd)
 Language interoperability issues
Typesafe Linkage (cont'd)
{ This problem arises as a side e ect of using  Language interoperability issues (cont'd)
type-safe linkage in C++
{ Other syntactic forms of extern blocks:
{ C functions used in C++ code (e.g., standard
UNIX library functions) must be explicitly de- extern "C" f
clared as requiring C linkage (i.e., names are char *mktemp (const char *);
not mangled) via the new extern "C" declara- char *getenv (const char *);
tion g
{ Encapsulating existing header les
 e.g., #if de ned ( cplusplus)
extern "C" f
extern "C" int abs (int i); #endif /* cplusplus */
double abs (double d); #include <string.h>
Complex abs (Complex &c); #ifdef cplusplus
g
int foo (int bar) f #endif /* cplusplus */
cout << abs (Complex (,10, 4.5)); { Note, extern blocks also support other languages :::

// calls abs F7Complex


<< abs (bar) // calls abs  e.g., FORTRAN, Pascal, Ada, etc.
<< abs (3.1416) // calls abs Fd

g
48 49

Inline Functions
Inline Functions (cont'd)
 Many programming languages force devel-
opers to choose between:
 Here's an example of a common C prob-
1. Modularity/abstraction (function call) lem with the preprocessor:
2. Performance (macro or inline-expansion by-hand) { Classic C macro, no sanity-checking at macro
expansion time
#de ne SQUARE(X) ((X) * (X))
 C++ allows inline function expansion, which int a = 10;
has several advantages:
int b = SQUARE (a++); // trouble!!! (a++) * (a++)
1. It combines the eciency of a macro with the
type-security and abstraction of a function call { C++ inline function template
2. It reduces both execution time and code size template<class T> inline
(potentially) T square (T x) f return x * x; g
3. It discourages the traditional reliance upon macro int c = square (a++); // OK
preprocessor statements

50 51
Inline Functions (cont'd) Inline Functions (cont'd)
 Points to consider about inline functions:  As an example of inlining in C++, we
1. Class methods that are de ned in their decla- will discuss a simple run-time function call
ration are automatically expanded inline \trace" facility
2. It is dicult to debug code where functions { Provides a rudimentary debugging facility
have been inline expanded and/or optimized  e.g., useful for long-running network servers
3. Compilers require more time and space to com-
pile when there are many inline functions
4. Inline functions do not have the pseudo-polymorphic  The goals are to be able to:
properties of macros 1. Determine the dynamic function calling behav-
{ However, inline templates approximate this ior of the program, i.e., \tracing"
functionality
2. Allow for ne-grain control over whether trac-
5. Compilers often have limits on the size and ing is enabled, e.g.,
type of function that can be inlined.
{ e.g., if stack frame is very large: { At compile-time (remove all traces of Trace
and incur no run-time penalty)
int foo (void) f
int local array[1000000]; { At run-time (via signals and/or command-
// line options)
{ This can cause surprising results wrt code
:::

size, e.g.,
3. Make it easy to automate source code instru-
int bar (void) f foo (); foo (); g mentation
52 53

Inline Functions (cont'd)


 Example output:
% CC -D__INLINE__ main.C trace.C
% a.out 10 1
enter int main (int argc, char *argv[]) in file main.C on line 25
enter void foo (void) (file main.C, line 8)
enter void foo (void) in (file main.C, line 8)
enter void foo (void) in (file main.C, line 8)
enter void foo (void) in (file main.C, line 8)
{ e.g., write a regular expression to match func- enter void foo (void) in (file main.C, line 8)

tion de nitions and then insert code auto- enter void foo (void) in (file main.C, line 8)

matically enter void foo (void) in (file main.C, line 8)


enter void foo (void) in (file main.C, line 8)
enter void foo (void) in (file main.C, line 8)
enter void foo (void) in (file main.C, line 8)
enter void foo (void) in (file main.C, line 8)
leave void foo (void)
leave void foo (void)
leave void foo (void)
leave void foo (void)
leave void foo (void)
leave void foo (void)
leave void foo (void)
leave void foo (void)
leave void foo (void)
leave void foo (void)
leave void foo (void)
leave int main (int argc, char *argv[])

54
Inline Functions (cont'd)
Inline Functions (cont'd)
 // Trace.h
 e.g., main.C
#if !de ned ( TRACE H)
#de ne TRACE H
#include "Trace.h" #if de ned (NTRACE) // compile-time omission
#de ne T(X)
void foo (int max depth) f #else
T ("void foo (void)"); #de ne T(X) Trace (X, LINE , FILE )
#endif /* NTRACE */
/* Trace ("void foo (void)", 8, "main.c") */
if (max depth > 0) foo (max depth , 1); class Trace f
/* Destructor called automatically */ public:
g Trace (char *n, int line = 0, char * le = "");
~Trace (void);
int main (int argc, char *argv[]) f static void start tracing (void);
const int MAX DEPTH = static void stop tracing (void);
static int set nesting indent (int indent);
argc == 1 ? 10 : atoi (argv[1]); private:
if (argc > 2) static int nesting depth ;
Trace::set nesting indent (atoi (argv[2])); static int nesting indent ;
if (argc > 3) static int enable tracing ;
Trace::stop tracing (); char *name ;
g;
T ("int main (int argc, char *argv[])"); #if de ned ( INLINE )
foo (MAX DEPTH); #de ne INLINE inline
return 0; #include "Trace.i"
/* Destructor called automatically */ #else
g #de ne INLINE
#endif /* INLINE */
#endif /* TRACE H */
55 56

Inline Functions (cont'd)


Inline Functions (cont'd)  e.g., /* Trace.C */
 e.g., /* Trace.i */ #include "Trace.h"
#include <stdio.h> #if !de ned ( INLINE )
INLINE #include "Trace.i"
Trace::Trace (char *n, int line, char * le) f #endif /* INLINE */
if (Trace::enable tracing )
fprintf (stderr, "%*senter %s ( le %s, line %d)\n", /* Static initializations */
Trace::nesting indent * int Trace::nesting depth = 0;
Trace::nesting depth ++, int Trace::nesting indent = 3;
"", this->name = n, le, line); int Trace::enable tracing = 1;
g
void Trace::start tracing (void)
INLINE Trace::enable tracing = 1;
Trace::~Trace (void) f g
if (Trace::enable tracing ) void Trace::stop tracing (void) f
fprintf (stderr, "%*sleave %s\n", Trace::enable tracing = 0;
Trace::nesting indent * g
--Trace::nesting depth , int Trace::set nesting indent (int indent) f
"", this->name ); int result = Trace::nesting indent ;
g Trace::nesting indent = indent;
return result;
g
57 58
Dynamic Memory Management Const Type Quali er
 Dynamic memory management is now a  C++ data objects and methods are qual-
built-in language construct, e.g., i able with the keyword const, making
them act as \read-only" objects
{ Traditional C-style
void *malloc (size t); { e.g., placing them in the \text segment"
void free (void *); { const only applies to objects, not to types
//
int *a = malloc (10 * sizeof *a);
:::

free ((void *) a);


{ C++ syntax  e.g.,
int *a = new int[10];
int *b = new int; const char *foo = "on a clear day";
// char *const bar = "you can C forever!";
delete [] a; const char *const zippy = "yow!";
:::

delete b;
foo = "To C or not to C?" // OK
 Built-in support for memory management foo[7] = 'C'; // error, read-only location
improves: // error, can't assign to const pointer bar
1. Type-security bar = "avoid cliches like the plague.";
// OK, but be careful of read-only memory!!!
2. Extensibility bar[1] = 'D';

3. Eciency const int index = 4 , 3; // index == 1


// read-only an array of constant ints
const int array[index + 3] = f2, 4, 8, 16g;
59 60

Const Type Quali er (cont'd) Const Type Quali er (cont'd)


 User-de ned const data objects:  const methods
{ A const quali er can also be applied to an { const methods may specify that certain read-
object of a user-de ned type, e.g., only operations take place on user-de ned const
objects, e.g.,
const String string constant ("Hi, I'm read-only!");
const Complex complex zero (0.0, 0.0); class String f
string constant = "This will not work!"; // ERROR public:
complex zero += Complex (1.0); // ERROR size t size (void) const f return this->len ; g
complex zero == Complex (0.0); // OK void set (size t index, char new char);
// :::

private:
 Ensuring \const correctness" is an impor- size t len;
tant aspect of designing C++ interfaces, g;
e.g.,
1. It ensures that const objects may be passed const String string constant ("hello");
as parameters string constant.size (); // Fine
{ A const method may not directly modify its
2. It ensures that data members are not acciden- this pointer
tally corrupted string constant.set (1, 'c'); // Error

61 62
Stream I/O
Stream I/O (cont'd)
 C++ extends standard C library I/O with
stream and iostream classes  The stream and iostream class categories
replace stdin, stdout, and stderr with cout,
 Several goals cin, and cerr

1. Type-Security
 These classes may be used by overloading
{ Reduce type errors for I/O on built-in and the << and >> operators
user-de ned types
{ C++ does not get a segmentation fault since
2. Extensibility (both above and below) the "correct" function is called
#include <iostream.h>
{ Allow user-de ned types to interoperate syn- char *name = "joe";
tactically with existing printing facilities int id = 1000;
cout << "name = " << name << ", id = " << id << '\n';
 Contrast with printf/scanf-family // cout.operator<< ("name = ").operator<< ("joe") :::

{ Transparently add new underlying I/O de- { In contrast, old C-style I/O o ers no protection
vices to the iostream model from mistakes, and gets a segmentation fault
on most systems!
 i.e., share higher-level formatting opera- printf ("name = %s, id = %s\n", name, id);
tions
63 64

Boolean Type
Stream I/O (cont'd)  C++ has added a new build-in type called
bool
{ The bool values are called true and false
 Be careful using Stream I/O in construc-
tors and destructors for global or static { Converting numeric or pointer type to bool
objects, due to unde ned linking order and takes 0 to false and anything else to true
elaboration problems :::
{ bool promotes to int, taking false to 0 and
true to 1
 In addition, the Stream I/O approach does { Statements such as if and while are now con-
not work particularly well in a multi-threaded verted to bool
environment :::

{ This is addressed in newer compilers that o er { All operators that conceptually return truth
thread-safe iostream implementations values return bool
 e.g., the operands of &&, jj, and !, but not
&, j, and ~

65 66
References
References (cont'd)
 C++ allows references, which may be:
1. Function parameters  e.g., consider a swap abstraction:
2. Function return values void swap (int x, int y)
3. Other objects f
int t = x; x = y; y = t;
g
 A reference variable creates an alternative int main (void) f
name (a.k.a. \alias") for an object int a = 10, b = 20;
printf ("a = %d, b = %d\n", a, b);
swap (a, b);
 References may be used instead of point- printf ("a = %d, b = %d\n", a, b);
ers to facilitate: g
1. Increased code clarity
 There are several problems with this code
2. Reduced parameter passing costs
1. It doesn't swap!
3. Better compiler optimizations
2. It requires a function call
 References use call-by-value syntax, but 3. It only works for integers!
possess call-by-reference semantics
67 68

References (cont'd) References (cont'd)


 e.g., swap  e.g., swap
void swap (int *xp, int *yp) f template <class T> inline void
int t = *xp; *xp = *yp; *yp = t; swap (T &x, T &y) f
g T t = x;
int main (void) f x = y;
int a = 10, b = 20; y = t;
printf ("a = %d, b = %d\n", a, b); g
swap (&a, &b);
printf ("a = %d, b = %d\n", a, b); int main (void) f
g int a = 10, b = 20;
double d = 10.0, e = 20.0;
#de ne SWAP(X,Y,T) \
do fT = (X); (X) = (Y); (Y) = ;g while (0) printf ("a = %d, b = %d\n", a, b);
int main (void) f printf ("d = %f, e = %e\n", d, e);
int a = 10, b = 20; swap (a, b);
printf ("a = %d, b = %d\n", a, b); swap (d, e);
SWAP (a, b, int); // beware of a++! printf ("a = %d, b = %d\n", a, b);
printf ("a = %d, b = %d\n", a, b); printf ("d = %f, e = %e\n", d, e);
g g

69 70
References (cont'd)
ir i Type Cast Syntax
10
 C++ introduces a new type cast syntax
in addition to Classic C style casts. This
"function-call" syntax resembles the type
conversion syntax in Ada and Pascal, e.g.,
 With references (as with classes), it is im- // function prototype from math.h library
portant to distinguish initialization from extern double log10 (double param);
assignment, e.g.,
int i = 10; if ((int) log10 ((double) 7734) != 0)
// initialization of ir ; /* C style type cast notation */
int &ir = i; // Equivalent to int *const ip = &i;
ir = ir + 10; // dereference is automatically done
// *ip = *ip + 10; if (int (log10 (double (7734))) != 7734)
; // C++ function-style cast notation
 Once initialized, a reference cannot be changed
{ i.e., it may not be reassigned to reference a  This \function call" is performed at com-
new location
pile time
{ Note, after initialization all operations a ect
the referenced object
 i.e., not the underlying const pointer :::

71 72

Type Cast Syntax (cont'd)


 This type cast syntax is also used to spec- Type Cast Syntax (cont'd)
ify explicit type conversion in the C++
class mechanism  Note, there are a variety of syntactical
{ This allows multiple-argument casts, i.e., \con- methods for constructing objects in C++,
structors" e.g.,
1. Complex c1 = 10.0;
 e.g.,: 2. Complex c2 = (Complex) 10.0;
class Complex f 3. Complex c3 = Complex (10.0);
public:
Complex (double, double = 0.0); 4. Complex c4 (10.0);
// :::

private:
double real, imaginary;
g;  I recommend version 4 since it is the most
consistent and also works with built-in types :::

// Convert 10.0 and 3.1416 into a Complex object


Complex c = Complex (10.0, 3.1416); { It also generalizes to multiple-argument casts :::

// Note that old-style C syntax would not suce here :::

Complex c = (Complex) (10.0, 3.1416);


73 74
Default Parameters (cont'd)
Default Parameters
 Default parameter passing semantics are
 C++ allows default argument values in similar to those in languages like Ada:
function de nitions { e.g., only trailing arguments may have defaults
{ If trailing arguments are omitted in the actual /* Incorrect */
function call these values are used by default, int x (int a = 10, char b, double c = 10.1);
e.g.,
{ Note, there is no support for \named parame-
void assign grade (char *name, char *grade = "A"); ter passing"
// additional declarations and de nitions :::

assign grade ("Bjarne Stroustrup", "C++");  However, it is not possible to omit argu-
// Bjarne needs to work harder on his tasks ments in the middle of a call, e.g.,
assign grade ("Jean Ichbiah"); extern int foo (int = 10, double = 2.03, char = 'c');
// Jean gets an "A" for Ada!
foo (100, , 'd'); /* ERROR!!! */
foo (1000); /* OK, calls foo (1000, 2.03, 'c');
 Default arguments are useful in situations
when one must change a class without af-
fecting existing source code  There are several arcane rules that per-
{ e.g., add new params at end of argument list mit successive redeclarations of a func-
(and give them default values) tion, each time adding new default argu-
ments
75 76

Declaration Statements Declaration Statements (cont'd)


 The following example illustrates declara-
 C++ allows variable declarations to occur tion statements and also shows the use of
anywhere statements occur within a block the \scope resolution" operator
{ The motivations for this feature are: #include <iostream.h>
1. To localize temporary and index variables struct Foo f static int var; g;
int Foo::var = 20;
const int MAX SIZE = 100;
2. Ensure proper initialization int var = 10;
{ This feature helps prevent problems like: int main (void) f
int k;
f k = call something ();
int i, j; // Note the use of the \scope resolution" operator
/* many lines of code */ ::: // (::) to access the global variable var
// Oops, forgot to initialize! int var = ::var , k + Foo::var;
while (i < j) /* */; :::

g for (int i = var; i < MAX SIZE; i++)


{ Instead, you can use the following for (int j = 0; j < MAX SIZE; j++) f
int k = i * j;
f cout << k;
for (int i = x, j = y; i < j; ) double var = k + ::var * 10.4;
/* ::: */; cout << var;
g g
g
77 78
Declaration Statements (cont'd) Abbreviated Type Names
 Unlike C, C++ allows direct use of user-
However, the declaration statement fea- de ned type tag names, without requiring

a preceding union, struct, class, or enum
ture may encourage rather obscure code speci er, e.g.,
since the scoping rules are not always in-
tuitive or desirable struct Tree Node f /* C code */
int item ;
struct Tree Node *l child , * child ;
g;
 Note, new features in ANSI C++ allow struct Tree Node f /* C++ code */
de nitions in the switch, while, and if int item ;
Tree Node *l child , *r child ;
condition expressions ::: g
 Another way of looking this is to say that
 According to the latest version of the ANSI/ISO C++ automatically typedefs tag names,
C++ draft standard, the scope of the def- e.g.,
inition of i in the following loop is limited
to the body of the for loop: typedef struct Tree Node Tree Node;
f  Note, this C++ feature is incompatible
for (int i = 0; i < 10; i++) with certain Classic and ANSI C identi er
/* */;:::
naming conventions, e.g.,
for (int i = 0; i < 20; i++)
/* */; struct Bar f /* */ g;
struct Foo f g;
:::
:::

g typedef struct Foo Bar; // Illegal C++, legal C!


79 80

User-De ned Conversions


User-De ned Conversions (cont'd)
 The motivation for user-de ned conver- Conversions come in two avors:
sions are similar to those for operator and 
function overloading 1. Constructor Conversions:
{ e.g., reduces \tedious" redundancy in source { Create a new object from objects of existing
code types
{ However, both approaches have similar prob- 2. Conversion Operators:
lems with readability :::
{ Convert an existing object into an object of
another type
 User-de ned conversions allow for more
natural looking mixed-mode arithmetic for e.g.,
user-de ned types, e.g.,: 

Complex a = Complex (1.0); class Complex f


Complex b = 1.0; // implicit 1.0 -> Complex (1.0)
public:
Complex (double); // convert double to Complex
operator String (); // convert Complex to String
a = b + Complex (2.5); // :::

a = b + 2.5 // implicit 2.5 -> Complex (2.5) g;


int foo (Complex c) f
c = 10.0; // c = Complex (10.0);
String s = a; // implicit a.operator String () String s = c; // c.operator String ();
cout << s;
g
81 82
Static Initialization
User-De ned Conversions
(cont'd)  In C, all initialization of static objects must
use constant expressions, e.g.,:
 In certain cases, the compiler will try a int i = 10 + 20; /* le scope */
single level of user-de ned conversion to int foo (void) f
determine if a type-signature matches a static int j = 100 * 2 + 1; /* local scope */
particular use, e.g., g

class String f  However, static initializers can be com-


public: prised of arbitrary C++ expressions, e.g.,
String (const char *s); extern int foo (void); // le scope
String &operator += (const String &); int a = 100;
g; int i = 10 + foo ();
String s; int j = i + *new int (1);
s += "hello"; // s += String ("hello");
int foo (void) f
 Note, it is easy to make a big mess by static int k = foo ();
abusing the user-de ned conversion lan- return 100 + a;
guage feature ::: g
{ Especially when conversions are combine with  Note, needless to say, this can become
templates, inheritance virtual functions, and
overloading, etc. rather cryptic, and the order of initializa-
tion is not well de ned between modules
83 84

Miscellaneous Di erences
 In C++, sizeof ('a') == sizeof (char); in
C, sizeof ('a') == sizeof (int)
Miscellaneous Di erences
{ This facilitates more precise overloading:::
(cont'd)
 In C++, a struct or class is a scope; in
 char str[5] = "hello" is valid C, but C++ C a struct, enum, or enum literal are
exported into the \global scope," e.g.,
gives error because initializer is too long
(because of hidden trailing '\0') struct Foo f enum Bar fBAZ, FOOBAR, BIZBUZZg; g;
/* Valid C, invalid C++ */
enum Bar bar = BAZ;
 In C++, a function declaration int f(); // Valid C++, invalid C
means that f takes no arguments (same Foo::Bar bar = Foo::BAZ;
as int f(void);). In C it means that f can
take any number of arguments of any type  The type of an enum literal is the type of
at all! its enumeration in C++; in C it is an int,
{ C++ would use int f ( );:::
e.g.,
/* True in C, not necessarily true in C++. */
 In C++, a class may not have the same sizeof BAZ == sizeof (int);
/* True in C++, not necessarily true in C. */
name as a typedef declared to refer to a sizeof Foo::BAZ == sizeof (Foo::Bar);
di erent type in the same scope
85 86
Miscellaneous Di erences
(cont'd) Summary
 In ANSI C, a global const has external  C++ adds many, many, many new fea-
linkage by default; in C++ it has internal tures to the C programming language
linkage, e.g.,
/* In C++, \global1" is not visible to other modules. */
const int global1 = 10;  It is not necessary to use all the features
/* Adding extern makes it visible to other modules. */ in order to write ecient, understandable,
extern const int global2 = 100; portable applications
 In ANSI C, a void * may be used as the
right-hand operand of an assignment or  C++ is a \moving target"
initialization to a variable of any pointer
type, whereas in C++ it may not (without { Therefore, the set of features continues to change
using a cast ):::
and evolve
void *malloc (size t); { However, there are a core set of features that
/* Valid C, invalid C++ */ are important to understand and are ubiquitous
int *i = malloc (10 * sizeof *i);
/* Valid C, valid C++ */
int *i = (int *) malloc (10 * sizeof *i);
87 88

Vous aimerez peut-être aussi