100% found this document useful (2 votes)
10 views79 pages

Multiparadigm Programming Using C 1st Edition Dirk Vermeir instant download

The document is about the book 'Multiparadigm Programming Using C' by Dirk Vermeir, which serves as an introduction to the C++ programming language and its abstraction mechanisms. It outlines the structure of the book, covering fundamental concepts, built-in types, user-defined types, and programming practices. The book is designed for second-year computer science students and includes supplementary materials available online.

Uploaded by

runzovalezxm
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (2 votes)
10 views79 pages

Multiparadigm Programming Using C 1st Edition Dirk Vermeir instant download

The document is about the book 'Multiparadigm Programming Using C' by Dirk Vermeir, which serves as an introduction to the C++ programming language and its abstraction mechanisms. It outlines the structure of the book, covering fundamental concepts, built-in types, user-defined types, and programming practices. The book is designed for second-year computer science students and includes supplementary materials available online.

Uploaded by

runzovalezxm
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 79

Multiparadigm Programming Using C 1st Edition

Dirk Vermeir download

https://ebookbell.com/product/multiparadigm-programming-
using-c-1st-edition-dirk-vermeir-48803382

Explore and download more ebooks at ebookbell.com


Here are some recommended products that we believe you will be
interested in. You can click the link to download.

Multiparadigm Programming In Mozartoz Second International Conference


Moz 2004 Charleroi Belgium October 78 2004 Revised Selected And
Invited Papers 1st Edition Gert Smolka Auth

https://ebookbell.com/product/multiparadigm-programming-in-mozartoz-
second-international-conference-moz-2004-charleroi-belgium-
october-78-2004-revised-selected-and-invited-papers-1st-edition-gert-
smolka-auth-4604406

Multiparadigm Constraint Programming Languages 1st Edition Petra


Hofstedt Auth

https://ebookbell.com/product/multiparadigm-constraint-programming-
languages-1st-edition-petra-hofstedt-auth-2448792

Multiparadigm Constraint Programming Languages 1st Edition Petra


Hofstedt Auth

https://ebookbell.com/product/multiparadigm-constraint-programming-
languages-1st-edition-petra-hofstedt-auth-4104716

Multiparadigm Modelling Approaches For Cyberphysical Systems 1st


Edition Bedir Tekinerdogan Editor

https://ebookbell.com/product/multiparadigm-modelling-approaches-for-
cyberphysical-systems-1st-edition-bedir-tekinerdogan-editor-34708930
Foundations Of Multiparadigm Modelling For Cyberphysical Systems Paulo
Carreira Vasco Amaral Hans Vangheluwe Carreira

https://ebookbell.com/product/foundations-of-multiparadigm-modelling-
for-cyberphysical-systems-paulo-carreira-vasco-amaral-hans-vangheluwe-
carreira-28689244

Introduction To The Design And Analysis Of Algorithms A Multiparadigm


Approach 1st Edition Arthur Nunes

https://ebookbell.com/product/introduction-to-the-design-and-analysis-
of-algorithms-a-multiparadigm-approach-1st-edition-arthur-
nunes-50244506

Kotlin Indepth Volii A Comprehensive Guide To Modern Multiparadigm


Language Aleksei Sedunov

https://ebookbell.com/product/kotlin-indepth-volii-a-comprehensive-
guide-to-modern-multiparadigm-language-aleksei-sedunov-44848948

Kotlin Indepth Voli A Comprehensive Guide To Modern Multiparadigm


Language Aleksei Sedunov

https://ebookbell.com/product/kotlin-indepth-voli-a-comprehensive-
guide-to-modern-multiparadigm-language-aleksei-sedunov-44848972

Kotlin Indepth Vol I A Comprehensive Guide To Modern Multiparadigm


Language Aleksei Sedunov

https://ebookbell.com/product/kotlin-indepth-vol-i-a-comprehensive-
guide-to-modern-multiparadigm-language-aleksei-sedunov-44859406
Multi-Paradigm Programming using c++
Springer-Verlag London Ltd.
Dirk Vermeir

Multi-Paradigm
Programming
using c++

Springer
Dirk Vermeir, PhD
Department of Computer Science, Free University of Brussels,
VUB, Pleinlaan 2, B1050 Brussels, Belgium

British Library Cataloguing in Publication Data


Vermeir, Dirk
Multi-paradigm programming using C++
1. Multiparadigm programming (Computer science) 2. C++
(Computer program language)
1. Title
005.1'33
ISBN 978-1-85233-483-3

Library of Congress Cataloging-in-Publication Data


Vermeir, Dirk, 1952-
Multi-paradigm programming using C++ / Dirk Vermeir.
p.cm
Inc1udes bibliographical references and index.
ISBN 978-1-85233-483-3 (alk. paper)
1. C++ (Computer program language) 1. Title.
QA76.73.CI53 V47 2001
005.13'33-dc21
2001032005

Apart from any fair dealing for the purposes of research or private study, or criticism or review, as
permitted under the Copyright, Designs and Patents Act 1988, this publication may only be reproduced,
stored or transmitted, in any form or by any means, with the prior permission in writing of the publishers,
or in the case of reprographic reproduction in accordance with the terms of licences issued by the
Copyright Licensing Agency. Enquiries concerning reproduction outside those terms should be sent to
the publishers.
ISBN 978-1-85233-483-3 ISBN 978-1-4471-0311-0 (eBook)
DOI 10.1007/978-1-4471-0311-0
http://www.springer.co.uk
© Springer-Verlag London 2001
Originally published by Springer-Verlag London Berlin Heide1berg in 2001
The use of registered names, trademarks etc. in this publication does not imply, even in the absence of a
specific statement, that such names are exempt from the relevant laws and regulations and therefore free
for general use.
The publisher makes no representation, express or implied, with regard to the accuracy of the
information contained in this book and cannot accept any legal responsibility or liability for anyerrors or
omissions that may be made.

Typesetting: Camera-ready by author

34/3830-543210 Printed on acid-free paper SPIN 10834524


Preface

Many Computer Science programmes teach two programming languages in the first
years of the core curriculum. The first language is selected for its simple semantics
and ease of use so that students can learn about fundamental computing topics such
as control structures, functions, recursion, abstract data types, etc. without bothering
about the underlying hardware and operating system aspects. C++ is not a good lan-
guage for this purpose.
The second language is then chosen to complement the first in that its teaching pro-
vides an opportunity to study the aspects that are abstracted from in the first language:
efficiency, run-time support including operating system interfaces and memory man-
agement, compilation and linking, etc. Choosing an industrially relevant and wide-
spectrum language has obvious additional advantages. C++ is an ideal candidate for
this purpose as it exposes the student to all of the above aspects while at the same time
it provides powerful abstraction mechanisms supporting generic and object-oriented
programming.
This textbook presents a concise yet reasonably complete introduction to the C++
programming language and its abstraction mechanisms. The reader is expected to be
familiar with basic programming concepts, making this book suitable, for example,
for second year computer science students.
C++ is a wide spectrum language that provides a confusing number of features, which
I've tried to streamline by providing a hierarchy of concepts centred around the no-
tions of types and type constructors. The structure of the book reflects the gradual
introduction of these concepts:

• simple data objects and functions,

• simple built-in types and operations,

• (user-defined) abstract data types,

• built-in type constructors,

• user-defined type constructors, and

• extending types using inheritance.

v
vi PREFACE

Each time, examples are provided to motivate the inclusion of a feature into the lan-
guage.
The text also touches on the implementation of the various concepts. This is necessary
to motivate the decisions that have influenced the design of C++, thus making it easier
to really understand the language. Moreover, knowing a bit about the implementation
is also useful when assessing the efficiency aspects of alternative designs.

Chapter Summary
• Chapter 1 presents the basic concepts of C++: data objects, values, types and
variables, references, object construction, functions; basic lexical and syntactic
(scope, namespaces) aspects of the language; compilation and linking.

• Chapter 2 covers built-in types and associated operators; it also introduces con-
versions and operator overloading.

• Functions are covered in Chapter 3: control flow, local and static data objects,
overloading.

• Chapter 4 introduces user-defined types, concentrating on the class construct as


a suitable mechanism for abstract data type programming.

• Pointers, constant objects and arrays are presented as built-in type constructors
(i.e. functions that map types to types) in Chapter 5. A taxonomy of object
memory management alternatives is also presented.

• Chapter 6 presents templates as user-defined type constructors. Template argu-


ment deduction, overloading and specialization are also covered.

• Generic programming using abstractions such as iterators is covered in Chap-


ter 7. The chapter includes an overview of several standard library containers,
algorithms and adaptors.

• Chapter 8 deals with derivation as a mechanism to support subtypes, polymor-


phism and object-oriented programming.

• Chapter 9 covers exceptions.

• Chapter 10 presents the iostream library, including its design and how to imple-
ment new stream classes.

• Chapter 11 motivates and describes good design practices: developing coherent


abstractions that are independent and reusable.
PREFACE vii

Supplementary Materials
The programs from the book, as well as other illustrative programs and case studies
can be found on the web site

http://tinf2.vub.ac.be/cpp/index.html.

The site also contains a set of transparencies and a list of errata.

Acknowledgements
This book was greatly improved through the comments and suggestions of students
and colleagues who read preliminary versions: Marina De Vos, Koen De Winter, Stijn
Heymans, Viviane lonckers, Carine Lucas, Michael Peeters, Frank Tavernier, Dirk
Verdonck, Wei Wang. Any mistakes that remain are of course my own.
Contents

Preface v

1 Basic Concepts of C++ 1


1.1 Objects, Values, Types, Variables . 1
1.1.1 Objects and Addresses 1
1.1.2 Values and Types . . . 2
1.1.3 Referring to Objects and Values: Variables, Constants, Ex-
pressions . . . . . . . . . . 2
1.2 Defining and Manipulating Objects . 3
1.3 References. 4
1.4 Functions . 6
1.4.1 Defining a Function 6
1.4.2 Calling a Function . 7
1.4.3 More on Parameter Passing. 10
1.5 Program Structure. . . . . . . . . . 12
1.5.1 Translation Units, Definitions and Declarations 12
1.5.2 The Compilation Process. 13
1.5.3 Program Organization . . 15
1.5.4 Linking and Executing a Program 17
1.6 Syntactic and Lexical Considerations. 19
1.6.1 Identifiers and Keywords . 19
1.6.2 Comments . . . 20
1.7 Scopes and Namespaces 21
1.7.1 Scopes . . . 21
1.7.2 Namespaces. 22

ix
x CONTENTS

2 Built-in Types 25
2.1 Arithmetic Types 25
2.2 Conversions for Arithmetic Types 27
2.3 Arithmetic Type Operations. 28
2.4 String Literals . 32

3 Functions 37
3.1 Function Declarations . ....... 37
3.1.1 Function Types, Signatures . 37
3.1.2 Default Arguments . . . . . 38
3.1.3 Unspecified Number of Arguments 38
3.1.4 Inline Functions 39
3.2 Overloading . . . . . 41
3.3 Function Definitions 42
3.3.1 Statements . 42
3.3.2 Control Flow Statements 43
The compound statement and the sequence operator 43
The if statement and the ? operator 43
The while statements 44
The £or statement . . 45
The switch statement . 46
The return, break and continue statements . 47
3.3.3 Local and Static Variables 49
Local object lifetime . 49
Persistent local objects 49

4 User-Defined Types 51
4.1 Abstract Data Types . 51
4.2 Classes ...... . 53
4.2.1 Class Members, Access Specification 53
4.2.2 Class Objects . . . . . . . . . . . . . 54
4.2.3 Data Member Declarations and Object Layout 54
4.2.4 Class Scope . . . . . . . . . . . 55
4.2.5 Function Member Declaration . 55
4.2.6 Overloading Member Functions 56
4.2.7 Initializing a Class Object . . . 56
CONTENTS Xl

The default constructor . 58


The copy constructor . . 58
4.2.8 Function Member Definition . 59
4.2.9 Inline Function Members. . . 60
4.2.10 Member Functions with Default Parameters . 61
4.2.11 User-Defined Conversions 61
4.2.12 Operator Overloading .. 63
Overloading the assignment operator 65
Overloading the increment and decrement operators 66
Forbidding operators 67
4.2.13 Finalizing an Object 68
4.2.14 Member Objects 69
4.2.15 Friends .... 71
4.2.16 Nested Classes 72
4.2.17 Static Members . 74
4.2.18 Implementation Aspects 74
4.2.19 Example: the Rational Class 76
4.3 Enumerations 80
4.4 Typedef . . . 81

5 Built-in Type Constructors 83


5.1 Constant Objects ... 83
5.2 Pointers . . . . . . . . 89
5.2.1 Pointers, Addresses, Dereferencing 89
5.2.2 Handles . . . . . . . . . . . . . . 91
5.2.3 Member Selection from Pointers . 91
5.2.4 Constant Pointers . . . . 92
5.2.5 Pointers vs. References . 92
5.2.6 The thi s Pointer 93
5.3 Arrays . . . . . . . . . . . 95
5.3.1 Initializing an Array 97
5.3.2 Arrays vs. Pointers, Pointer Arithmetic 98
5.3.3 Array Parameters . . . . . 99
5.3.4 Multidimensional Arrays . 101
5.4 Command Line Processing . . . . 101
xii CONTENTS

5.5 Pointers to Functions 102


5.6 Pointers to Members 103
5.7 Memory Management. 104
5.7.1 Static, Global, Automatic and Member Objects 104
5.7.2 Free Objects . . . . . 105
5.7.3 Encapsulating Pointers 107
5.8 More Operator Overloading . 110
5.8.1 Overloading new, delete 110
5.8.2 Placement New . 113
5.8.3 Smart Pointers . 115

6 User-Defined Ty][)e Constructors 117


6.1 Function Templates . . . . . . . . . . . 117
6.1.1 Template Argument Deduction . 120
6.1.2 Overloading Function Templates . 120
6.1.3 Explicit Specializations of Function Templates 122
6.1.4 A Generic Sort Function 122
6.2 Class TempIates . . . . . . . . . 123
6.2.1 Friends of Class Templates . 126
6.2.2 Nested Class Templates .. 127
6.2.3 Function Objects . . . . . . 128
6.2.4 Class Template Specialization 131
6.2.5 Reference Counting Pointers . 132
6.2.6 Auto Pointers . . . . . . . 134

7 Generic Programming Using the STL 137


7.1 Generic Programming. . . . . . . 137
7.2 Iterators.............. 140
7.2.1 Types Associated with an Iterator 143
7.2.2 Iteraaor Traits . . . . . . . . . . . 146
7.2.3 Dispatching on the Iterator Category . 148
7.3 Stream Iterators . . . . . . . 149
7.3.1 Input Stream Iterator 149
7.3.2 Output Stream Iterator 151
7.4 STL Containers 152
7.4.1 Pair .. 153
CONTENTS xiii

7.4.2 List .. 153


7.4.3 Vector. 155
7.4.4 Map. 157
7.4.5 Set 161
7.4.6 Other Containers 163
7.4.7 Container Adaptors. 163
7.5 STL Algorithms . . . . . . . 164
7.5.1 Non-mutating Algorithms 165
Finding elements in a range 165
Finding subranges . . . . . 165
Counting elements in a range . 166
Processing a range 166
Comparing ranges 167
Minimum and maximum . 168
7.5.2 Basic Mutating Algorithms. 169
Copying ranges . . . 169
Swapping elements . 169
Transforming a range . 169
Replacing elements in a range 169
Filling a range . . . 170
Removing elements . 170
Permuting algorithms . 171
Partitioning ranges . . 172
Random shuffling and sampling 172
Generalized numeric algorithms 173
7.5.3 Sorting and Searching .. . 174
Sorting ranges . . . . . . . 174
Operations on sorted ranges 175
Set operations. . 176
Heap operations 177
7.6 Iterator Adaptors . . . 178
7.6.1 Insert Iterators 178
7.6.2 Reverse Iterators 181

8 Subtypes and Inheritance 183


xiv CONTENTS

8.1 Derived Classes . . . . . . . . . . . . . . . . . . . . . . . . . . 183


8.1.1 Construction and Destruction of Derived Class Objects . 185
8.1.2 Inheritance and Scope ... 185
8.1.3 Inheritance and Conversions 186
8.1.4 Inheritance and Arrays . . . 187
8.2 Virtual Member Functions ..... 187
8.2.1 Implementation of Virtual Member Functions . 189
8.2.2 Pure Virtual Function Members and Abstract Classes 191
8.2.3 Virtual Destructors . . 192
8.3 Derivation and Access Control 193
8.3.1 Protected Members . . 193
8.3.2 Protected and Private Derivation 194
8.4 MUltiple and Virtual Inheritance .... 195
8.4.1 Multiple Inheritance ...... 195
8.4.2 Implementing Multiple Inheritance 196
8.4.3 Virtual Inheritance .. 197
8.5 Object-Oriented Programming 199
8.5.1 Class Hierarchies . 199
8.5.2 Polymorphism .. 199
8.6 Run-Time Type Identification. 201

9 Exceptions 205
9.1 Throwing and Catching Exceptions. 205
9.2 Run-Time Behaviour . . . . . . . . 208
9.3 Exceptions, Constructors and Destructors 210
9.3.1 Exceptions and Resource Management 210
9.3.2 Constructors Throwing Exceptions . 211
9.3.3 Destructors Throwing Exceptions 212
9.4 Exception Specifications 213
9.5 Standard Exceptions 214

10 Iostreams 217
10.1 Requirements 217
10.2 Design . . . . 218
10.3 Streambuf .. 219
10.4 Stream Base Classes 223
CONTENTS xv

10.4.1 los_base. . . . . . . . . 223


10.4.2 Basicios(CharT,Traits) 225
10.5 Stream Classes . . . . . . . . . 227
10.5.1 Basicistream(CharT,Traits) 227
10.5.2 Basicostream( CharT,Traits) 230
10.5.3 Basiciostream(CharT,Traits) 231
10.6 Manipulators . . . . . . . . . . . . . 231
10.7 File Streams . . . . . . . . . . . . . . 234
10.7.1 Basicifstream(CharT,Traits). 235
10.7.2 Basic_ofstream(CharT,Traits) 236
10.7.3 Basicfstream(CharT,Traits) 236
10.8 String Streams. . . . . . . . 237

11 Introduction to Program Design 241


11.1 Motivation: Properties of Good Programs 241
11.2 Abstractions . . . . . . . . . . . 246
11.3 Criteria For Good Abstractions . 252
11.4 The Design Process . . . . . 259
11.4.1 Finding Abstractions 259
11.4.2 Designing Classes 260
11.4.3 Refactoring . . 260
11.4.4 Documentation 260
11.4.5 Patterns 261

A C++ Operators 265

B The String Class 267

Bibliography 273

Index 275
Chapter 1

Basic Concepts of C++

1.1 Objects, Values, Types, Variables

1.1.1 Objects and Addresses

In C++, data are kept in (data) objects where an object is simply an area of memory.
Since each memory location is associated with a unique address, we can use the ad-
dress of the first (in the order of the addresses) byte of the object as the address of the
whole object) . An object's size, i.e. the size of its memory area, is fixed for its lifetime
but the contents of the associated memory area can, in general, vary over time.
Figure 1.1 depicts an object of size 28 bytes with address 10002.

memory

00000
I,(10002value~ I10030 IFFFFF
,,
object
address
Figure 1.1: Object, address, value.

1We will see in Section 5.2 that C++ makes these addresses available to the programmer, i.e. they can
be manipulated as other values. This contrasts with other programming languages such as Scheme, Java,
Prolog that provide a higher level of abstraction which does not include the concept of address. Of course,
that does not mean that these languages do not use addresses internally (as a matter of fact e.g. Java uses
addresses more intensely than many C++ programs). It's just that the programmer does not have access to
them.

1
2 CHAPTER 1. BASIC CONCEPTS OF C++

1.1.2 Values and Types


The contents of an object is a value. C++ supports many kinds of values, from primi-
tives like integers to complex programmer-defined values. Of course, the value of an
object must fit into its memory area. E.g. an object that is only 4 bytes wide cannot
contain a double precision floating point number which usually needs 8 bytes. This is
one of the reasons why C++ uses the notion of type. Theoretically, a type can be re-
garded as a collection of values belonging to that type. E.g. on a 32-bit processor, the
type int contains all integers that can be represented (in 2's complement notation)
using 32 bits.
Thus each object is associated with a type and the contents (value) of an object must
always be a value belonging to its type.
A type is usually associated with a set of operations that can be performed on that type.
E.g. int values can be added, subtracted, etc. Since, as we will see in Chapter 4, a
programmer can define her own types and associated operations, we can justly claim
that C++ supports abstract data types (ADTs?
Moreover, C++ also supports type constructors, i.e. (compile-time) functions that,
when applied to a type, yield a new type. Besides a number of built-in type construc-
tors, C++ also lets the programmer define her own type constructors3, a feature which
seems to be unique among commonly used programming languages.

1.1.3 Referring to Objects and Values: Variables, Constants, Ex-


pressions
The simplest way to refer to an object in a program text is by using a name for a par-
ticular object. Such a name is called a variable4 . The association between a variable
and the object it refers to is immutable.
One way to refer to a particular value is through a reference to an object containing
that value. If e.g. x is a variable that refers to an integer object containing the value 5
then we may use

to denote 5.
Simple values, i.e. values that belong to primitive data types such as integers, charac-
ters or literal strings, may be referenced directly using so-called constants. E.g.

23

denotes an integer value. Note that 23 is not an object, i.e. it does not have a known
address.
20f course, to properly support ADTs we also must be able to hide implementation details, but as will
be made clear in Chapter 4, C++ provides the necessary facilities for this as well.
3Templates are programmer-defined type constructors in C++, see Chapter 6.
4The otber ways are through references (see Section 1.3), pointers or arrays (see Chapter 5).
1.2. DEFINING AND MANIPULATING OBJECTS 3

Finally, we can denote values using expressions that compute new values using op-
erations that are applied on other values or objects. Variables and constants are also
considered to be (simple) expressions.
E.g. if x is a variable that refers to an integer object with value 5, then the expression

x+23

refers to the value 28. Here + is an operator representing integer addition. We will
see that some expressions refer to an object (and its value) while others result in a pure
value. The expression x+23 above represents a pure value.
In general, a reference to a value through an object (with this value) is called an lvalue
while a value without an address is called an rvalue 5 •
Thus the simple expression x denotes an lvalue while x+y denotes an rvalue.

1.2 Defining and Manipulating Objects


The easiest way to define an object is by defining it together with an associated variable
referring to that object. This may be done using a statement of the form6

I NameOfType NameOfVariable(InitialValue);

where NameO[Iype is the name of a primitive or programmer-defined type, Name-


OjVariable is the name of the variable and InitialValue is an expression denoting the
initial value of the object1.
E.g. the following fragment defines three objects: two of type int and one of type
doubleS.

int x(5);
int y(x+7);
double z(3.14);

When processing this fragment, the compiler will reserve 16 bytes of memory: 4 bytes
for x, 4 bytes for y and 8 bytes for z. Moreover, where appropriate9, the compiler will
5The importance of the distinction will become clear in Section 1.2.
6 An alternative syntax is

I NameOfType NameOfVariable = InitialValue


However, this is confusing with assignment (Section 1.2). In this book we will use mostly the NameOf-
Variable (Ini tial Value) syntax.
7The InitialValue is often optional but it is strongly recommended to initialize each newly defined vari-
able. Also, in Chapter 4 we will see that it is possible to initialize complex objects using programmer-
defined functions.
8Values of type double represent double-precision floating point numbers; on a 32-bit machine, a
double object takes 8 bytes.
9This depends on the scope, see Section 1.7.1.
4 CHAPTER 1. BASIC CONCEPTS OF C++

translate each usage of x (or y or z) as a reference to the appropriate memory area, as


illustrated in Figure 1.2.

memory

x y z
int int double

Figure 1.2: Defining three numeric objects.

The assignment statement lO can be used to change the value of an object. Its syntax is

LeftExpression = RightExpression;

Here, LeftExpression on the left-hand side of the assignment operator "=" must yield
an lvalue while RightExpression may result in either an lvalue or an rvalue. The
effect of the assignment is that the contents of the object referred to by LeftExpression
becomes the value denoted by RightExpression 11.
E.g. at the end of the following fragment the value of y will be 29, as illustrated in
Figure 1.3.

int x(5);
int y(x+7);
double z(3.14);

y =y * 2 + x;

1.3 References
An alternative way to refer to an object is by using a reference variable or, more
correctly, a variable of a reference type.
Such a variable is defined using a statement of the form

I NameOfType&: NameOfVariable (Expression) ;

which looks very much like a variable definition.


Here Expression is assumed to yield an lvalue of type NameO[I'ype 12 • The variable
NameOjVariable will then be "bound" to the object referred to by Expression.
IOMore accurately, the assignment expression statement, see also Section 2.3.
"This is actually only a convention: we shall see later (Section 4.2.12) that, for user-defined types, the
programmer can make the assignment operator do whatever she likes.
'2However, if Expression yields an rvalue, then a fresh object containing this value will be created and
NameOjVariable will be made to refer to it.
1.3. REFERENCES 5

memory (before)

x
5
y
12
z
3.14 I I
" I
t, ,
I ,
1 ~

Y =}
...
*2+ ~
_---
29

-
~~ memory (after)
5 3.14
x y z
iot iot double

Figure 1.3: Assigning the value of an object.

Like a nonnal variable, the association between a reference variable and the object it
refers to is immutable and must be established when the variable is defined.
Note that "reference to a type" is a type constructor, i.e. for any type T, there exists a
type T&:.
As an example, in the fragment

int x(5);

int& y(x);

y = 6;

both y and x refer to the same object. Consequently, after the assignment to y, also
the value of x is 6.
Reference variables are usually implemented as shown in Figure 1.4 which illustrates
the above code fragment: the "real" value (which is unaccessible to the programmer)
of y is the address of the object referred to by x.
Reference variables may not appear to be very useful but they are important in com-
bination with parameter passing to functions (Section 1.4). In addition, they come in
handy to implement immutable relationships between class objects (Section 4.2.12,
page 67).
6 CHAPTER 1. BASIC CONCEPTS OF C++

memory
r [00031
x y
int int&
y=6
" "
""
memory

x
int

Figure 1.4: A reference variable.

1.4 Functions
1.4.1 Defining a Function
Sometimes, an expression or, more generally, a sequence of statements, is needed
many times in a program. In order to avoid repeating the same code fragment again
and again, one may define a named junction that serves as an abstraction for the
behaviour of the code fragment.
A function can then be regarded as a black box that returns an output value, based on
its parameter input values (Figure 1.5).

xl

xn
___-=-:-----,:~( {unction ( J result" f(xl, ... ,xn)

parameters

Figure 1.5: A function is a black box.

For example, in the following fragment

int x(3);
int y(O) ;
int z(4);

y = x * x;
y=y+z*z;
1.4. FUNCTIONS 7

the square of both x and z is computed (* is the multiplication operator).


We can create a function square that takes a single integer parameter (input) value
and returns the square of this parameter as its return (output) value.

int
square(int a) {
return a*a;
}

In general, the definition of a function is of the form

ReturnType
FunctionNarne(PararneterDeclarationList) {
StatementList
}

The definition of a function consists of

• The name of the type of the output (return) value (int in the example). It may
be that there is no return value, in which case the return type should be specified
as void.

• The name of the function (square in the example).

• A comma-separated list of parameter declarations, between parentheses. Each


parameter declaration consists of the name of the type of the parameter, option-
ally followed by the name of the formal parameter variable. The list may be
empty but the parentheses must always be present. In the example, there is a
single parameter declaration: int a.

• The function body which consists of a sequence of statements between braces.


Within the body, there should be at least one return statement which has the
form

return Expression;

where, of course, the type of Expres s ion must match the declared type ofthe
return value (if the return type was void, there should be no return statement).

1.4.2 Calling a Function


Afunction call is an expression of the form

FunctionNarne(PararneterExpressionList)
8 CHAPTER 1. BASIC CONCEPTS OF C++

where ParameterExpressionList is a comma-separated list of expressions.


Each expression must yield a value of a type that matches the corresponding parameter
type in the function definition. A function call can appear anywhere that an expression
can appear, as is illustrated in the code below.

int x(3);
int y(O);
int z(4);

int
square(int a) {
return a*a;
}

y = square(x) + square(z);

At run-time, a function call is evaluated as follows:

1. For each formal parameter of the function:

(a) The corresponding parameter expression in the call is evaluated and


(b) the result is used to initialize a new object corresponding to the formal
parameter variable (note that fresh memory must be allocated to accom-
modate this new object).

Thus, the evaluation of a function call starts by copying the actual parameter
values to fresh local parameter variables.
E.g. for a call f (e 1, e2) to a function R f (Ti vi, T2 v2), this boils
down to defining two local objects
Tl vl( el);
T2 v2( e2);

2. The statements of the function body are executed. This happens in an "environ-
ment" where the following names are available:

• local names, e.g. variables (including the ones containing copies of the
actual parameters, see (1) above
• all the names available in encompassing scopes 13 (see Section 1.7.1).

3. When a return statement is encountered, the corresponding expression is


evaluated. The result is used to initialize a new object (of the proper type)
which is returned to the caller.

4. All memory allocated during the execution of the function call, e.g. to store the
parameter objects, is deallocated, i.e. returned to the operating system.
13 As long as there is no more closely nested (around the function body) scope that defines the same name.
1.4. FUNCTIONS 9

Thus a function call needs extra memory from the operating system to store "local"
information such as the formal parameter variable objects, (local) variables that are
defined within the body, etc. This extra memory area is called the function call's
frame 14.
Since function calls may be nested, i.e. one function may call another (or the same)
function from within its body, it follows that such memory is allocated and deallocated
in a "first-allocated-Iast-deallocated" fashion. Hence the system will manage a call
stack of frames corresponding to "active" function calls.
The process is illustrated in Figure 1.6 for the expression factorial (3) where the
function factorial is defined below.

int
factorial(int n) {
if (n<2)
return 1;
else
return n*factorial(n -1);
}

Here the function body consists of an if statement which, when executed, first tests the
condition expression n<2. If this is the case, i.e. if the value of the parameter variable
n is indeed strictly smaller than 2, then the return 1 statement is executed, return-
ing 1 for the function call. If the condition is false, i.e. the value of the parameter vari-
able n is at least 2, then the alternative statement return n * factorial (n-
1) is executed. Note that to compute the expression n * factorial (n-l), an-
other call to the factorial function (this time with a smaller parameter value) must be
performed.

return 1

1"l-(2) ~,., '__(2) 1"'1"""'"'"(2)


=1 factorial(l) return 2

",,",6

1 n = 3 1factorial(3) n =3 factorial(3) n =3 factorial(3) n =3 factorial(3) 1 n =31 factorial(3)

(I) (2) (3) (4) (5)

Figure 1.6: Evaluating a function call.

Figure 1.6 shows snapshots of the call stack at various stages of the evaluation of
factorial (3).

1. factorial (3) is being evaluated: since n=3, which is not smaller than
14 Actually, a frame contains more than parameters and local variable objects: also saved information on
the state of the CPU just before the call, including the program counter, is kept in the frame.
10 CHAPTER 1. BASIC CONCEPTS OF C++

2, the expression n*factorial (n-1) must be evaluated; causing a call to


factorial (2).

2. factorial (2) is being evaluated: n is still not smaller than 2, so, again,
n*factorial (n-1) is evaluated, leading to a call to factorial (1).

3. factorial (1) is evaluated: n is less than 2, so the call to factorial (1)


returns 1; its frame will be popped from the stack and control will return to
factorial (2) .

4. factorial (2) is being evaluated: the call to factorial (1) returned 1


and thus factorial (2) returns 2*1=2; its frame will be popped and control
will return to factorial (3).

5. factorial (3) is being evaluated: the call to factorial (2) returned 2


and thus factorial (3) will returns 3 * 2 = 6; its frame will be popped and
control will return to the caller.

1.4.3 More on Parameter Passing


As explained in Section 1.4.2, the parameter expressions of a function call are evalu-
ated and the resulting values are copied to local parameter variables. We say that C++
supports call-by-value.
Sometimes however, one would like a function to have access to the original parameter
object (assuming that the parameter expression resulted in an lvalue) so that it can
change the contents of this parameter object.
This can be easily achieved by declaring the formal parameter variables to be refer-
ence variables, as illustrated by the following code fragment.

int x(3);
int y(4);

void
swap(int& a,int& b) {
int tmp(a);
a =
b;
b = tmp;
}

swap(x,y);

Note that

• The function swap does not have a return type. Consequently, its body does
not contain a return statement.

• Within the function, an extra local int variable (and corresponding object) tmp
is defined. Hence the frame corresponding to a call to swap will contain three
variables: a, b (the formal parameter variables) and tmp.
1.4. FUNCTIONS 11

• The fonna1 parameter variables are both of type int&, i.e. they contain refer-
ences to integers.

According to the mechanism described in Section 1.4.2, the fonnal parameters a and
b will be initialized using the parameter expressions x and y, which, incidently, both
yield 1values. But we know from Section 1.3 that reference variables such as a and b
are defined by binding them to the same object as the initializing expression. Hence a
will refer to the same object as x and b will refer to the same object as y, as illustrated
in Figure 1.7 which shows the situation just after the definition of the local tmp object.
After executing swap (x, y), the value of x will be 4 while the value ofy will be 3,
i.e. the call to swap (x, y) will have swapped (hence the name) the values of x and
y.

2010 3 int tmp


2006 1000 int& b } swapframe
2002 1004 int& a

1004 3 int x
1000 4 inty

Figure 1.7: Reference fonnal parameter.

Thus, declaring fonnal parameter variables to be of a reference type effectively results


in the passing of references to the parameter expressions (which should yield lvalues)
to the function. This method of passing parameters to functions is called call-by-
address: it is achieved naturally in C++ by combining the concepts of call-by-value
and reference types.
A similar mechanism can be used to make a function return an 1value, as in the next
example.

int x(10);
int y(23);

int&
max(int& a,int& b) {
if (a>b)
return a;
else
return b;
}

max(x,y) = 25;
12 CHAPTER 1. BASIC CONCEPTS OF C++

Because the return type of the function is of a reference type, the function call will
result in an lvalue to which a value can be assigned (Section 1.2). Specifically, e.g.
the statement return a will execute int&: tmp (a) , which initializes a temporary
object of type int&: to contain a reference to (the object) a. Note that, in the example,
both a and b are reference parameters, thus ensuring that e.g. the object referred to by
a in return a does not live in the function call frame and, consequently, still exists
after the function call returns.
If the function max would take value parameters, the function would return a reference
to a parameter object (a copy of the original) which doesn't exist any more at the time
of the assignment max (x, y) = 25, a sure recipe for disaster.

1.5 Program Structure


1.5.1 Translation Units, Definitions and Declarations
A C++ program consists of one or more translation units where a translation unit
corresponds to a source text file that can be processed by the compiler. In this book,
source text files will always have a name of the form filename. C where the • C
suffix indicates that the file contains C++ source code lS .
A translation unit consists of a sequence of declarations and definitions of types, vari-
ables and functions.
The difference between a declaration and a definition is that a declaration announces
the existence of a type, variable or function while a definition also defines it.
The syntax for a declaration is similar to the corresponding definition:

• A variable declaration is of the form

I extern NameOfType NameOfvariable;

where extern is a keyword (short for "external", i.e. "defined elsewhere").

• A function declaration is of the form

I ReturnType FunctionName(ParameterDeclarationList);

Thus a function declaration is like a function definition where the actual body
has been replaced by a semicolon "; ".

The fragment below contains declarations for a double variable pi and a function
circle_area (definitions and declarations for types will be discussed in Chapters 4
and 6).
150ther widely used suffixes for C++ source file names are • cc and • cpp.
1.5. PROGRAM STRUCTURE 13

extern double pi;


double circle_area(double radius);

Upon reading a definition, the compiler will fully "implement" the concept, i.e. it will

• allocate memory for a defined variable,

• generate code for a defined function,

• compute the detailed information, e.g. the size, of a defined type (note that,
contrary to the previous actions, processing a type definition does not have a
direct effect on the generated code).

In addition, the compiler will update its database so that when it next encounters the
name of the variable, function or type, it can react appropriately. On the other hand, a
declaration will only cause the compiler to enter the concept in its tables. The compiler
assumes that the concept will be defined elsewhere, e.g. in another translation unit, or
further on in the same translation unit.

1.5.2 The Compilation Process


The C++ compiler translates a source text file to an object file that contains machine
code for the functions and variables defined in the source text file. The name of the
object file is usually derived from the name of the source file. Under Linux or UNIX,
the object file produced by the compilation of filename. C is, by default, called
filename. o.
The following listing is a readable version of the object file factorial. 0 corre-
sponding to the source file for the factorial function on page 9.

factorial.o: file fonnat elf32-i386

Disassembly of section .text:

00000000 <factorial(int»:
0: 55 pushl %ebp
1: 89 e5 moyl %esp,%ebp
3: 83 7d 08 01 cmpl $Ox1,Ox8(%ebp)
7: 7f 09 jg 12 <factorial(int)+Ox12>
9: b8 01 00 00 00 moyl $Ox1,%eax
e: eb 24 jmp 34 <factorial(int)+Ox34 >
10: eb 1e jmp 30 <factorial(int)+Ox30>
12: 8b 45 08 moyl Ox8(%ebp),%eax
15: 48 decl %eax
16: 50 pushl %eax
17: e8 e4 ff ff ff call o <factorial(int»
1c: 83 c4 04 addl $Ox4,%esp
1f: 89 cO moyl %eax,%eax
21: 89 c2 moyl %eax,%edx
14 CHAPTER 1. BASIC CONCEPTS OF C++

23: Of af 55 08 imull Ox8(%ebp),%edx


27: 89 dO movl %edx,%eax
29: eb 09 jmp 34 <factorial(int)+Ox34 >
2b: 90 nop
2c: 8d 74 26 00 leal OxO(%esi,1 ),%esi
30: eb 02 jmp 34 <factorial(int)+Ox34 >
32: eb 00 jmp 34 <factorial(int)+Ox34 >
34: c9 leave
35: c3 ret

We notice that the code for the factorial function contains 53 (35 in hexadecimal
notation) bytes. At run-time, this code object will reside somewhere in memory and its
address is available to a C++ program via the name ofthe function (see Section 5.5).
The C++ compiler contains two modules that are organized in a "pipeline", as shown
in Figure 1.8.

C++ compiler

preprocessor compiler

Figure 1.8: C++ compiler architecture.

The preprocessor module (usually also available as a separate program called cccp
or cpp) reads the source text file and processes any directives it encounters in the
source text. Such directives are not passed on to the compiler proper; they can be
distinguished from ordinary C++ source text by the occurrence of a # character at the
beginning of a line.
The most important directives, for our purposes, are

#include "filename" This directive causes the preprocessor to process the file
called filename before continuing processing the current source text. Note
that filename may itself contain preprocessor directives (including #in-
clude directives).

#include <filename> Like the #include "filename" directive but the


preprocessor will also look in "standard" directories for filename.

#define VariableName Value This directive defines a compile-time variable


variableName and assigns to it the value Value which can be any text.
Value may be omitted, in which case the default value 1 will be assigned. If
variableName is defined, the preprocessor will replace any occurrence of a
1.5. PROGRAM STRUCTURE 15

variableName token with the current value of this variable 16 •

#ifdef VariableName ••• #endif If the variable VariableName has not


previously been defined, skip all text until the next matching #endi f directive
is encountered. (#ifdef .•• #endif directives may be nested.) If vari-
ableName is defined, continue processing as usual.

#ifndef VariableName ••• #endif This directive is the opposite of the


#ifdef .•• #endif directive: if the variable VariableName is defined,
skip all text until the next matching #endif directive. IfVariableName is
not defined, continue processing as usual.

1.5.3 Program Organization


All but the most trivial programs consist of many interdependent translation units. In
a well-designed program, each translation unit will export some services (type defini-
tions, functions or variables) that can be used by other units. In addition, a translation
unit will often contain extra auxiliary functions or variables that are used to help im-
plement the exported services.
By convention, all variables and functions from a translation unit that are also used
outside of the translation unit are declared in a corresponding header file. In addition,
such a header file may also contain type definitions; this is necessary because e.g.
in order to properly process the definition of a variable of type T, the compiler must
know the exact size of an object of type T, so that it can allocate the necessary amount
of memory for this variable.
Such a file can be included (using an #include preprocessor directive) from another
translation unit. In this way, the declarations and type definitions are kept in one place
only and there is no possibility of inconsistencies. Furthermore, one should always
include the header file in the source file that defines the concepts of the header file.
This will force the compiler to first process the declarations (from the header file)
before processing the definitions. Any inconsistencies between the declarations and
the corresponding definitions will thus be detected automatically by the compiler.
We illustrate the above by a program that consists of three translation units; two of
which have an associated header file:

• The source file pi. C contains the definition of a double variable pi. The file
pi. h contains the corresponding declaration.

• The source file circle. C contains the definition of two functions, cir-
cle_area and circle_circumference. The corresponding declarations
can be found in the header file circle. h.

• The source file progl. C contains the definition of a single function main.
There is no corresponding header file.
16 As a matter of fact, the preprocessor is a full, but not very sophisticated, macro processor. However,
using this facility tends to make source text less understandable and is therefore discouraged.
16 CHAPTER 1. BASIC CONCEPTS OF C++

The file pi . C is shown below.

#include "pi. h"


double pi(3.14);

Note the line # inc 1 ude "pi. h": this will cause the compiler to include the text
of the header file pi. h in the source text at that point. If we made the mistake of
declaring pi as an integer variable in pi. h the compiler would complain with a
message explaining the inconsistency of the declaration with the definition

pi.C:3: conflicting types for 'double pi'


pi.h:3: previous declaration as 'int pi'

The header file pi . h is shown next.

#ifndef PLH
#define PLH
extern double pi;
#endif

The preprocessor directives

#ifndef PI...H
#def ine PI...H

#endif

are typical for the structure of a header file: the first line #ifndef PI...H will cause
the preprocessor to check whether the compile-time variable PI...H is defined. If so,
all following lines will be skipped until a matching #endi f directive is found. If,
however, PI...H is not defined, then the following lines are processed. In that case,
the next line #define PI...H defines the variable PI...H by setting its value to 1.
The overall effect is that, when compiling a translation unit, the declarations or type
definitions of the file pi . h will be processed at most once, even if the header file
pi.h is included many times (since #include directives may be nested, it may
be unavoidable that the same header file is included more than once, e.g. from other
different header files). Hence any type definitions in the header file are processed only
once by the compiler (defining the same type twice will cause the compiler to generate
an error, even if both definitions are identical).
The file circle. C contains the definitions of two functions, circle_area and
circle_circumference.

#include "pi.h"
#include "circle. h"
double
circle_circumference(double radius) {
return 2 * pi * radius;
}
1.5. PROGRAM STRUCTURE 17

double
circle_area(double radius) {
return pi * radius * radius;
}

The header file circle. h contains the corresponding declarations.

#ifndef CIRCLE_H
#define CIRCLE_H
double circle_circumference(double radius);
double circle_area(double radius);
#endif

Finally, the file progl. C contains the definition of a single function called main.

#include "circle.h"

int
mainO {
double r(3.5);
circle_area(r);
return 0;
}

Every program must have exactly one such function in some translation unit: when
starting the program, the system will simply perform a function call to the function
main; as soon as this call is finished, the program will exit with a return code that
equals the value returned by the main function. The main function may return any
int value but, by convention, a value of 0 means that the program's execution was
successful, i.e. without errors, while any other return value indicates an error. Note
that this convention makes sense: there may be many reasons why the execution of
a program fails and the programmer can choose a particular return value to represent
each of them separately: e.g. 1 can be used to indicate that some input value was
illegal while 2 can be used to signal that the program ran out of memory, etc.

1.5.4 Linking and Executing a Program


Once all translation units (source text files) constituting the program have been com-
piled, one still needs to combine the corresponding object files into a single executable
file. This is done by the linker, as illustrated in Figure 1.9 for the example program
from Section 1.5.3.
In Figure 1.9, the object files are annotated with the (variable or function name) sym-
bols they either define (indicated by a "!") or require but do not define (indicated by a
"?"). The latter kind of symbols are called unresolved symbols.
It is the job of the linker to resolve all references to unresolved symbols by finding
their definitions (addresses) in one of the supplied object files. In addition, the linker
18 CHAPTER 1. BASIC CONCEPTS OF C++

circle.o
! circle_circumference
! circle_area
? pi

pi.o prog

! pi
H linker r----- ! main
! circle circumference
! circle=:area
! pi
progl.o

! main
? circle_area

Figure 1.9: The linking process.

will also relocate the code in the object files such that the different (code or data)
objects do not overlap in the executable file.
As an example, the following listing shows a fragment of the progl . 0 object file.

00000000 <main>:
0: 55 pushl %ebp

1a: dd 1c 24 fstpl (%esp,1 )


1d: e8 fc ff ff ff call 1e <main+Ox1e>

Here is the same fragment after linking:

08048710 <main>:
8048710: 55 pushl %ebp

804872a: dd 1c 24 fstpl (%esp,1 )


804872d: e8 36 00 00 00 call 8048768 <circle_area(double»

08048768 <circle_area(double»:
8048768: 55 pushl %ebp

Note that the correct address of the circle_area code object has been filled in and
that the address of the main function has changed from 0 to 8048710 hex.
1.6. SYNTACTIC AND LEXICAL CONSIDERATIONS 19

1.6 Syntactic and Lexical Considerations


1.6.1 Identifiers and Keywords
As mentioned in Section 1.5.1, a translation unit consists of definitions and declara-
tions of user-defined types, variables and functions. These concepts must be named
using identifiers. In C++, an identifier is a string starting with a letter or underscore
(_) 17, followed by any number of letters, digits or underscores. Moreover the identifier
should not be one of a fixed number of strings, called keywords which are reserved as
part of the C++ language: they have a fixed meaning which cannot be changed by the
programmer. Table 1.11ists all keywords.

asm do inline short typeid


auto double int signed typename
bool dynamic_cast long sizeof union
break else mutable static unsigned
case enum namespace static_cast using
catch explicit new struct virtual
char extern operator switch void
class false private template volatile
const float protected this wchar_t
consLcast for public throw while
continue friend register true
default goto reinterpreLcast try
delete if return typedef

Table 1.1: C++ keywords.

Thus http_request_1 is a correct identifier while 1st_request and error!


are not legal identifiers. Identifiers (but not keywords) are case sensitive, so Student
and student are considered to be different.
To make a program readable (and understandable), it is very important to choose good
names (identifiers). A good name conveys the meaning ofthe concept that the identi-
fier denotes. E.g. student is a better name for a variable than s. If you cannot find
a good name for something, chances are that you do not understand the concept the
name is supposed to stand for.
To further enhance readability, it is good practice to stick to a naming convention
regarding the use of upperllower case letters and underscores. In this book we use the
following naming conventions:

• Types have a name that starts with a capital letter. If the name contains several
words, we capitalize the first letter of each word. E.g.

HttpRequest, Student
17It is not recommended, however, to start an identifier with an underscore since the compiler may gen-
erate extra symbols starting with one or several underscores; thus possibly causing a conflict.
20 CHAPTER 1. BASIC CONCEPTS OF C++

• Variables and functions have a name that starts with a lower case letter. If the
name contains several words, we use underscores to separate them. E.g.

student, sample_size, notify_server

• Constant (see Section 5.1) names are all upper case, with underscores separating
constituent words. E.g.

1.6.2 Comments
Even with well-chosen names, the purpose of a piece of source code may not be
obvious. That is why it is imperative to liberally sprinkle comments in the source
text. Comments are thus documentation text that is added to the source code.
Syntactically, the C++ compiler ignores

• any text that follows" / !" until the end of the line, and

• any text between "/ *" and "* /".

Usually, only the first possibility is used; the second option is reserved for temporarily
"commenting out" a block of code, e.g. for debugging purposes.
As a minimum, each non-trivial definition should be preceded by a comment stating
the purpose of the various aspects of the definition. For a function, this can be fur-
ther enriched by specifying the pre- and postconditions associated with the function.
Moreover, each source text file should start with a comment detailing its author(s),
modification history and other administrative data 18 .
The sample below shows a fragment of a well-documented header file.

#define ERR_H
// $Id: err.h,v 1.5 2001/02/28 12:47:02 dvermeir Exp $
// Error message & error exit routines.
void err_msg(const char* fonnat, ... );
// Like fprintf(stderr, . .).
void err_exit(int status,const char *fonnat, ... );
// Like printf(. .), precedes printing by "Fatal error: "; follows printing by \n;
// also prints message associated with last system error (errno), which mayor may
// not be useful. Never returns (calls exit(status)).
void err_abort(const char *fonnat, ... );
// Use this if you want a core dump (abort()), in addition to the functionality of err_exit().
#endif

A common mistake is to insert comments that do not add anything to the understanding
of the code, as illustrated in the following fragment.
18 Such infonnation can be easily inserted and automatically maintained using a source code control
system such as cvs.
1.7. SCOPES AND NAMESPACES 21

II this function computes the maximum of two integers


int
maximum(int x,int y) {
if (x>y) II x is larger than y, so return x
return x;
else II x is not larger than y, so return y
return y;
}

A major problem with comments is that, as the code evolves, because of bug fixes or
changes to its functionality, the comments are not updated, e.g. because of laziness or
time pressure. This should be avoided at all cost: it is better not to have comments
than to have comments that are inconsistent with the code.

1.7 Scopes and Namespaces

1.7.1 Scopes

In C++, the collection of all identifiers used in a program is not a flat set where every
name must uniquely identify one concept. This would be unacceptable since large
programs may contain tens of thousands of concepts and it would be a nightmare to
ensure that they all have different names.
Instead, names are organized in scopes where a scope can be thought of as a piece of
source text wherein names must be unique. The same identifier can be used to mean
different things in different scopes.
Scopes can be nested, so a fragment of source text can belong to many different scopes.
A particular occurrence of an identifier must then be interpreted using the meaning it
has in the most closely nested scope to which it belongs.
Most scopes are established as a side effect of a definition. E.g. a function definition
(see Section 3.3) defines a scope encompassing the whole definition, as shown in
Figure 1.10.
There are two definitions of the identifier x in this fragment; there is no conflict be-
cause the definitions are in different scopes: in the global (encompassing) scope x is a
double variable, while in the local scope, which corresponds to the definition of the
function f, x denotes an in t variable. The meaning of the other occurrences of x can
be easily determined using the "most closely nested scope" rule: the "a" occurrence
lies in the function scope and thus it refers to the int variable. The "b" occurrence
is in the outer scope and therefore refers to the double variable. On the other hand,
since the function definition does not redefine z, both uses of z refer to the double
variable in the global scope.
22 CHAPTER 1. BASIC CONCEPTS OF C++

global scope
x is double

z =f(3) + x;
b

Figure 1.10: Nested scopes.

1.7.2 Namespaces
Namespaces are explicitly defined scopes: a definition of the form

namespace OptionalNamespaceName {
SourceCode
}

will create a named scope containing all names declared in SourceCode l9 • Like
scopes, namespaces can be nested.

namespace A {
int x;
namespace C {
int x;
}
}
namespace B {
int x;
}
int
mainO {
int z(2);
z = x;
}

The above code defines three namespaces A and Band C: A contains two names: x
and C; Band C just contain x. With the nameless scope associated with the function
19The name is optional; if it is omitted, the system will generate a unique name for the namespace. This
makes such namespaces practically unaccessible from outside. However, as an exception, the names defined
in such an unnamed namespace are still accessible from the translation unit where they are defined.
1.7. SCOPES AND NAMESPACES 23

definition, this yields a scope structure as in Figure 1.11. The statement z = x will

global scope l
Ai ~
x ~

Cb
_ - scope of function definition

l z J
Figure 1.11: Namespaces.

cause the compiler to complain about x not being declared. Indeed, the function
definition scope where the statement appears does not contain a declaration of a name
x. On the other hand, the only encompassing scope, that is the global scope, does
not contain a declaration of x either. Consequently, no x is visible from within the
function definition scope.
To fix the problem we can use the scope resolution operator (": : "): if Scope refers to
a scope then

Scope: : name

refers to the name contained in Scope. Thus, we can make the statement z = x refer
to the x defined in C by writing
z = A::C::x;

instead. The expression A: : C: : x in the function definition scope is processed by


searching for the most closely nested scope where the name A is defined. This yields
the global scope 80 where A refers to another scope (namespace) 81 of that name. Next
we search 81 for the following component C of the expression; this yields another
scope 82 corresponding to the namespace C defined within A. Finally, 82 is examined
for a declaration of x.
The search for the most closely nested subscope containing the first name in the ex-
pression can be bypassed by writing an "absolute path" : : A: : C: : x. In this case,
the search will immediately start in the global scope where the name A must be found,
etc.
A using declaration imports a name from another scope:

I using Scope: : name; I


makes name from Scope visible in the current scope. E.g. in the example, we can
write
using A:: C:: x;
z = x;
24 CHAPTER 1. BASIC CONCEPTS OF C++

instead of z = A::C::x.
It is also possible to import all the names of a namespace with a using directive:

I using namespace NameSpace; I


will make all names declared in Namespace visible in the current scope.
All components of the C++ standard library are contained within anamespace : : std;
hence, many programs will contain a clause
using namespace std;

to make these facilities available in the current scope20 .


Namespaces are extendible, as shown in the following example.

namespace A {
namespace C {
extern int x; II only a declaration
}
}
namespace B {
int x;
}

int A::C::x; II definition of name "x" declared in ::A::C

namespace A { II continuation of namespace A


int x;
}

int
mainO {
int z(2);
using namespace A::C;
z = x;
}

In the above code, the namespace A initially just contains a nested namespace C but is
later extended to also contain x. Also, A: : C: : x is only declared, not defined, within
the namespace A: : C. The subsequent definition
int A:: C:: x;

refers explicitly to the x declared within A: : C.

20 Some compilers, including the one used in this book, silently assume such a using directive.
Chapter 2

Built-in Types

2.1 Arithmetic Types


C++ supports the following fundamental types which correspond closely to hardware
facilities. For all such types, it is possible to use literal constants to represent a value
of this type.

int An object of this type represents an integer. An object of type int has a size
which is "convenient" for the underlying hardware (typically 32 bits). Integer
literals are written in the usual notation, e.g. 3241, 0, -123. Integer constants
can also be written in hexadecimal notation: simply prefix the hexadecimal
number with "Ox", as in Oxffff of Oxl00aSfff. Furthermore, any integer
literal that starts with "0" is considered to be in octal notation: 010 = S.

short An object of this type also represents an integer, but its size is typically smaller
than the size of into E.g. on 32-bit machines, a short may be 16 bits. Short
constants are written as normal integer constants.

long This is also an integer type but its size may exceed the size of an into Long
integer constants consist of an integer constant optionally followed by a suffix
"L". E.g. the constant 255L will be treated as a long integer by the compiler,
although a short object would suffice to hold it (if no suffix is used, the com-
piler will automatically determine a suitable type for an integer constant).

double A double object represents a double-precision floating point (i.e. real) num-
ber. Besides the usual notation, e.g. -1. 23,3.14, double literals can also
be written in scientific notation, e.g. 4. 23E12 for 4.23 x 10 12 or O. 67E-5
for 0.67 x 10- 5 . A double object usually takes 64 bits.

long double A long double object represents an extended-precision floating point


number. On a 32-bit machine, it usually takes 96 bits.

25
26 CHAPTER 2. BUILT-IN TYPES

float A float object represents a single-precision floating point number. Its size
does not exceed the size of a double. To write a float literal, simply use
a double literal immediately followed by the letter "F" (or "f"): 4. 23f,
o .13E-3F.
boot An object of this type represents a boolean value. There are two boolean literals
representing the classical truth values using the keywords true and false.
Internally, true and false are represent by the integer values 1 and 0, re-
spectively.

char A char object represents a letter in some standard encoding alphabet, usually
ASCII. The size of a char object is almost always 8 bits, i.e. a single byte.
Character constants are written between single quotes, e.g. ' a " , 0 ' , etc. In
addition, one can use the underlying integer to represent a character with that
code: simply write ' \x' where X is a number in octal notation, or ' \xY'
where Y is a number in hexadecimal notation. E.g. ' \12' and' \xa' both
represent the newline character (with decimal code 10). In addition, there are
some standard names to represent certain characters, as shown in Table 2.1.

Name I ASCII (decimal) I C++ constant I


newline 10 '\n'
horizontal tab 41 ,\t'
carriage return 13 '\r'
backslash 92 ,\\,
vertical tab 11 '\v'
backspace 8 ' \b'
form feed 12 '\f'
alert (bell) 7 '\a'
single quote 39 ' \ I ,

double quote 34 ' \ II'

Table 2.1: Special character constants.

wchar _t The wchar _t (wide character) type is used to represent chars from a larger
character set such as unicode. A wide character constant is of the form L' s '
where s is a sequence of characters. The size of s and its meaning are implemen-
tation dependent.

For each of the integer types (int, short, long), there is an unsigned variant which
interprets the same storage area as the original type as an unsigned number. These un-
signed variants are obtained by prefixing the original type name with the "unsigned"
keyword: unsigned short, unsigned intI and unsigned long. The ex-
tra bit, which is otherwise used for representing the sign, doubles the size of the
largest number that can be represented. E.g. if the size of a short integer is 16
1Actually, unsigned int may be abbreviated as unsigned.
2.2. CONVERSIONS FOR ARITHMETIC TYPES 27

bits; it can represent any integer in the [-32768 ... 32767] interval. The range of
unsigned short then becomes [0 ... 65535] (note that both ranges contain ex-
actly 216 = 65536 integer numbers). For 32-bit int values, the ranges become
[-2147483648 ... 2147483647] and [0 ... 4294967295].
The integer types, as well as the bool, char and wchar _t types, are called inte-
gral types because their underlying implementation is an integer number. All integral
types, as well as the floating point types support the usual arithmetic operations. Such
types are also called arithmetic types. The various categories of primitive types are
shown in Figure 2.1.

arithmetic types
integral types
integer types floating point types
int float
unsigned int double
short long double
unsigned short
long
unsigned long

char
unsigned char
signed char
bool

Figure 2.1: Primitive types.

2.2 Conversions for Arithmetic Types


Consider the variable definitions below:

long I( , a ,); / / char fits into I. no problem; I will be 97, the ascii code for 'a'
int i(3.14); / / compiler will generate a warning; i will be 3

The first line defines a long object 1 which is initialized from a char value I a I •
Although the types of the value (a char) and the receiving object (a long) do not
match, the compiler will not complain because it is able to convert a char value to
a long value without loss of information. Indeed, since both char and long are
integral types, and the size of a char certainly does not exceed that of a long, such a
conversion can easily be performed and, consequently, the compiler will not complain
about it.
28 CHAPTER 2. BUILT-IN TYPES

The second line is a different matter: here we initialize an int object i with a dou-
ble value 3.14 and there is no way that we can accurately convert this value to an
into Hence the compiler \lIill give a warning

warning: initialization to 'int' from 'double'

It will however not generate an error; instead it will simply do its best to approximate
(actually truncate) 3.14 by an int value. This will result in i being initialized to 3.
In general, for a definition or an assignment that attempts to store a value of an arith-
metic type tl into an object of a different arithmetic type t2, the compiler will do the
following:

1. If it is possible to convert a tl value to a t2 value without loss of information,


then it will silently do so and use the converted value to perform the initialization
or assignment.
2. Otherwise, a lossy conversion is still possible (both tl and t2 are arithmetic
types). The compiler will do this conversion and use the resulting t2 value but
it will also generate a warning.

Most conversions are as expected, e.g. converting a floating point type to an integral
type involves truncation. Converting a larger type to a smaller one (e.g. an unsigned
long to an int) may give strange results. Conversion to a bool will yield false
for a source value of 0 while any other value will yield true.
A different problem arises with expressions containing (references to) values of dif-
ferent arithmetic types, as in the example below.

double d(0.5);
float [(0.6);
int itO);

i = d + [; II i will become 1

Here the resulting value of i will be 1: the compiler will first convert, without loss of
information, the value of f to a double, then compute the expression, yielding 1.1,
and then convert the result to an into
In general, for an arithmetic operation involving values of different arithmetic types,
the compiler will figure out the most appropriate type t to perform the computation
without information loss. All operands will be promoted (converted) to t and the
operation is performed. The result may then be further converted, e.g. to fit it into a
receiving object.

2.3 Arithmetic Type Operations


The C++ syntax defines a number of operators, which are denoted by special char-
acter combinations such as "&&" or by keywords. The operation corresponding to an
2.3. ARITHMETIC TYPE OPERATIONS 29

operator can be thought of as a function. E.g. the "logical and" operation, denoted
"&:&:", can be considered a function

&:&: : bool x bool -t bool

The corresponding C++ function declaration for such operator functions can be writ-
ten as follows:

bool operator&:&:(bool,bool);

As a matter of fact, C++ allows the programmer to define her own implementation
for many operators on user-defined types using a syntax like the one above, see Sec-
tion 4.2.12, page 63.
The following operations are defined for arithmetic types.

• The simple binary arithmetic operations: addition (+), subtraction (-), mul-
tiplication (*) and division (I). Note that, due to conversions (Section 2.2),
expressions may contain values of different types, e.g. 0 • 5 * true + ' a '
is legal and will result in a double value.

• The % operator computes the remainder of the integral division of the first
operand by the second: e.g. 7 % 2 returns 1. The % operator does not work on
floating point types.

• The usual binary comparison operators, which return a bool value:

a1 == a2 a1 is equal to a2
a1 != a2 a1 is not equal to a2
a1 < a2 a1 is strictly smaller than a2
a1 > a2 a1 is strictly greater than a2
a1 <= a2 a1 is not greater than a2
a1 >= a2 a1 is not smaller than a2

• Several operators manipulate the underlying bit pattern of integral type objects:
- The binary operator« shifts the bits in the first operand to the left by the
number of positions indicated by the second operand (the open positions
will be filled by 0). E.g. 1 « 10 will yield 1024, i.e. 210.
- The binary operator » shifts the bits in the first operand to the right by
the number of positions indicated by the second operand. E.g. 1025 »
1 0 will yield 1.
- The bitwise complement operator (-) will replace each 0 by a 1 and each
1 by a O. E.g. -0 will yield -1, assuming int objects are represented
using 2's complement notation.
- The &: operator can be used to perform a "bitwise and" operation on its
operands: x&:4 will be different from 0 iff x has its third bit set.
Similarly, I and ~ perform bitwise or and bitwise xor (exclusive or).
30 CHAPTER 2. BUILT-IN TYPES

• The following boolean connectives are available: ! represents logical "not"


while &:&: and I I represent logical "and" and logical "or", respectively. Note
that appropriate conversions to bool may happen; e.g. O. 5 &:&: ! 0 will re-
turn true .

• The« and» operators are overloaded (see Sections 3.2 and 4.2.12): besides
the bitshift operations (page 29), they also have a definition as input/output op-
erators: for an arithmetic value a,

out « a

will write a to the output stream ou t, while, for an lvalue la of some arithmetic
typeT

in » la
will attempt to read a value of type T into the object referred to by la. Note that
this interpretation of « and » is not part of the language proper. It is provided
by the standard iostream library (Chapter 10), e.g. by the definition of functions
like

ostream& operator«(ostream&,int);

where ostream is a (class) type defined in the iostream library representing


an output stream, or

istream& operator»(istream&,char&);
where istream is a (class) type, also defined in the iostream library, repre-
senting an input stream.
The iostream library provides some standard stream objects: cout is an 0-
stream that represents the UNIX standard output. Standard input is available
as an istream object cin while cerr is another ostream representing
standard error.
Note that the « and » 110 operations take a reference to a stream and return
a reference to a stream. The fact that the stream is passed by reference should
not be surprising since the alternative call-by-value (see Section 1.4.3) would
involve copying a stream. The return value is actually a reference to the same
stream as the parameter stream. Together with the associativity of the « and
» operators, this allows for expressions like

cout « 123 « ' , « 3.14;

which is interpreted as indicated by the parentheses in

«cout « 123) « ' ') « 3.14;


i.e. first 123 is output on standard output, the result is (a reference to) the same
output stream, to which' , is written, again resulting in a reference to standard
output on which 3 • 14 is written.
2.3. ARITHMETIC TYPE OPERATIONS 31

• The increment operator ++ comes in two flavours: the prefix version ++la adds
1 to its single lvalue operand la and then returns the new value of lao The post-
fix version la++ also increments its lvalue operand la, but returns the original
(before the increment) value of this operand. The decrement operator - - is sim-
ilar to ++, the difference being that in both the prefix and postfix versions 1 is
subtracted from its argument.

• The simple assignment operator= is as described in Section 1.2. An assignment


also returns a value (T stands for any arithmetic type):

T& operator=(T& la,T a);

copies a to (the object referred to by) the lvalue la but also returns a reference
to lao Because of this, one can write e.g.

x = y = z = 0;

which, due to the associativity of the = operator, will be interpreted as

x = ( y = ( z = 0»;

i.e. z will be set to 0, then y will be set to (the value of) z, and, finally, x will
be set to (the value of) y. The net result is that x, yand z are all set to o.

• Often assignments are of the form

where another binary operator, instead of +, could have been used. This can be
abbreviated by using a compound assignment operator which better expresses
the programmer's intention (increment the value of x by an amount a):

X += a

Compound assignment operators exist for several binary operators: *=, 1=, %=,
+ =, -=, < < =, > > =, & =, I =and =. The type of a compound assignment operation
A

for a type T is

T& operator+=(T& la,T a);

Like an ordinary assignment, a compound assignment expression returns a ref-


erence to the receiving lvalue:

x = y *= 2;
will store the new value of y in the object x.

• The sizeof operator is actually defined on values of any type. It returns the
size, in bytes, of its arguments. In addition, one can also write sizeof (T)
where T is the name of a (built-in or user-defined) type; in that case the size (in
bytes) of an object of that type is returned. E.g. sizeof (long double)
returns 12 on a typical (early 2000) Linux notebook system.
32 CHAPTER 2. BUILT-IN TYPES

• For any type T, the notation T (a) , where a represents some value, denotes the
construction of a T-value out of a. The operator T () is called a value construc-
tor. This is very useful for user-defined types, for which the programmer can
define arbitrary constructor/initialization functions, see Section 4.2.7.
For built-in types, the operator is less useful: the only reasonable way to initial-
ize e.g. an integer is by giving it the value of another integer, as in int (34) .
One would expect that the value constructor operator could also be used to ex-
plicitly request a conversion, as in int (100.23) and indeed, this works in
most cases. Unfortunately, the compiler may2, when interpreting such an ex-
pression T (a) where T is a built-in type and a does not have the same size as
T, rudely truncate a to the size of T. E.g.

cout « short(100000000.0f);

prints -7936 3 . Still, the operator is useful when the construction of the T-
value is well-defined, e.g. when converting from integers to enumeration types,
see Section 4.3.
The value constructor operator may also be used without arguments: T () re-
turns the default value of the type T, see Section 4.2.7.

The relative precedence of the above operators is shown, in decreasing order, in Ta-
ble 2.2 where operators with the same precedence appear in the same "box".

2.4 String Literals


String literals, denoted by a string of characters enclosed by double quotes, are also
recognized by the C++ compiler. E.g.

"hello world"

will cause the compiler to allocate a data object containing a consecutive sequence of
characters, i.e. an array of char objects as shown in Figure 2.2.
Note that the double quotes surrounding the text are not present. Also, there is one
extra char at the end which contains a zero character (denoted I \ 0 I according to the
rules on page 26). Such objects are often called C strings because they were inherited
from the C language4 •

2This is not a requirement; e.g. g++, the gnu C++ compiler, seems to do a decent job in trying to do
reasonable conversions in all cases we tested.
3This behaviour is reminiscent of the C-style cast:
cout« (short)(lOOOOOOOO.Of);

4Por most applications, the C++ class type string provides a safer and more powerful alternative to
C strings.
2.4. STRING LITERALS 33

Operator Function Example Remark


type () value construction double ( 'e')
++ post increment la++ Ivalue only
-- post decrement la-- Ivalue only
sizeofO size of object or type sizeof(a) or sizeof (double)
++ pre increment ++la Ivalue only

--- pre decrement --la type Ivalue only


bitwise complement -i integral type only
! logical not !a
- unary minus -a
+ unary plus +a
* multiplication a*a
I division ala
% modulo (remainder) i %i integral types only
+ addition a+a
- subtraction a-a
« shift left i «j integral types only
« output to stream eout« a
» shift right i» j integral types only
» input from stream ein » la to Ivalue only
< less than a<a
<= less than or equal to a <= a
> greater than a>a
>= greater than or equal to a >= a
== equal to a == a
!= not equal to a! = a
& bitwise and i &j integral types only
~

bitwise xor i~j integral types only


1 bitwise or i Ij integral types only
&& logical and i&&j
II logical or i II j
= assign la = a left operand must be Ivalue
*= mUltiply and assign la *= a
1= divide and assign la 1= a
%= modulo and assign la %= a
+= add and assign la += a
-= subtract and assign la -= a
«= shift left and assign li «= i integral types only
»= shift right and assign Ii »= i integral types only
&= bitwise "and" and assign li &= i integral types only
1= bitwise "or" and assign Ii I = i integral types only
~

= bitwise "xor" and assign li ~= i integral types only

Table 2.2: Precedence, in decreasing order, of operators for arithmetic types.


34 CHAPTER 2. BUILT-IN TYPES

o 1008 1011 1019

"hello world" returns


a pointer to an array of constant characters

const char*

Figure 2.2: A string literal.

It is possible to split a single literal over several strings written one after the other. E.g.

"hello " "world"

is equivalent to the example above.


A string literal is an expression; its value is however not the data object described
above but rather the address of this object. In fact, the type of the expression is cons t
char*, i.e. a pointer( *) to a constant (const) (array of) char, see Section 5.2.
For the moment, it is sufficient to know that const char* values can be written
to an output stream using the same overloaded operator as the one used for printing
arithmetic types: the function

ostream& operator«(ostream&,const char*);

is defined in the iostream library.


The following program contains a single main function (see Section 1.5.3) that prints
a line "hello world" to the standard output stream couto

#include <iostream>

int
mainO {
cout « "hello world\n";
}

Note the newline ( , \n ,) character embedded in the string literal: it ensures that the
cursor will go to the (beginning of the) next line on the screen.
To spread the output over two lines, one could either replace the space character after
"hello" by another ' \n' or one could simply spread the string literal over several
lines, as in the code below.
2.4. STRING LITERALS 35

#include <iostream>

int
main() {
cout« "hello
world

}
Random documents with unrelated
content Scribd suggests to you:
The Project Gutenberg eBook of Teresa of
Watling Street: A Fantasia on Modern Themes
This ebook is for the use of anyone anywhere in the United States
and most other parts of the world at no cost and with almost no
restrictions whatsoever. You may copy it, give it away or re-use it
under the terms of the Project Gutenberg License included with this
ebook or online at www.gutenberg.org. If you are not located in the
United States, you will have to check the laws of the country where
you are located before using this eBook.

Title: Teresa of Watling Street: A Fantasia on Modern Themes

Author: Arnold Bennett

Illustrator: Frank Gillett

Release date: July 15, 2017 [eBook #55114]


Most recently updated: October 23, 2024

Language: English

Credits: Produced by David Widger from page images generously


provided by the Internet Archive

*** START OF THE PROJECT GUTENBERG EBOOK TERESA OF


WATLING STREET: A FANTASIA ON MODERN THEMES ***
TERESA OF WATLING STREET
A Fantasia On Modern Themes
By Arnold Bennett
With Eight Illustrations By Frank Gillett
London: Chatto & Windum

1904
CONTENTS
TERESA OF WATLING STREET
CHAPTER I—THE BANK
CHAPTER II—THE CIRCUS
CHAPTER III—CHINK OF COINS
CHAPTER IV—MR. PUDDEPHATT
CHAPTER V—FIRE
CHAPTER VI—THE DESIRE FOR SILVER
CHAPTER VII—NOLAN
CHAPTER VIII—THE PEER’S ADVICE
CHAPTER IX—A VISIT
CHAPTER X—MONEY-MAKING
CHAPTER XI—END OF THE NIGHT
CHAPTER XII—THE NAPOLEON
CHAPTER XIII—THE VASE
CHAPTER XIV—FEATHERSTONE’S RECITAL
CHAPTER XV—ARRIVAL OF SIMON
CHAPTER XVI—THE INTERVIEW
CHAPTER XVII—THE CLOSE
TERESA OF WATLING STREET
CHAPTER I—THE BANK

S
ince money is the fount of all modern romantic adventure, the
City of London, which holds more money to the square yard
than any other place in the world, is the most romantic of
cities. This is a profound truth, but people will not recognise it.
There is no more prosaic person than your bank clerk, who ladles
out romance from nine to four with a copper trowel without knowing
it. There is no more prosaic building than your stone-faced banking
office, which hums with romance all day, and never guesses what a
palace of wonders it is. The truth, however, remains; and some time
in the future it will be universally admitted. And if the City, as a
whole, is romantic, its banks are doubly and trebly romantic. Nothing
is more marvellous than the rapid growth of our banking system,
which is twice as great now as it was twenty years ago—and it was
great enough then.
Such were the reflections of a young man who, on a June
morning, stood motionless on the busy pavement opposite the
headquarters of the British and Scottish Banking Company, Limited,
in King William Street, City. He was a man of medium size, fair, thick-
set, well-dressed, and wearing gold-rimmed spectacles. The casual
observer might have taken him for a superior sort of clerk, but the
perfect style of his boots, his gloves, and his hat precluded such a
possibility; it is in the second-rate finish of his extremities that the
superior clerk, often gorgeous in a new frock-coat, betrays himself.
This particular young man, the tenor of whose thoughts showed that
he possessed imagination—the rarest of all qualities except honesty
—had once been a clerk, but he was a clerk no longer.
He looked at his watch; it showed three minutes to twelve o’clock.
He waited another minute, and then crossed through the traffic and
entered the sober and forbidding portals of the bank. He had never
before been inside a City bank, and the animated scene, to which
many glass partitions gave an air of mystery, would have bewildered
him had he not long since formed the immutable habit of never
allowing himself to be bewildered. Ignoring all the bustle which
centred round the various cash desks lettered A to F, G to M, and so
on, he turned unhesitatingly to an official who stood behind a little
solitary counter.
‘Sir?’ said the official blandly; it was his sole duty to be bland (and
firm) to customers and possible customers of an inquiring turn of
mind.
‘I have an appointment with Mr. Simon Lock,’ said the young man.
The official intensified his blandness at the mention of the august
name of the chairman of the British and Scottish Banking Company,
Limited.
‘Mr. Lock is engaged with the Board,’ he said.
‘I have an appointment with the Board,’ said the young man. ‘My
card;’ and he produced the pasteboard of civilization.
The official read:
Mr. Richard Redgrave, M.A.,
Specialist.
‘In that case,’ said the official, now a miracle of blandness, ‘be
good enough to step this way.’ Mr. Richard Redgrave stepped that
way, and presently found himself in front of a mahogany door, on
which was painted the legend, ‘Directors’ Parlour’—not ‘Board Room,’
but ‘Directors’ Parlour.’ The British and Scottish was not an ancient
corporation with a century or two of traditions; it was merely a joint-
stock company some thirty years of age. But it had prospered
exceedingly, and the directors, especially Mr. Simon Lock, liked to
seem quaint and old-fashioned in trifles. Such harmless affectations
helped to impress customers and to increase business. The official
knocked, and entered the parlour with as much solemnity as though
he had been entering a mosque or the tomb of Napoleon. Fifty
millions of deposits were manoeuvred from day to day in that
parlour, and the careers of eight hundred clerks depended on words
spoken therein. Then Mr. Richard Redgrave was invited to enter. His
foot sank into the deep pile of a Persian carpet. The official closed
the door. The specialist was alone with three of the directors of the
British and Scottish Bank.
‘Please take a seat, Redgrave,’ said Lord Dolmer, the only one of
the trio with whom Richard was personally acquainted, and to whom
he owed this introduction. ‘We shall not keep you waiting more than
a minute or two.’
The other directors did not look up. All three were rapidly signing
papers.
Richard occupied a chair upholstered in red leather, next the door,
and surveyed the room. It was a large and lofty apartment, simply
but massively furnished in mahogany. A table of superb solidity and
vast acreage filled the middle space—such a table as only a bank
director could comfortably sit at. As Richard gazed at that article of
furniture and listened to the busy scratching of pens, he saw, with
the prophetic vision characteristic of all men who are born to
success, that a crisis in his life was at hand. He had steadily risen
throughout his brief life, but he had never before risen so high as a
bank parlour, and the parlour of such a bank! His history, though a
short one, was curious. He came to London from Westmoreland at
the age of nineteen as a clerk in the Customs. From the first he
regarded his clerkship merely as a means to an end; what end he
had yet to ascertain. He paid particular attention to his clothes,
joined a large political club, and kept his eyes open. His personal
stock-in-trade consisted of a rather distinguished appearance, a
quiet, deliberate, and confident voice and manner, an imperturbable
good temper which nothing could affect, and a firm belief that he
could do anything a little better than the average doer of that thing.
He desired a University degree, and by working at night for four
years obtained the M.A. of London. He practised a little journalism of
the sensational kind, and did fairly well at that, but abandoned it
because the profits were not large enough. One Sunday he was
cycling down the Portsmouth Road, and had reached an hotel
between twenty and thirty miles from London, when he met with his
first real chance. A motor-tricycle had unaccountably disappeared
from the hotel during luncheon. The landlord and the owner of the
tricycle were arguing as to the former’s liability. Redgrave listened
discreetly, and then went to examine the barnlike coach-house from
which the motor-tricycle had been spirited away. Soon the owner,
who had instructed the police and bullied the landlord, and was now
forced to kick his angry heels till the departure of the afternoon train
back to London, joined him in the coach-house. The two began to
talk.
‘You are Lord Dolmer,’ said Redgrave at length.
‘How do you know that?’ asked the other quickly.
He was a black-haired man of forty, simply dressed, and of quiet
demeanour, save of unusual excitement.
‘I have seen you at the Constitutional Club, of which I am a
member. Did you know that a motor-tricycle disappeared from this
same hotel a fortnight ago?’
Lord Dolmer was impressed by the youth’s manner.
‘No,’ he said; ‘is that really so?’
‘Yes,’ said Redgrave, ‘only a fortnight ago. Strange coincidence,
isn’t it?’
‘Who are you? You seem to know something,’ said Lord Dolmer.
Redgrave gave his name, and added:
‘I am an officer in the Customs.’
That sounded well.
‘I fancy I could trace your tricycle, if you gave me time,’ he said.
‘I will give you not only time, but money,’ the peer replied.
‘We will talk about that later,’ said Redgrave.
Until that hour Richard had no thought of assuming the rôle of
detective or private inquiry agent; but he saw no reason why he
should not assume such a rôle, and with success. He calmly
determined to trace the missing tricycle. By a stroke of what is called
luck, he found it before Lord Dolmer’s train left. Over half of the
coach-house was a loft in the roof. Richard chanced to see a set of
pulleys in the rafters. He climbed up; the motor-tricycle was
concealed in the loft. The landlord, confronted with it, said that of
course some mischievous loiterers must have hoisted it into the loft
as a practical joke. The explanation was an obvious one, and Lord
Dolmer was obliged to accept it. But both he and Redgrave had the
gravest suspicions of the landlord, and it may be mentioned here
that the latter is now in prison, though not for any sin connected
with Lord Dolmer’s tricycle.
‘What do I owe you? Name your own sum,’ said Lord Dolmer to
Redgrave.
‘Nothing at all,’ Redgrave answered.
He had come to a resolution on the instant.
‘Give me some introductions to your friends.
It is the ambition of my life to conduct important private inquiries,
and you must know plenty of people who stand in need of such a
man as I.’
Lord Dolmer was poor—for a lord—and eked out a bare
competence by being a guinea-pig in the City, a perfectly respectable
and industrious guinea-pig. He agreed to Redgrave’s suggestion,
asked him to dinner at his chambers in Half Moon Street, and
became, in fact, friendly with the imperturbable and resourceful
young man. Redgrave obtained several delicate commissions, and
the result was such that in six months he abandoned his post in the
Customs, and rented a small office in Adelphi Terrace. His
acquaintance with Lord Dolmer continued, and when Lord Dolmer,
after a lucky day on the Exchange, bought a 5-h.p. motor-car, these
two went about the country together. Redgrave was soon able to
manage a motor-car like an expert, and foreseeing that motor-cars
would certainly acquire a high importance in the world, he cultivated
relations with the firm of manufacturers from whom Lord Dolman
had purchased his car. Then came a spell of ill-luck. The demand for
a private inquiry agent of exceptional ability (a ‘specialist,’ as Richard
described himself) seemed to die out. Richard had nothing to do,
and was on the point of turning his wits in another direction, when
he received a note from Lord Dolmer to the effect that Mr. Simon
Lock and the directors of the British and Scottish had some business
for him if he cared to undertake it.
Hence his advent in King William Street.
‘Let me introduce you,’ said Lord Dolmer, beckoning Redgrave
from his chair near the door, ‘to our chairman, Mr. Simon Lock,
whose name is doubtless familiar to you, and to my co-director, Sir
Charles Custer.’
Redgrave bowed, and the two financiers nodded.
‘Take that chair, Mr. Redgrave,’ said Simon Lock, indicating a fourth
chair at the table.
Simon Lock, a middle-aged man with gray hair, glinting gray eyes,
a short moustache, and no beard, was one of the kings of finance.
He had the monarchical manner, modified by an occasional gruff
pleasantry. The British and Scottish was only one of various
undertakings in which he was interested; he was, for example, at
the head of a powerful group of Westralian mining companies, but
here, as in all the others, he was the undisputed master. When he
spoke Lord Dolmer and Sir Charles Custer held their tongues.
‘We have sent for you on Lord Dolmer’s recommendation—a very
hearty recommendation, I may say,’ Simon Lock began. ‘He tells us
that you have a particular partiality for motor-car cases’—Richard
returned Simon Lock’s faint smile—‘and so you ought to be specially
useful to us in our dilemma. I will explain the circumstance as simply
as possible. Will you make notes?’
‘I never write down these details,’ said Richard. ‘It is safer not to.
My memory is quite reliable.’
Simon Lock nodded twice quickly and resumed:
‘We have a branch at Kilburn, in the High Street, under the
managership of Mr. Raphael Craig. Mr. Craig has been in our service
for about twenty years. His age is fifty-five. He is a widower with
one daughter. He came to us from an Irish bank. Professionally, we
have no fault to find with him; but for many years past he has
chosen to live thirty-five miles from London, at a farmhouse between
the town of Dunstable and the village of Hockliffe, in Bedfordshire.
Dunstable, you may be aware, is on the old Roman road, Watling
Street, which runs to Chester. He used to go up to Bedfordshire only
at weekends, but of late years he has travelled between his country
home and London several times a week, often daily. He owns two or
three motor-cars, and has once been summoned and convicted for
furious driving. It is said that he can come to London by road from
Dunstable in sixty minutes. When he stays in London he sleeps over
the bank premises in the suite of rooms which we provide for him,
as for all our managers.’
‘You say you have no fault to find with Mr. Craig professionally,’
said Richard. ‘He does not, then, in any way neglect his duties?’
‘The reverse. He is an admirable servant, and our Kilburn branch is
one of the most lucrative of all our branches. Mr. Craig has built up a
wonderfully good business for us in that suburb. Let me continue.
Last year but one a relative of Mr. Craig’s, an uncle or something of
that sort, reputed to be crazy, died and left him a hundred thousand
pounds, chiefly, one heard, in new silver coins, which the old miser
had had a mania for collecting, and kept in his cellars like wine. The
strange thing is that Mr. Craig, thus made rich, did not resign his
position with us. Now, why should a man of large fortune trouble
himself with the cares of a comparatively unimportant bank
managership? That aspect of the case has struck us as somewhat
suspicious.’
‘Highly suspicious,’ murmured Sir Charles Custer, M.P., out of his
beard.
‘You naturally—shall I say?—resent eccentricity in any member of
your staff?’ said Richard sagaciously.
‘We do, Mr. Redgrave. In a bank, eccentricity is not wanted.
Further—another strange fact—a month ago the cashier of our
Kilburn branch, a mediocre but worthy servant named Featherstone,
a man of fifty, whose brains were insufficient to lift him beyond a
cashiership, and who, outside our bank, had no chance whatever of
getting a livelihood in this hard world, suddenly resigned. He would
give no reason for his resignation, nor could Mr. Craig give us any
reason for it. In the following week Featherstone committed suicide.
No doubt you saw the affair in the papers. The man’s books were
perfectly straight. He was a bachelor, and had no ties that the police
could discover. Such is the brief outline of the case. Have you any
questions to ask?’
Redgrave paused. When, from ignorance or any other cause, he
had nothing to say, he contrived to produce an excellent effect by
remaining silent and peering through his gold-rimmed spectacles.
‘Only one,’ he said. ‘What do you want to know?’
‘We don’t know what we want to know,’ said Simon Lock abruptly.
‘We want to know anything and everything. Our suspicions are too
vague to be formulated, but, as directors of a great financial
undertaking, we are bound to practise precautions. We do not desire
to dismiss Mr. Craig without a reason. Such a course would be unfair
—and unprofitable.’
‘May I define your position thus?’ said Redgrave. ‘You do not
precisely fear, but you perceive the possibility of, some scandal,
some revelations, which might harm the general reputation of the
bank. And therefore you wish to know, first, why Mr. Craig runs
about Watling Street so much on a motor-car; second, why, being
possessed of a hundred thousand pounds, he still cares to work for
you; and third, why this Featherstone killed himself.’
‘Just so,’ said Simon Lock, pleased.
‘Just so,’ echoed Sir Charles Custer.
Lord Dolmer gave his protégé a smile of satisfaction.
‘I will undertake to assuage your curiosity on these points,’
Redgrave said, with that air of serene confidence which came so
naturally to him.
‘And your fee?’ asked Simon Lock.
‘If I fail, nothing. If I succeed I shall present my bill in due course.’
‘When shall we hear from you?’
‘In not less than a month.’
That evening Richard strolled up the Edgware Road to Kilburn, and
looked at the exterior of the Kilburn branch of the British and
Scottish. It presented no feature in the least extraordinary. Richard
was less interested in the bank than in the road, the magnificent
artery which stretches, almost in a straight line, from the Marble
Arch to Chester. Truly the Roman builders of that road had a glorious
disregard of everything save direction. Up hill and down dale the
mighty Watling Street travels, but it never deviates. After sixty years
of disuse, it had resumed its old position as a great highway through
the magnificence of England. The cyclist and the motorist had
rediscovered it, rejuvenating its venerable inns, raising its venerable
dust, and generally giving new vitality to the leviathan after its long
sleep.
To Richard Redgrave it seemed the avenue of adventure and of
success. His imagination devoured the miles between Kilburn and
Dunstable, and he saw the solitary farmhouse of Raphael Craig,
bank manager, motorist, and inheritor of a hundred thousand
pounds in virgin silver coin.
CHAPTER II—THE CIRCUS

A
week later—and in the meantime he had been far from idle—
Richard Redgrave arrived in Dunstable. It was a warm,
sunshiny, sleepy day, such as suited that sleepy town, and
showed off its fine old church and fine old houses to perfection.
There is no theatre in Dunstable, no concert-hall, and nothing ever
excites this staid borough save a Parliamentary election or the
biennial visit of Bosco’s Circus.
On the morning of Richard’s arrival Dunstable was certainly
excited, and the occasion was Bosco, who, with his horses, camels,
elephants, lions, bears, acrobats, riders, trapezists, and pavilions,
had encamped in a large field to the south of the town. Along the
whole of its length Dunstable, which consists chiefly of houses built
on either side of Watling Street for a distance of about a mile and a
half, was happily perturbed by the appearance of Bosco’s gigantic,
unrivalled, and indescribable circus, which was announced to give
two performances, at two-thirty and at seven-thirty of the clock.
And, after all, a circus which travels with two hundred horses (chiefly
piebald and cream), and with a single tent capable of holding four
thousand people, is perhaps worthy to cause excitement.
Richard determined to patronize Mr. Bosco’s entertainment—he
thought he might pick up useful information in the crowd—and at
two-thirty he paid his shilling and passed up the gorgeous but
rickety steps into the pavilion.
A brass band was playing at its full power, but above the noise of
the trumpets could be heard the voice of the showman—not Bosco
himself, but an individual hired for his big voice—saying, ‘Step up,
ladies and gentlemen. Today happens to be the thirtieth anniversary
of our first visit to this town, and to celebrate the event we shall
present to you exactly the same performance as we had the honour
of presenting, by special command, to Her Majesty the Queen at
Windsor last year. Step up, step up, and see our great spectacle, the
Relief of Mafeking! See the talking horse! See Juana, the most
beautiful rider in the world! Step up!
Children half-price to morning performance only.’ The big voice
made precisely this speech every day of his life all over England.
The circus was well filled, and the audience enthusiastic. The
clowns had an enormous success. As for Richard, he was more
interested in Juana, the horsewoman. She was a tall and beautiful
girl, apparently of the Spanish type. She rode, in a strictly
conventional park riding costume, a superb strawberry-roan mare,
which at her command waltzed, circled, caracoled, and did
everything except stand on its head. Mare and rider were equally
graceful, equally calm and self-contained. It was a charming item in
the programme, but somewhat over the heads of the audience, save
a few who knew a born rider when they saw one. An elephant was
brought in, a young man in Indian costume being perched on its
neck. The mare and the elephant went through a number of
evolutions together. Finally the mare reared and lodged her forepaws
on the elephant’s tremendous flank, and so situated the strange pair
made an exit which roused the house from apathy to wild
enthusiasm. Juana was vociferously recalled. She re-entered on foot,
holding her habit up with one hand, a light whip in the other. Richard
could not help being struck by the rather cold, sad, disdainful beauty
of the girl’s face. It seemed wrong that the possessor of such a face
should have to go through a series of tricks twice daily for the
diversion of a rustic audience.
‘That wench is as like Craig’s girl as two peas.’ Richard turned
quickly at the remark, which was made by one of two women who
sat behind him industriously talking. The other agreed that there
was some likeness between ‘Craig’s girl’ and the lovely Juana, but
not a very remarkable one.
Richard left his seat, went out of the pavilion, and walked round
the outside of it towards the part where the performers entered the
ring. Attached to the pavilion by a covered way was a smaller tent,
which was evidently used as a sort of green-room by the performers.
Richard could see within, and it happened that he saw Juana
chatting with a girl who was very much like Juana, though rather
less stately. The young man in Indian costume, who had ridden the
elephant, was also of the group. Soon the young man went to
another corner of the tent, and the two girls began to talk more
rapidly and more earnestly. Lastly, they shook hands and kissed,
Juana burst into tears, and her companion ran out of the tent.
Richard followed her at a safe distance through the maze of minor
tents, vans, poles, and loose horses, to the main road. A small,
exquisitely-finished motor-car stood by the footpath; the girl jumped
on board, pulled a lever, and was off in a northerly direction through
Dunstable up Watling Street.
‘Is that the road to Hockliffe?’ he asked a policeman.
‘Yes, sir.’
‘It’s Raphael Craig’s daughter, I bet,’ he said to himself, and for
some reason or other smiled a satisfied smile. Then he added, half
aloud, ‘But who is Juana?’
He went back to see the rest of the performance, and he had
scarcely sat down before he had cause to wish that he had remained
outside. The famous strawberry-roan mare, formerly ridden by
Juana, was making a second appearance as the talking horse, in
charge of the young man who had shone before in Indian costume,
but who now wore the dress of a riding-master. An attendant was
walking along the front benches with a bundle of numbered cards.
He offered one to Richard, and Richard thoughtlessly accepted the
offer. From that moment the eyes of the entire assemblage were
upon him.
Welcome to our website – the perfect destination for book lovers and
knowledge seekers. We believe that every book holds a new world,
offering opportunities for learning, discovery, and personal growth.
That’s why we are dedicated to bringing you a diverse collection of
books, ranging from classic literature and specialized publications to
self-development guides and children's books.

More than just a book-buying platform, we strive to be a bridge


connecting you with timeless cultural and intellectual values. With an
elegant, user-friendly interface and a smart search system, you can
quickly find the books that best suit your interests. Additionally,
our special promotions and home delivery services help you save time
and fully enjoy the joy of reading.

Join us on a journey of knowledge exploration, passion nurturing, and


personal growth every day!

ebookbell.com

You might also like