Download - Introductory Course on C++
-
8/4/2019 Introductory Course on C++
1/209
June 2003 Copyright (C) 2003 by Dragan Miliev 1
The C++ Programming Language
Introductory Course
Covers basic concepts and elements of C++ Requires knowledge of fundamental concepts of object-oriented and procedural programming
Does not require knowledge of C
Dr. Dragan Miliev
Ass. Professor, University of [email protected], www.rcub.bg.ac.yu/~dmilicev
-
8/4/2019 Introductory Course on C++
2/209
June 2003 Copyright (C) 2003 by Dragan Miliev 2
Outline
Part I: Introduction
Part II: General Issues
Part III: Procedural Elements
Part IV: Classes
Part V: Derived Classes and PolymorphismPart VI: Conclusions
-
8/4/2019 Introductory Course on C++
3/209
June 2003 Copyright (C) 2003 by Dragan Miliev 3
Part I: Introduction
About this Course
Getting Started
-
8/4/2019 Introductory Course on C++
4/209
June 2003 Copyright (C) 2003 by Dragan Miliev 4
Chapter 1: About this Course
Subject and Objectives
Prerequisites
Resources
-
8/4/2019 Introductory Course on C++
5/209
June 2003 Copyright (C) 2003 by Dragan Miliev 5/209
Subject and Objectives
Subject: Basic concepts of the C++ programming language
Implementation of procedural and OO concepts in C++
Style guidelines for programming in C++
General applicability: not oriented to any library,framework, or tool
Objectives: Get familiar with the basic concepts of C++
Get ready to read, understand, and write C++programs
-
8/4/2019 Introductory Course on C++
6/209
June 2003 Copyright (C) 2003 by Dragan Miliev 6/209
Prerequisites
Understanding of fundamental concepts of theprocedural programming paradigm: Type and variable, pointer/reference
Declaration, expression, statement, condition, loop
Subprogram (procedure and function), argument(formal and actual), invocation, recursion
Understanding of fundamental concepts of theobject-oriented programming paradigm:
Classes, objects, and references to objects Attributes and structural relationships
Operations, constructors/destructors, and encapsulation
Inheritance (generalization/specialization, substitution)and polymorphism
-
8/4/2019 Introductory Course on C++
7/209
June 2003 Copyright (C) 2003 by Dragan Miliev 7/209
Resources
Books on OO programming and C++: B. Stroustrup, The C++ Programming Language, 2nd
ed., Addison-Wesley, 1993
M. A. Ellis, B. Stroustrup, The Annotated C++
Reference Manual, Addison-Wesley, 1990
Discussion with Dr. Miliev:[email protected]/~dmilicev
Other books on OO programming, C++ and otherprogramming languages, and design patterns
-
8/4/2019 Introductory Course on C++
8/209
June 2003 Copyright (C) 2003 by Dragan Miliev 8
Chapter 2: Getting Started
About C++
C/C++ Design Principles
A Simple C++ Program
-
8/4/2019 Introductory Course on C++
9/209
June 2003 Copyright (C) 2003 by Dragan Miliev 9/209
About C++
C++ is a standard, object-oriented, common-purposeprogramming language
C++ is vertically compatible with C: all C programs can becompiled with C++ compilers
However, C++ is a language of a new generation and ofdifferent paradigm than C! The difference between C andC++ is much bigger (conceptual) than between C++ andJava, for example
C++ supports all fundamental OO concepts, but alsoallows non-OO parts or entire programs
C++ is a tool that helps to make good OO programs, notprevents from making bad OO or procedural programs
C++ is a means of expressing OO design of software
-
8/4/2019 Introductory Course on C++
10/209
June 2003 Copyright (C) 2003 by Dragan Miliev 10/209
C/C++ Design Principles
C++ is vertically compatible with C: all C programs can becompiled with C++ compilers
Efficiency of implementation: the compiled code has almostthe same efficiency as the equivalent hand-writtenassembly code
Extensive compile-time checkingNo runtime checking
Static typing, strong, but not exclusive typing (conversionsare allowed)
Uniform treatment of built-in (primitive) and user-defined(classes) types of objects
Alignment of the sizes of the built-in types to the machinearchitecture; consequently, the sizes of the built-in typesare not standard
-
8/4/2019 Introductory Course on C++
11/209
June 2003 Copyright (C) 2003 by Dragan Miliev 11/209
Counter
3
create(3)
A Simple C++ Program
Task:Write a class that abstracts a counter that can beinitialized to the given value, incremented, andasked for the current value.
Write a program that creates several counters,increments them independently, and writes theirvalues at the standard output.
val()?
Counter
- counter : int
+ Counter(int)+ inc()+ val() : int
4
inc()
5inc()
-
8/4/2019 Introductory Course on C++
12/209
June 2003 Copyright (C) 2003 by Dragan Miliev 12/209
A Simple C++ Program
// A simple C++ program#include
class Counter {
public:
Counter (int initVal);
voidinc ();
int val();
private:
int counter;};
Counter::Counter (int initVal) {
counter = initVal;}
Comment: from // to end of line
Include declarations of librarian elements forstandard input/output operations
Start of definition of class Counter
Start of the section of public class members
Declaration of a constructor with aninteger argument
Declaration of an operation (member function)without arguments and with no resultDeclaration of an operation (member function)without arguments and with an integer result
Start of the section of private class members
Declaration of an integer attribute (data member)
End of definition of class CounterDefinition of the constructor of class Counter
Start of the method definition: a compoundstatement (block)
Access to the member of the object being constructed
Assignment expression as a statementEnd of the method definition (block)
-
8/4/2019 Introductory Course on C++
13/209
June 2003 Copyright (C) 2003 by Dragan Miliev 13/209
A Simple C++ Program
// A simple C++ program, continued:voidCounter::inc () {counter = counter + 1;
}
int Counter::val () {
return counter;}
voidmain () {Counter* c1 = new Counter(0);Counter* c2 = new Counter(3);
c1->inc(); c2->inc();cout
-
8/4/2019 Introductory Course on C++
14/209
June 2003 Copyright (C) 2003 by Dragan Miliev 14
Part II: General Issues
Lexical Elements
Types and Conversions
Built-in Types
Declarations and Scopes
Object LifetimesProgram Structure
-
8/4/2019 Introductory Course on C++
15/209
June 2003 Copyright (C) 2003 by Dragan Miliev 15
Chapter 3: Lexical Elements
Tokens
Comments
Identifiers
Literals
-
8/4/2019 Introductory Course on C++
16/209
June 2003 Copyright (C) 2003 by Dragan Miliev 16/209
Tokens
C++ is case-sensitiveWhite spaces: blanks, tabs, new lines, new pages
White spaces separate tokens and do not nave any othermeaning for the compiler; these are equivalent:
if (acharchar c1 = 0;for (int i=0; iint->char...
}
Variants ofchar, which have the same memory size aschar, but treated differently when converted into int: signed char: the integer value may be negative
unsigned char: the integer value is always non-negative
-
8/4/2019 Introductory Course on C++
29/209
June 2003 Copyright (C) 2003 by Dragan Miliev 29/209
Boolean Type
Newer version of C++ allow a Boolean type boolThe objects ofbool may have one of two symbolic values:false and true
A Boolean object may be implicitly converted into an
integer: false is converted to 0, and true to 1An integer object may be implicitly converted into a bool:0 is converted to false, and any non-zero value to true
bool flag = false;
...
flag = true;...
if (flag) ...
-
8/4/2019 Introductory Course on C++
30/209
June 2003 Copyright (C) 2003 by Dragan Miliev 30/209
Integer Types
Integer types: int: the basic integer type of the size of one machine word (most
efficient) short int (or short for short): integer of size less than or equal
to the size ofint
long int (or long for short): integer of size greater than orequal to the size ofint
Variants of the same size as the primary type: signed (default): values may be negative
unsigned: values are always non-negative
Conversions to smaller-sized types or from signed tounsigned and vice versa may lose information (warning,not compilation error)
Examples:short si = 127; // signed short intunsigned long
ul = 123456UL; // unsigned long int
-
8/4/2019 Introductory Course on C++
31/209
June 2003 Copyright (C) 2003 by Dragan Miliev 31/209
Floating-Point Types
Types for floating-point rational numbers: double: default floating-point type
float: floating-point of size less than or equal to thesize ofdouble
long double: floating-point of size greater than orequal to the size ofdouble
Conversions to smaller-sized types may loseinformation or precision (warning, not compilationerror)
Examples:float pi = 3.14;double d = 1.5e-4;long double dl = 1.3;
-
8/4/2019 Introductory Course on C++
32/209
June 2003 Copyright (C) 2003 by Dragan Miliev 32/209
Enumerations
Enumeration is a type that defines a finite set of discretesymbolic values. Its instances may take only the valuesfrom the set
Examples:enumBool { false, true };enumReply { YES, NO, CANCEL };
enumStatus { initiated, suspended,committed, canceled, failed };
Status s1 = initiated;...
if (s1==committed) ...
-
8/4/2019 Introductory Course on C++
33/209
June 2003 Copyright (C) 2003 by Dragan Miliev 33/209
Enumerations
There is a standard (built-in) conversion from anenumeration value to an int, resulting in the value of the
order number of the symbol in the set, starting from 0:enumStatus { initiated, suspended,
committed, canceled, failed };
int i = suspended; // i gets the value 1Status s = canceled;...if (s==4) ... // conversion Status->int;
// evaluates to true if s==failed
The default ordering can be changed:enumStatus{ initiated = 1, suspended, //suspended = 2committed, canceled = 5,failed = committed+4 }; // failed = 7
The opposite conversion (intpenum) may not be implicit:Status s = 3; // Error!
-
8/4/2019 Introductory Course on C++
34/209
June 2003 Copyright (C) 2003 by Dragan Miliev 34/209
Enumerations
Enumerations should be used whenever there is a need fora data type that abstracts a concept from the problemdomain and its instances take values from a finite discreteset of symbolic values
It is not wise to use a built-in integer type instead of anenumeration in that case, because: the program is more difficult to understand, because the abstract
type is mixed with the built-in integer type
the values of the abstract type should not take part in arithmetic
operations (addition, subtraction, multiplication, etc.) the program is less flexible: if there is a need to change the
decision about the implementation of the abstract type, it is difficultto find those occurrences of the type that are not really theintentional usage of built-in integer types and replace them
-
8/4/2019 Introductory Course on C++
35/209
June 2003 Copyright (C) 2003 by Dragan Miliev 35/209
Pointers
A pointer is an object that points to another object
In C++, pointers are implemented as memory cells that
carry values of the addresses of pointed objects inmemory; however, this is a matter of implementation andthe concrete value of a pointer should not be considered,except in special cases of debugging pointers
A pointer realizes a unidirectional link to an object; there is
no additional information about the linkage of the pointerand the pointed object and no runtime checking of pointervalidity; consequently, pointers are not safe against somesevere problems, and the programmer is responsible for
the pointers validity
anObjectaPointer
-
8/4/2019 Introductory Course on C++
36/209
June 2003 Copyright (C) 2003 by Dragan Miliev 36/209
Pointers
If a pointer p points to an objectx, then theoperation *p results in the objectx (pointer
dereferencing)The operation &x results in a pointer value thatpoints to the objectx (address operation)
Pointers are derived types: there is no a pointer
(just like this), but a pointer to T. The typepointer to T is denoted with T*:T x;T* p = &x; // &x is of type T*...*p... // *p is of type T and refers to x
T xT* p
-
8/4/2019 Introductory Course on C++
37/209
June 2003 Copyright (C) 2003 by Dragan Miliev 37/209
2int* pi
0
i
int
0
j
1Pointers
int i=0, j=0;int* pi = &i;
*pi=2;
j=*pi;
pi=&j;
2
3
24
int* pi
5
Counter* p = new Counter(4);
p->inc(); // call inc() of *P
(*p).inc(); // the same
-
8/4/2019 Introductory Course on C++
38/209
June 2003 Copyright (C) 2003 by Dragan Miliev 38/209
2
int* pi 0
i
int
0
j
1
Pointers
Pointers are objects that point to objects, including otherpointers:int i=0, j=0;int* pi=&i;int** ppi; // pointer to- pointer to - int";ppi=
*pi=1;**ppi=2; // Evaluated: *(*ppi)*ppi=&j;ppi=&i; // Compilation error:
// int* cannot be converted to int**
1
54
int** ppi
3
2
6
7
-
8/4/2019 Introductory Course on C++
39/209
June 2003 Copyright (C) 2003 by Dragan Miliev 39/209
Pointers
A pointer of type void can point to an object of any type(typeless pointer). There are no objects of type void, onlypointers of type void*. void* pointers are not used inOO programs because they are not type-safe; they areused in low-level programming when accessing raw data in
computer memory or hardware registersCounter* c = new Counter(7);void* p = c;
p->inc(); // Compilation error: *p is not a Counter!
A pointer can point to nothing a null pointer with the
symbolic value 0. The value 0 is a symbolic value, notnecessarily the binary value of the pointersimplementation (although often so). A pointer can be: initialized or assigned the null value: int* p=0; ... p=0;
checked against the null value: if(p==0)... if(p!=0)...
-
8/4/2019 Introductory Course on C++
40/209
June 2003 Copyright (C) 2003 by Dragan Miliev 40/209
Pointers
C/C++ pointers are very unsafe and may cause severebugs. Here are some most often problems
Invalid pointer Cause: dereferencing a pointer with an invalid value (points to an
invalid object, its value is an invalid or corrupted address); neither
a pointer nor its pointed object are checked against validity atruntime:Counter* p; // Pointer has undefined default value
p->inc(); // Possible runtime error!
Effect: a possible (but not always) runtime error or exception (memory access
violation or program blockage) a bug (invalid result of an operation)
Typical cases of occurrences: uninitialized pointer:Counter* p; // No default initial value!p->inc(); // Possible runtime error or exception!
-
8/4/2019 Introductory Course on C++
41/209
June 2003 Copyright (C) 2003 by Dragan Miliev 41/209
Pointers
corrupted pointer:int a[5]; // array of 5 integers in range [0..4]
Counter* p = new Counter(2);
// p is probably allocated behind the array
for (int i = 0; iinc(); // p is probably corrupted!
Cure: careful programming
always initialize pointers
check indices against array boundaries compilers sometimes warn you to these problems
-
8/4/2019 Introductory Course on C++
42/209
June 2003 Copyright (C) 2003 by Dragan Miliev 42/209
Pointers
Null-pointer dereferencing Cause: dereferencing a pointer with a null value; a pointer is not
checked against null value at runtime:Counter* p = 0;
p->inc(); // Runtime error (probably hardware exception)!
Effect: a runtime error on almost all platforms (a memory-access-violation
hardware exception in most cases)
Typical cases of occurrences: non-checked pointer value, typically as a result of a function:Counter* getCounter(...); // function that returns a ptr...
Counter* p = getCounter(...); // May return 0p->inc(); // Possible runtime error!
non-checked result ofnew; when there is no free memory, newreturns null:Counter* p = new Counter(7); // May return 0p->inc(); // Possible runtime error!
-
8/4/2019 Introductory Course on C++
43/209
June 2003 Copyright (C) 2003 by Dragan Miliev 43/209
Pointers
Cure: always check the pointer as a result of a function or new:
Counter* p = getCounter(...); // Or:
Counter* p = new Counter(7);
if (p!=0) p->inc();
never believe in pointersalways check them beforedereferencing (very conservative) :if (p!=0) ...p->...
if (p!=0) ...*p...
-
8/4/2019 Introductory Course on C++
44/209
June 2003 Copyright (C) 2003 by Dragan Miliev 44/209
Pointers
Dangling pointer: Cause: dereferencing a pointer that points to a destroyed object;
the pointer is not notified on destruction of the pointed object:Counter* p = new Counter(5);delete p;p->inc(); // Bug: *p does not exist any more!
Effect: a bug due to the access of invalid objects sometimes a runtime error, blockage, or exception, because the
memory space of the destroyed object may have been allocated byother system data
Typical cases of occurrences:
invalid use of objects and pointers:Counter* p = new Counter(3);... // In another context:Counter* q = p;... // In yet another context:
delete p; // p and q dont change their values even to 0... // In yet another context:...*q... or ...q->...
-
8/4/2019 Introductory Course on C++
45/209
June 2003 Copyright (C) 2003 by Dragan Miliev 45/209
Pointers
returning pointers to automatic (local) objects placed on thestack from functions:int* f() {
int x = 5; // a local, automatic integer...
return &x; // x dies on function return
}...
int* p = f(); // p is a dangling pointer!
Cure: Careful programming
Compilers often warn you to dangling pointers, especially asreturn values of functions
-
8/4/2019 Introductory Course on C++
46/209
June 2003 Copyright (C) 2003 by Dragan Miliev 46/209
Arrays
An array is an object that represents an ordered,bounded collection of objects with a fixed sizedetermined at the time of its creation
Arrays are derived types: there is no an array(just like this), but an array of objects of type T.The type an array ofTs is denoted with T[]:int a[100]; // An array of 100 ints
The indices of an array are always in the range[0..n-1]:a[2] = 5; // access to the third elementa[50] = a[0]+a[99];
T T T ... T T0 1 2 ... n-2 n-1
-
8/4/2019 Introductory Course on C++
47/209
June 2003 Copyright (C) 2003 by Dragan Miliev 47/209
Arrays
There is no runtime range-checking of indices. Therefore,runtime errors are possible due to range errors (corruptionof other data or runtime exceptions due to memory accessviolations)
An element of an array may be any object, even anotherarray (multidimensional arrays):int m[5][7]; // a 5 x 7 matrixm[3][5] = 2; // evaluated as (m[3])[5];
// m[3] is the 4th element of m;// it is an array of 7 ints;
// (m[3])[5] is its 6th integer element
-
8/4/2019 Introductory Course on C++
48/209
June 2003 Copyright (C) 2003 by Dragan Miliev 48/209
Arrays
Due to its orientation to efficiency, C/C++ arrays are usedin operations with as little information about them aspossible; to generate the code to access an element of anarray, apart from the index, the compiler needs: the starting address of the array
the size of an element, which is determined by its typeThis information can be deduced from a pointer to the firstelement of the array.
For example, arrays are not passed to functions by value(as entire packages of elements), but by a pointer to their
beginning. Consequently, the invoked function does nothave an implicit information about the array size theymust be provided by the program semantics!
Therefore, arrays and pointers are tightly coupled by thefollowing rules
-
8/4/2019 Introductory Course on C++
49/209
June 2003 Copyright (C) 2003 by Dragan Miliev 49/209
Arrays
Rule #1: Whenever an array (of type T[]) is used in anoperation (except for &), it is implicitly converted into apointer (of type T*) that points to the arrays first element:T[] p T*
Rule #2: For a pointer (of type T*) and an integer, the
operations of additions and subtractions are defined; if apointer p points to an element of an array, the result ofaddition p+i (where i is an integer) is a value of a pointerthat points to the element of the same array, i places
ahead: T T T ... T T
p p+i
i
-
8/4/2019 Introductory Course on C++
50/209
June 2003 Copyright (C) 2003 by Dragan Miliev 50/209
Arrays
Rule #2 (continued): The result is defined provided that the pointer points to an element of an array and
the resulting pointer points to an element of the same array, or oneelement behind (not allowed to dereference)
These rules are not checked at runtime: the compiler does
not generate the code for checking against these rules, butsimply the code that sums up the value of the pointer andthe value of the integer multiplied by the size of an element.If the rules are not satisfied, there is no compilation warningor error, but the result will be undefined (a silent bug due to
invalid or corrupted data or a runtime exception due tomemory access violation).
The similar holds for subtraction of an integer from a pointer(the result is a pointer i places backward) or for subtractionof two pointers that point to elements of the same array (the
result is an integer).
-
8/4/2019 Introductory Course on C++
51/209
June 2003 Copyright (C) 2003 by Dragan Miliev 51/209
Arrays
Rule #3: The expression a[i] is treated as *(a+i) bydefinition
Consequences: the treatment of array indexing operation:
int a[10];
int* p = &a; // p points to a[0];a[2]=1;p[3]=3;
p=p+1;*(p+2)=1;
p[-1]=0;
The same as: = a; because a is converted into &a
a[2]|*(a+2) by Rule #3 in *(a+2), a is converted into a pointer to its first element
of type int* by Rule #1 the pointer is added with 2 by Rule #2, and the result of(a+2) is a pointer that points to a[2] the resulting pointer is dereferenced by *(a+2), and theresult refers to the pointed object that is exactly a[2]
p[3]|*(p+3) by Rule #3 the pointer is added with 3 by Rule #2, and the result of(p+3) is a pointer that points to a[3] the resulting pointer is dereferenced by *(p+3), and theresult refers to the pointed object that is exactly a[3]
By Rule #2, a pointer is added with 1 and the resultpoints to the next element in the array
The same as p[2]
The same as *(p-1). The result of p-1 is a pointerthat points one element in front of the one pointedto by p
-
8/4/2019 Introductory Course on C++
52/209
June 2003 Copyright (C) 2003 by Dragan Miliev 52/209
Arrays
arrays cannot be passed to functions by value (as entirepackages of elements), but only pointers to their firstelements are passed (by value):voidsort (int* p); // A fn that accepts an int*
voidqsort (int a[]); // Also accepts an int*,
// because it can be called by:int a[10];qsort(a); // a is converted into int*
consequently, T[] and T* as types of arguments aretreated uniformly
when arrays are passed as arguments, the argumentsdo not carry the information about the size of the array(C/C++ arrays do not carry this information); this mustbe ensured by the program semantics; for example:int sumUp (int a[], int numOfElements);
-
8/4/2019 Introductory Course on C++
53/209
June 2003 Copyright (C) 2003 by Dragan Miliev 53/209
Arrays
for that purpose, the compiler terminates string-literals with \0 bydefault:char s[] = Hello;
char* p = World;
char q[5] = {H,e,l,l,o};
s is an array of 6 characters
p is a pointer (not an array) toan array of 6 chars
for the same purpose (implicit information about array size), thereis a traditional C convention for the arrays of characters: theyshould be always terminated by \0 (null-terminated strings); alllibrarian functions that deal with strings expect such arrays; if an
array is not terminated so, the function will not work correctly (itmay loop until it accidentally comes across a null byte in memory):int strlen (char* p);
// Expects a null-terminated string
// Returns the size of the string,
// without counting in \0q is an array of 5 chars, initialized to the given
values, but it is not null-terminated!
H e l l o w o r l d \0
-
8/4/2019 Introductory Course on C++
54/209
June 2003 Copyright (C) 2003 by Dragan Miliev 54
Chapter 6: Declarations and Scopes
Declarations
ScopesGlobal Scope
Local Scope
Class Scope
-
8/4/2019 Introductory Course on C++
55/209
June 2003 Copyright (C) 2003 by Dragan Miliev 55/209
Declarations
A declaration introduces a name (identifier) into aprogram:int a = 3; // an object of type int
int* p = &a; // an object of type int*
voidf(int); // a function that
// accepts an int and returns no resultint* g(char*,int); // a function that// accepts a char* and an int and returns an int*
class Counter; // a class named Counter
Counter* pc; // an object of type Counter*
Any name in the program must be declared before it isused
A declaration lets the compiler know about the languagecategory of the name (a type, an object, a reference, afunction, etc.) and its type
-
8/4/2019 Introductory Course on C++
56/209
June 2003 Copyright (C) 2003 by Dragan Miliev 56/209
Declarations
After processing a declaration, the compiler: adds the name into its symbol table, along with the information
about the names language category and type
possibly allocates the space for an object, generates the code forits initialization, or generates the code for a function body
checks the usage of the name afterwards according to its categoryand type information from the symbol table, and reports violations(compilation errors)
knows how to compile the code when the name is used afterwards
A definition is a declaration that: (declaration of an object) initializes (creates) an object or
(declaration of a function) defines the body of a function or
(declaration of a class) declares the members of a class
-
8/4/2019 Introductory Course on C++
57/209
June 2003 Copyright (C) 2003 by Dragan Miliev 57/209
Declarations
Declarations of objects: which are not definitions (do not initialize objects):extern int a, b;extern Counter* theCounter;
After such a declaration, an object can be used freely (all
operations are allowed), provided it is definedsomewhere in the program
which are definitions (do initialize objects):int a, b=0; // a has an undefined initial valueCounter *p, *q = new Counter;// p and q are of type Counter*;// p has an undefined initial value
Objects of built-in types do not have default initial value;unless they are explicitly initialized with an initializer,they will have an undefined value (whatever isencountered in memory)
-
8/4/2019 Introductory Course on C++
58/209
June 2003 Copyright (C) 2003 by Dragan Miliev 58/209
Declarations
Declarations of functions: which are not definitions (do not define bodies):int f(), sqr(int); // f has no arguments,// sqr accepts an int, both return an int
voidCounter::inc(); // a member of Counter
After such a declaration, the function can be used freely(it can be invoked), provided it is defined somewhere inthe program.
The name of formal arguments are not relevant in these
declarations (the compiler ignores them). They shouldbe provided in order to increase the readability.
which are definitions (do provide bodies):voidCounter::inc() { counter=counter+1; }
int sqr(int i) { return i*i; }
-
8/4/2019 Introductory Course on C++
59/209
June 2003 Copyright (C) 2003 by Dragan Miliev 59/209
Declarations
Declarations of classes: which are not definitions (do not declare members):class Counter;
After such a declaration, only pointers and references toobjects of that class can be defined, but no other
operations on these objects are possible; used to reducecompilation dependencies among program modules:class Counter;class Clock {
public:Clock(Counter*); // Decl. of a constructor
private:Counter* myCounter;
};
which are definitions (declare all members); objects canbe defined and manipulated after such definitions
-
8/4/2019 Introductory Course on C++
60/209
June 2003 Copyright (C) 2003 by Dragan Miliev 60/209
Scopes
Scope is a part of the program source code inwhich a declared name can be used (it is said tobe in scope)
Scope is a notion exclusively bound to: the space dimension (relates with a part of the program
source code)
compilation time (scopes are resolved at compilationtime only and have no effects at runtime)
A name can be used in its scope directly. Outsideits scope, the name can be accessed in a specificway or not used at all
-
8/4/2019 Introductory Course on C++
61/209
June 2003 Copyright (C) 2003 by Dragan Miliev 61/209
Scopes
Scopes can be nested: if a name is declared in a nestedscope, it hides the same name declared in an enclosingscope, meaning the following: when a name is used, the compiler tries to bind it to the
declaration that describes that name
it first tries to find the declaration in the inner-most nested scope(the current scope)
if the declaration is not found there, the compiler searches the firstenclosing scope, etc. outward, until a declaration is found
if no declaration is found, the compiler reports an error (name not
declared)The language defines the rules of scope nesting
-
8/4/2019 Introductory Course on C++
62/209
June 2003 Copyright (C) 2003 by Dragan Miliev 62/209
Scopes
Example:int x = 0;
voidf () {
int x = 1;
x = 3;
}
class Dummy {public:
int x;
};
A global x of file scope
Scopes in C++: global (file)
local (block)
class
function (not covered by this course)
Start of a nested scope
Hides the global xRefers to the x from the nested
scopeEnd of the nested scope; thelocal x is no more in scopeStart of a nested scope
Hides the global x
End of the nested scope; the member x is no morein scope
-
8/4/2019 Introductory Course on C++
63/209
June 2003 Copyright (C) 2003 by Dragan Miliev 63/209
Global Scope
A name has the global scope if it is declared outside allclasses and function bodies
A global name is in scope from the place of its declarationto the end of the compilation unit (the source code file)
A global name can be accessed from a nested scope,although it is hidden, over the :: operator:int x = 0; // global x, in scope to the end of file
voidf () { // a nested scope
int x = 2; // hides the global x
x = 3; // access to x from the nested scope::x = 3; // access to the global x
} // end of the nested scope
int* p = &x; // access to the global x
-
8/4/2019 Introductory Course on C++
64/209
June 2003 Copyright (C) 2003 by Dragan Miliev 64/209
Local Scope
A name has a local scope if it is declared inside acompound statement (a block between braces {}),including a function body
A local name is in scope from the place of its declaration tothe end of the block in which it is declared
A block is a nested scope for an enclosing block or the file(the global scope):int x;
voidf () {int x = 1;
x = 2;{int x = 0;x = 2;
}x = 3;
}
A global x of file scope
Start of a nested compound statement(block) and scope
A local x, hides the global x
Refers to the local x
A nested local x, hides the globaland the enclosing local onesRefers to the second local xEnd of the nested scopeRefers to the first local x
-
8/4/2019 Introductory Course on C++
65/209
June 2003 Copyright (C) 2003 by Dragan Miliev 65/209
Local Scope
The same declaration of a name can be repeated in thesame scope, unless it is a definition
Formal arguments of functions have a local scope of theoutermost block of the function body:voidf(int x) { // argument x has a local scope
int x = 0; // Compilation error:// multiple definitions of the same name
...
}
-
8/4/2019 Introductory Course on C++
66/209
June 2003 Copyright (C) 2003 by Dragan Miliev 66/209
Class Scope
A name has a class scope if it is declared inside a classdefinition; all names declared inside a class definition arecalled its members: data members and member functions
types: typedefs, enumerations, structures, unions, classes
class DatabaseManager {public:
enumDBStatus { ok, failed, refused };DatabaseManager (char* name); // ConstructorDBStatus openConnection();DBStatus closeConnection();
DBStatus getConnectionStatus();DBStatus performQeury (char* sqlQuery);
private:char* name;...
};
-
8/4/2019 Introductory Course on C++
67/209
June 2003 Copyright (C) 2003 by Dragan Miliev 67/209
Class Scope
A name with a scope of class X can be accessed: directly, within the same scope:DatabaseManager::DatabaseManager(char* nm) {name = new char[...]; // name is in scope
...
} over an object of type X and . operator:voidmain (){
DatabaseManager* p = new DatabaseManager(...);...
(*p).openConnection();...
}
over a pointer of type X* and -> operator:p->openConnection();
-
8/4/2019 Introductory Course on C++
68/209
June 2003 Copyright (C) 2003 by Dragan Miliev 68/209
Class Scope
over the :: operator (X
::memberName):class Base {
public:virtual voidf(); // polymorphic function
};
class Derived :public Base {public:
virtual voidf(); // redefined operation};
voidDerived::f () {...f();Base::f();...
}
End of scope of class Derived; the only active
scope is global
f() is from the scope of class Derived Reactivation of that class scope
Start of a nested local scope
We want to call the Base class version off(). This is an error, because f is searchedfor:
in the active local scope (not found) in the active class scope Derived (found)Thus, this is an endless recursion!
Correct: start the search from the Base classscope (and possibly the scopes of its baseclasses)
-
8/4/2019 Introductory Course on C++
69/209
June 2003 Copyright (C) 2003 by Dragan Miliev 69/209
Class Scope
Types can be defined in a class scope, e.g., classes orenumerations. If a class is defined inside another class,this is only the matter of scopes and there is no othermeaning (no object embodying, no special access rightsamong the classes):class List {
public:enumStatus { ok, error };
List ();Status put (Object* anItem);...
private:class ListElement { // nested classListElement (ListElement*); // constructor//...
};};
-
8/4/2019 Introductory Course on C++
70/209
June 2003 Copyright (C) 2003 by Dragan Miliev 70/209
Class Scope
List::Status List::put (Object* p) {...
return ok;
}
List::ListElement::ListElement
(List::ListElement* next) {...}
Status is not in scope. It must be accessedthrough the operator ::
ok is now in scope, because the List class scopeis active ListElement is not in scope. It
must be accessed this way.
A nested type is used when it is needed only for animplementation of another class. Nested types aregenerally equivalent to global types, except that:
they do not pollute the global name space, thus reducing chancesfor name clashing
they are logically packed into a proper class, thus improvingreadability and understandability of the program
access to them may be controlled (they can be public, protected, orprivate), allowing their encapsulation
-
8/4/2019 Introductory Course on C++
71/209
June 2003 Copyright (C) 2003 by Dragan Miliev 71
Chapter 7: Object Lifetimes
Object Lifetime
Automatic ObjectsStatic Objects
Dynamic Objects
Data MembersTemporary Objects
Object Initialization and Destruction
-
8/4/2019 Introductory Course on C++
72/209
June 2003 Copyright (C) 2003 by Dragan Miliev 72/209
Object Lifetime
An object lifetime is the time interval from its creation tillits destruction. The object can be accessed only during itslifetime
In the beginning of its lifetime, an object is initialized. If itis an object of a class, its constructor is called.In the end of its lifetime, the object is destroyed. If it is anobject of a class, its destructor is called.There is no exception to this rule, regardless of the lifetimecategory
Lifetime is a concept orthogonal to scope: it is time-related (instead of space-related)
it is runtime-related (instead of compilation-related)
-
8/4/2019 Introductory Course on C++
73/209
June 2003 Copyright (C) 2003 by Dragan Miliev 73/209
Object Lifetime
Categories of lifetimes in C++ automatic
static
dynamic
data members
temporary objects
One of the main design principles of C++ is that objects ofall types (built-in as well as user-defined) can be of alllifetime categories
-
8/4/2019 Introductory Course on C++
74/209
June 2003 Copyright (C) 2003 by Dragan Miliev 74/209
Automatic Objects
An automatic object lives from the time of execution of itsdefinition, until the execution exits its scope (block)
Automatic objects are local objects not specified asstatic
Every time the flow of control executes a definition of anautomatic object, a new incarnation of that object iscreated; this allows nested and recursive function calls:int f (...) {int i = ...;
... f(...)...for (i=0; i
-
8/4/2019 Introductory Course on C++
75/209
June 2003 Copyright (C) 2003 by Dragan Miliev 75/209
Automatic Objects
Automatic objects are placed on the program control stack:when a function is called, an activation block of itsautomatic objects is created on the stack; when it isfinished, the activation block is cleared from the stack; thecompiler compiles operations with automatic objects byaddressing modes relative to the top of the stack
Formal arguments of functions are automatic by theirlifetime. When a function is called, the formal argument iscreated as an automatic object and initialized by the actualargument. The initialization semantics are the same as for
any other initialization:voidf (X x1) {...}
voidg () {...f(x2)...
}
At the time of function invocation
f(x2), local automatic x1 is createdand initialized by x2; the semanticsare the same as in the definition:X x1=x2;
-
8/4/2019 Introductory Course on C++
76/209
June 2003 Copyright (C) 2003 by Dragan Miliev 76/209
Automatic Objects
Objects of classes can be automatic, too. Constructors anddestructors are invoked at the beginning and end of theirlives:voidmain () {
Counter c1(3), c2(3); // automatic objects
c1.inc(); // call inc() of c1...} // destructors of c1 and c2 are called here
Substitution does not take place for these objects, becausethey are always exactly the objects of the specified class
known to the compiler, identified directly by their names:Derived d; // an object of a derived classBase b = d; // b is certainly a Base, nothing else!
-
8/4/2019 Introductory Course on C++
77/209
June 2003 Copyright (C) 2003 by Dragan Miliev 77/209
Automatic Objects
An automatic object is created when the executionencounters its definition. Consequently, an automaticobject does not need to be created at all; if it is not, it willnot be destroyed, either (constructor and destructor willnot be called):voidmain () {...
if (...) {
Counter c1(2); // c1 may never be created...
} // destructor for c1 is called here
}
-
8/4/2019 Introductory Course on C++
78/209
June 2003 Copyright (C) 2003 by Dragan Miliev 78/209
Static Objects
A static object lives from the moment of execution of itsdefinition, till the end of the program. There is only oneincarnation of each static object during the execution ofthe program
Static objects are: all global objects
local objects declared as staticCounter c(2); // global static objectvoidf () {
static Counter c(3); // local static object
}
-
8/4/2019 Introductory Course on C++
79/209
June 2003 Copyright (C) 2003 by Dragan Miliev 79/209
Static Objects
The moment of creation of a static object depends on itsscope: global static objects are created at a moment on program startup,
not necessarily before the invocation ofmain(); the moment of
their initialization is not guaranteed; recommendation: avoid global
static objects of classes local static objects are created when the flow of control comes to
their definition for the first time; they are initialized only when thedefinition is encountered for the first time, every other time thedefinition is skipped;
Static objects are stored in a static memory space,allocated at compile time. Static objects of built-in typesmay often be initialized at compile time:static int a = 5; // may be initialized
// at compile time
-
8/4/2019 Introductory Course on C++
80/209
June 2003 Copyright (C) 2003 by Dragan Miliev 80/209
Static Objects
Local static objects are secure with initialization.Recommendation: instead of global static objects ofclasses, use local static objects of classes. If a definition ofa local static object is never executed, the object will notbe created nor destroyed (the constructors and destructors
will not be called):Counter* Counter::Instance() {
static Counter instance(0);
return &instance;}
Here, the local static object is created (its constructor iscalled) when the function Instance() is first called, if
ever
-
8/4/2019 Introductory Course on C++
81/209
June 2003 Copyright (C) 2003 by Dragan Miliev 81/209
Static Objects
Local static objects survive over subsequent invocations oftheir enclosing functions:int a=1;
voidf () {int b=1; // initialized at each call
static int c=1; // initialized only oncecout
-
8/4/2019 Introductory Course on C++
82/209
June 2003 Copyright (C) 2003 by Dragan Miliev 82/209
Dynamic Objects
The lifetime of a dynamic object is explicitly controlled bythe program semantics. A dynamic object is explicitlycreated by the operator new, and is explicitly destroyed bythe operator delete:Counter* p = new Counter(3);...
delete p;
Dynamic objects survive the execution of functions and arenot tied to implicit destruction, as automatic and staticobjects:Counter* pc = 0;
voidf() {pc = new Counter(2);}voidmain () {f();delete pc;
}
-
8/4/2019 Introductory Course on C++
83/209
June 2003 Copyright (C) 2003 by Dragan Miliev 83/209
Dynamic Objects
The operator new:new T(init)
allocates a space in memory to store an object of typeT; by default, the space is allocated in a special memory
section assigned to a program, managed by a built-inmemory manager, called the freestore or the heap;however, this behavior can be changed for a class
initializes the object by simple copying the result of the initializer expression init to
the allocated space, ifT is a built-in type calling the constructor ofT that accepts the initializer init to
initialize the object, ifT is a class
returns the pointer to the created object of type T*
-
8/4/2019 Introductory Course on C++
84/209
June 2003 Copyright (C) 2003 by Dragan Miliev 84/209
Dynamic Objects
The created dynamic object is always anonymous. The solelink to it is the pointer returned by new. If that pointer islost, there is no way to access the anonymous dynamicobject, even to delete it:int* p1 = new int(3); // correctint p2 = new int(3); // compilation error:
// incompatible typesint p3 = *new int(3);// no compilation error,
// but the object is lost!
The operator delete:delete ptr
if the result of the expression ptr is a pointer to a class, calls thedestructor for the object pointed to by ptr
releases the space allocated for the object; by default, it is done bya built-in heap manager, but it can be changed for a class; ptrmust point to an object created with new, otherwise a runtimeerror may occur
-
8/4/2019 Introductory Course on C++
85/209
June 2003 Copyright (C) 2003 by Dragan Miliev 85/209
Dynamic Objects
Allocation of a dynamic array:char* str2 = new char[strlen(s1)+1];T* a = new T[n][5];
When an array is allocated: all but the first dimensions must be evaluated at compile time; the
first dimension may be computed at runtime (this is the reason for
creating dynamic arrays) no initializers can be specified:
if the type of the elements is a built-in type, the elements haveundefined initial values; the values must be set in a separate loop
if the type of the elements is a class, it must have a constructor thatmay be called without arguments, which is then called for each
element in order of indices; otherwise, a compilation error occurs new returns a pointer to its first element
A dynamic array must be deleted this way:delete [] str;delete [] a;
-
8/4/2019 Introductory Course on C++
86/209
June 2003 Copyright (C) 2003 by Dragan Miliev 86/209
Dynamic Objects
A potential problem with dynamic objects:Memory Leakage Cause: dynamic objects are repetitively created, but not
destroyed (forgotten deletes)
Effect: after a long run, the freestore is exhausted new then returns 0, possibly causing the null pointer
dereferencing problem, or the program simply does not work asintended
Typical cases of occurrences:A function creates a dynamic object, but it is forgotten to be
destroyed in the clients context:X* getAnX(); // It is not obvious who is responsible
// to destroy the returned objectX* pX = getAnX();// there is no delete pX afterwards
-
8/4/2019 Introductory Course on C++
87/209
June 2003 Copyright (C) 2003 by Dragan Miliev 87/209
Dynamic Objects
Cure:Use a naming convention for functions that return
objects for which the client code is responsible todelete:X* getAnX(); // client not responsible to delete
X* createX(); // client responsible to deleteX* pX1 = getAnX();X* pX2 = createX();...delete pX2;
Some tools that monitor execution of a system may
help you to find memory leakage
-
8/4/2019 Introductory Course on C++
88/209
June 2003 Copyright (C) 2003 by Dragan Miliev 88/209
Data Members
The lifetime of a data member object is bound to thelifetime of the enclosing object: it is created when the enclosing object is being constructed
it is destroyed when the enclosing object is being destroyed
class Clock {public:
Clock(); // Constructor~Clock(); // Destructor
private:Counter c; // Data member object of class Counter
};
Clock::Clock() : c(0) { ... }
Clock::~Clock() {...
}
The constructor of the datamember c is called here
The destructor of the datamember c is called here
-
8/4/2019 Introductory Course on C++
89/209
June 2003 Copyright (C) 2003 by Dragan Miliev 89/209
Data Members
A data member is initialized in the list of initializers of aclass constructor, behind :. Every other operation on the
data member in the body of the constructor is an operationon an already initialized member:class Counter () {
public:Counter (int i);
private:
int counter;
};
Counter::Counter (int i) : counter(i) {counter = ...
}
Thisis the initialization of thedata member counter
This is not an initialization, butan operation: counter hasbeen already initialized
-
8/4/2019 Introductory Course on C++
90/209
June 2003 Copyright (C) 2003 by Dragan Miliev 90/209
Data Members
Each data member is initialized in the list of initializers,either explicitly or implicitly, before the body of theconstructor is executed. If an explicit intializer for a datamember does not exist in the list, the initialization isimplicit: for objects of built-in types, the initial value is undefined
objects of classes are initialized by calling the constructor that maybe called without actual arguments; if such a constructor does notexist in the class, there is a compilation errorClock::Clock() {...
}
Error: counter data member cannot beinitialized implicitly, because the classCounter does not have a defaultconstructor!
Similar holds for destructors, except that: a class always has a destructor
built-in types do not have destruction
destructors of data members are called after the completion of thebody of the enclosed objects destructor
-
8/4/2019 Introductory Course on C++
91/209
June 2003 Copyright (C) 2003 by Dragan Miliev 91/209
Temporary Objects
The lifetime of a temporary object is short and under thecontrol of the compiler: a temporary object is created as a result of an operation, including
a function call
a temporary object is destroyed when it is not needed any more
(as an operand of another operation), sooner or later (the matterof the compiler)
Temporary objects are those created as results ofoperations, including results of function calls. They arealways anonymous:double f(double), log(double);int n = i + j k;
double d = f(u)+log(x);int m = aCounter.val()+5;
The result of (i+j) is a temporary, anonymous int
The result of (?-k) is a temporary, anonymous int
The result of f(u) is a temporary, anonymousdouble
The result of log(x) is a temporary, anonymoudouble
The result of call aCounter.val() is a temporaryanonymous int
-
8/4/2019 Introductory Course on C++
92/209
June 2003 Copyright (C) 2003 by Dragan Miliev 92/209
Temporary ObjectsRegardless to the exact moment of their creation anddestruction, temporary objects are initialized anddestructed as all other objects: for objects of classes,constructors and destructors are called consistently
A result of a function call is a temporary, anonymous
object, created in the context of function invocation (in thecontext of an expression where the function call is), at themoment when the function returns a value. The temporaryobject is initialized with the result of the expression in thereturn statement. The semantics of this initialization arethe same as for any other initialization:X f () {return x1;
}
...f()... // an expression with a function call
The result of f() is a temporary, anonymous X, initializedat the moment of function return, as in: X temp(x1)
-
8/4/2019 Introductory Course on C++
93/209
June 2003 Copyright (C) 2003 by Dragan Miliev 93/209
Object Initialization and Destruction
In declarations, an object can be initialized using thenotation X x1 = x2, provided that the object is either of
a built-in primitive type, or of a class that has a constructorthat can be called with one actual argument. Except for asubtle difference, this is equal to the notation X x1(x2)
At all other places, an object is initialized using thenotation X x1(list_of_initializers)optional
An implicit initialization (without explicit initializers) ispossible for:
built-in types; the initial value is undefined objects of classes that have constructors that can be called with no
actual arguments
-
8/4/2019 Introductory Course on C++
94/209
June 2003 Copyright (C) 2003 by Dragan Miliev 94/209
Objects Initialization and DestructionThe order of objects creation is defined in almost all cases: for global static objects, the order is undefined except for the
objects in the same file
for local static, automatic, and dynamic objects, the order isdefined by the order of execution of their definitions or newoperators
for data member objects, the order of creation is defined by theirorder of declarations in the class, regardless to the list of theirinitializations in the class constructors
for temporary objects, the order is defined by the order ofevaluation of operations
elements of an array are created in the increasing order of theirindices; the initialization of elements is always implicit
Objects are destroyed (destructors are called for objects ofclasses): only if they have been constructed
always in exactly the reverse order of their creation
-
8/4/2019 Introductory Course on C++
95/209
June 2003 Copyright (C) 2003 by Dragan Miliev 95
Chapter 8: Program Structure
Structure of Units
CompilationLinking
Preprocessor
-
8/4/2019 Introductory Course on C++
96/209
June 2003 Copyright (C) 2003 by Dragan Miliev 96/209
Structure of UnitsIn C and C++, a program consists of a number of units(modules), whereby a unit is one file with source code(usual extensions are .c and .cpp)
One file is a separate compilation unit: the compiler doesnot cross the boundaries of a singe file. A file is the only
scope of compilationAccording to the the general rule, a name can be used onlyif it is previously declared. Therefore, a file must have thedeclarations for all names used in it
A source file consists of declarations only (some of them
being definitions): global objects
classes and other types
functions
-
8/4/2019 Introductory Course on C++
97/209
June 2003 Copyright (C) 2003 by Dragan Miliev 97/209
B.objA.obj
int a = 3;
void f() {
...}
void g() {...f()...
...a...}
A.cpp B.cpp
Compilation
a: 3
f: ......
...
oa: 0
of: 1...
a and f must bedeclared beforeusage
int a;
void f();
This is a definition
which will causespace allocation
a: ?
...
extern int a;
void f();
This isnt a definition
og: 0
qf: ...
qa: ...
g:
...?f...
...?a...
...
-
8/4/2019 Introductory Course on C++
98/209
June 2003 Copyright (C) 2003 by Dragan Miliev 98/209
Linking
The linker has a task to collect a set of .obj files (A.obj,B.obj, C.obj, etc.) and to make an executable program(P.exe)
The linker makes it in two passes: makes a global map of .obj files and a symbol table of exported
symbols and their computed global addresses
resolves the references to imported symbols using the computedaddresses from the symbol table
B.objA.obj a: 3f: ...
...
...
oa: 0
of: 1...
og: 0
qf: ...
qa: ...
g:
...?f...
...?a...
...
A.obj
B.obj
C.obj
...
P.exe
-
8/4/2019 Introductory Course on C++
99/209
June 2003 Copyright (C) 2003 by Dragan Miliev 99/209
LinkingLibraries have the same form and meaning as ordinary .objfiles, except that they are prepared by compiling andlinking a set of source files (.lib files)
The linker treats libraries in the same way as other .objfiles
Some libraries are provided with the compiler environment(e.g., standard libraries)
Possible linker errors: a symbol not defined; the linker reports only the name of the .obj
file which imports the unresolved symbol; often very confusing,
because your code might not use the symbol at all; possible cause:the symbol is used in an included library, but the library whichdefines the symbol is not included in the linkers list
multiple definitions of a symbol; the linker reports the names of the.obj files that define the symbol; possible cause: multipledefinitions in several .cpp files
-
8/4/2019 Introductory Course on C++
100/209
June 2003 Copyright (C) 2003 by Dragan Miliev 100/209
Preprocessor
Consequence: for each program element N that is definedin a file A and should be used in many other files B,declarations must exist in all these files B
Problem: how to keep the declarations consistent in caseof modifications? Example:
A.cpp double a = 3; B.cppextern int a;
void g() {
... = a+3...}
The type of a has beenchanged into double
The extern declarationforgotten to be updated
The compiler will generatethe code that operates withan int, which is totallydifferent from the code thatdeals with a double
This error cannot be detected either by the compiler, because it does not consider cross-file
declarations (a file is an independent compilation unit)
or by the linker, because it does not have any idea about the typesof the symbols; the linker deals solely with mapping of (typeless)symbols to their addresses
-
8/4/2019 Introductory Course on C++
101/209
June 2003 Copyright (C) 2003 by Dragan Miliev 101/209
PreprocessorThe preprocessor is a program that transforms the sourcecode of a file before its compilation. It is a part of theC/C++ compiler (in a broader sense)
Thus, the compilation (in a broader sense) is performed intwo phases (or pipes): preprocessing and compilation
The preprocessor works exclusively with the source codeas a text, and transforms it into the output text that ispassed to the compiler. The preprocessor does notconsider any language-related issues, so it does notrecognize program elements
The preprocessor is controlled by the preprocessordirectives that specify the transformations of the textPreprocessor directives start with # and last till the end ofline, except when the line ends with \, when the directiveis continued in the next line
-
8/4/2019 Introductory Course on C++
102/209
June 2003 Copyright (C) 2003 by Dragan Miliev 102/209
Preprocessor
There are several preprocessor directives in C/C++. Themostly used one is#include filename
The #include directive results in the complete contents
of the included file put in lieu of the directive. The included
text is preprocessed again for eventual preprocessordirectives, e.g. other #include directives
This directive has two forms:#include the preprocessor starts searching for the
file from a predefined place, which usually stores the include fileswith the declarations of librarian elements
#include filename the preprocessor starts searching for the
file from another place, usually defined by the user, which storesthe include files of the users program
-
8/4/2019 Introductory Course on C++
103/209
June 2003 Copyright (C) 2003 by Dragan Miliev 103/209
PreprocessorThis mechanism can be used to solve the described problem.
For a .cpp file, a header file is created (.h). It consists of declarationsof the program elements that are defined in this .cpp file, and are tobe used in other files
Note that a .h file should not contain the declarations of all elementsdefined in the .cpp file, but only those that are to be used in other
files, i.e., the interface of the .cpp module. This way, encapsulation issupported at module level, although rudimentary and indirectly (notthrough a first-class language concept)
Instead of an explicitdeclaration, #include is used
A.cpp int a = 3; B.cpp#include A.h
void g() {
... = a+3...}
extern int a;A.h
P
-
8/4/2019 Introductory Course on C++
104/209
June 2003 Copyright (C) 2003 by Dragan Miliev 104/209
PreprocessorThe effect is that the compiler encounters the same codeas before, but the difference for the programmer issignificant: the declarations are now localized in onephysical place, making modifications easier and error-free
As a result, when a .h file is modified, all .cpp files that
include it must be recompiled (including transitiveinclusions), which assumes that the compiler compiles thedirectives in .h files, too (at least in order to create itssymbol table)
The programming environment may help in reducing
recompilation by the make procedure, which selectivelyand automatically recompiles only necessary .cpp files.However, the programmers should try their best to reducecompilation dependences between files, especially in largeprojects
P
-
8/4/2019 Introductory Course on C++
105/209
June 2003 Copyright (C) 2003 by Dragan Miliev 105/209
PreprocessorAnother directive is #define. It defines a symbol within
the preprocessor (in its symbol table, which has nothing todo with the compilers one), and optionally replaces eachoccurrence of that symbol with the defined text (a macroreplacement):
#define _A_h#define N 10#define max(a,b) (((a)>=(b))?(a):(b))
int a[N];
voidf (int a, int b){...
int c = max(x/3,y+1);
...}
Simply introduces a new symbol _A_h into the
preprocessors symbol tableIntroduces a new symbol N into thepreprocessors symbol table. Every occurrenceof N in the text will be replaced with the text 10
Introduces a new symbol max into thepreprocessors symbol table. Every occurrenceof max(?,?) in the text will be replaced with thegiven text, but the parameters will be replacedproperly (parameterized replacement)The compiler will see: int a[10];
The compiler will see:
int c = (((x/3)>=(y+1))?(x/3):(y+1));
P
-
8/4/2019 Introductory Course on C++
106/209
June 2003 Copyright (C) 2003 by Dragan Miliev 106/209
Preprocessor
Header files often contain definitions of classes (whichdeclare the members):
class Counter {
public:Counter(int);
int val();void inc();
private:
int counter;
};
Counter.h
#include Counter.h
Counter::Counter (int i) :
counter(i) {}
int Counter::val () {
return counter;
}...
Counter.cpp
The entire definition of the class Counter isneeded for the definitions of its memberfunctions.Caution: multiple definitions of a class are not allowed,
even when completely identical
P
-
8/4/2019 Introductory Course on C++
107/209
June 2003 Copyright (C) 2003 by Dragan Miliev 107/209
PreprocessorProblem: what if a .h file witha class definition is includedseveral times in a .cpp file,either directly or indirectly?The compiler will encounter
multiple class definitions andwill report an error!
A.h
B.h
C.h
D.h
X.cpp
The directives #ifdef/#endif and #ifndef/#endif
process the enclosed text conditionally: the enclosed text is
passed to the output of preprocessing only if the specifiedsymbol is (not) defined in the preprocessors symbol table:#ifdef _A_h... // some code that is compiled only if
... // the symbol _A_h is defined#endif
P
-
8/4/2019 Introductory Course on C++
108/209
June 2003 Copyright (C) 2003 by Dragan Miliev 108/209
PreprocessorThese directives are used: to solve the multiple-class-definition problem: enclose the code of
each header file like this:#ifndef _A_h
#define _A_h... // The code of the header file;
// it will be transferred to the compiler// only the first time it is included
#endif
to enclose platform-dependent code:#ifdef Windows
... // Windows-dependent code
#elif defined(Linux)... // Linux-dependent code
#endif
-
8/4/2019 Introductory Course on C++
109/209
June 2003 Copyright (C) 2003 by Dragan Miliev 109
Part III: Procedural Elements
Operators and Expressions
StatementsFunctions
-
8/4/2019 Introductory Course on C++
110/209
June 2003 Copyright (C) 2003 by Dragan Miliev 110
Chapter 9: Operators and Expressions
Expressions
OperatorsLvalues
Overview of Selected Operators
Summary of Operators
E i
-
8/4/2019 Introductory Course on C++
111/209
June 2003 Copyright (C) 2003 by Dragan Miliev 111/209
ExpressionsAn expression is an element of a program that consists ofoperands (types, objects, literals, or functions) andoperations, and returns a result. The operations arespecified using the built-in operators
An operation takes some operands and produces a result;the result may be used as an operand of anotheroperation, making compound expressions:a+b*ci + p->val()- b
-
8/4/2019 Introductory Course on C++
112/209
June 2003 Copyright (C) 2003 by Dragan Miliev 112/209
ExpressionsThere is a default order of computation defined by: the priority of operators and
their direction of grouping: left to right or right to left, in cases aresult of an operator is used as an operand of the same operator
It can be modified by parentheses as usual (subexpressions):a+b*c // evaluated as a+(b*c);
// * has a higher priority than +
(a+b)*c
cout
-
8/4/2019 Introductory Course on C++
113/209
June 2003 Copyright (C) 2003 by Dragan Miliev 113/209
OperatorsC and C++ are very rich in operators. A major part of thecomputation in a typical C/C++ program is in operationswithin expressions
A side effect occurs when a function/operation that returnsa result also modifies the state of its environment (e.g. thevalues of global variables or actual arguments/operands).In the classic theory of programming, side effects areconsidered harmful, since they reduce program readability,because functions, the focus of which is to produce aresult, have unexpected effects
As opposed to this belief, many operators in C/C++ haveside effects: they modify their operands. For most of them,the side effect is their primary role!
This is a result of the fact that C was dedicated to conciseand effective expressions, which became very popular
Operators
-
8/4/2019 Introductory Course on C++
114/209
June 2003 Copyright (C) 2003 by Dragan Miliev 114/209
OperatorsExample: the operator ++ increments the operand andreturns a value. It has two forms, prefix and postfix: ++operand: increment the operand, and return the new value
operand++: increment the operand, and return its old value
Similar holds for decrementing (--)
(Hence the name of C++ - an incremented C; skeptics:what is the value of C++? :)a = i++; // a gets value of i before incrementb = --k; // b gets value of k after decrement
Assignment is also an operator: except from assigning thevalue to its left operand (side effect!), it returns theassigned value as its result; it groups from right to left:a = b = c // evaluated as a=(b=c)
x = y = f()+z // evaluated as x=(y=(f()+z))
Operators
-
8/4/2019 Introductory Course on C++
115/209
June 2003 Copyright (C) 2003 by Dragan Miliev 115/209
OperatorsThere are operators of compound assignment: a+=bmeans the same as a=a+b, except that the expression a iscomputed only once:a += b
x -= y++u *= v+3
w /= z--*p++ += 3 // evaluated as (*(p++))+=3;
// not equivalent to *p++ = *p++ + 3,// because p is incremented twice in
// the latter
Lvalues
-
8/4/2019 Introductory Course on C++
116/209
June 2003 Copyright (C) 2003 by Dragan Miliev 116/209
LvaluesApart from checking the types of operands an other thingswhen analyzing expressions, the compiler checks theconsistency of the lvalue property of operators operands
Lvalue is a property of a program element; it is a Booleanproperty: an element is or is not an lvalue: a name of an object or a function is an lvalue for each built-in operator, it is defined whether it requires an
operand that is an lvalue, and whether its result is or is not anlvalue
In most cases, an lvalue is an element that refers to asound object in memory (but not a temporary object),although names of functions are also lvalues
Lvalues
-
8/4/2019 Introductory Course on C++
117/209
June 2003 Copyright (C) 2003 by Dragan Miliev 117/209
LvaluesIn most cases, the fact that an operator requires an lvaluemeans that the operator requires a sound object inmemory. All operators that have side effects on anoperand require that the operand is an lvalue
The fact that an operator produces an lvalue as its result
means that its result refers to a sound object and that itcan be used as an operand of another operator thatrequires an lvalue
Examples:
operator = requires an lvalue as its left operand (to produce theside effect), but not for its right operand; operators +, -, etc. donot result in lvalues:a = (b+c) // correct: a is an lvalue
(a+b) = c // incorrect: a+b is not an lvalue
Lvalues
-
8/4/2019 Introductory Course on C++
118/209
June 2003 Copyright (C) 2003 by Dragan Miliev 118/209
Lvalues operator = produces an lvalue, too; it refers to the same object to
which the left operand (as an lvalue) refers to:(a = b) = c // correct: a=b is an lvalue
operator & requires an lvalue, but does not produce an lvalue; incontrast, operator * (pointer dereferencing) does not require anlvalue, but produces an lvalue, which refers to the object pointedto by the pointer operand:&a // correct: a is an lvalue&a = ... // incorrect: &a is not an lvalue&(a+3) // incorrect: a+3 is not an lvalue*(p+3) // correct: * does not require an lvalue*(p+3)=...// correct: *(p+3) is an lvalue
operation a
-
8/4/2019 Introductory Course on C++
119/209
June 2003 Copyright (C) 2003 by Dragan Miliev 119/209
LvaluesThe term lvalue has its origin in something that may bethe left operand of assignment, although all lvaluescannot be that
A modifiable lvalue is an lvalue that is not a function,array, or a constant object. Only modifiable lvalues can be
left operands of assignments:int a[N];a = b+3; // incorrect: a is not a modifiable lvalue
voidf();f = ...; //incorrect: f is not a modifiable lvalue
&f // correct: f is an lvalue, & does not require// a modifiable lvalue
Overview of Selected Operators
-
8/4/2019 Introductory Course on C++
120/209
June 2003 Copyright (C) 2003 by Dragan Miliev 120/209
Overview of Selected OperatorsFunction call is also an operator that results in a temporaryobject initialized with the return expression:expr(listOfArgs)
There is an operation of constructing a temporaryanonymous object by explicit constructor call:Counter(0)
Member access operators . and -> require an object and apointer to an object as their left operands, respectively,and a member name as their right operand. Their result isan lvalue only if the member is an lvalueIncrement (++) and decrement (--) operators requirenumeric operands. The result of the prefix form is, and ofthe postfix form is not an lvalue:++i = 5; // correct: ++i is an lvaluei-- = 5; // incorrect: i is not an lvalue
Overview of Selected Operators
-
8/4/2019 Introductory Course on C++
121/209
June 2003 Copyright (C) 2003 by Dragan Miliev 121/209
Overview of Selected OperatorsOperator sizeof returns the size of the operand. The
operand (as an expression) is not evaluated at runtime,but only its type is determined at compile time. The unit ofmeasurement is sizeof(char)==1, not a byte! Twoforms: sizeof expr: sizeof (a+p->inc())
sizeof(type): sizeof(Counter)
Logic negation operator ! requires a numeric, a pointer, oran object that may be converted to a numeric or a pointeras its operand: if the operand is equal to 0 (symbolic value for pointers does not
point to an object), which is treated as False, the result is 1 if the operand is not equal to 0 (symbolic value for pointers does
point to an object), which is treated as True, the result is 0if (!p) ... // if p is not 0
Overview of Selected Operators
-
8/4/2019 Introductory Course on C++
122/209
June 2003 Copyright (C) 2003 by Dragan Miliev 122/209
Overview of Selected OperatorsArithmetic operators * (multiplication) and / (division)
require numeric operands, and % (remainder) requiresintegral operands. If both operands are integral, the resultis integral; otherwise, the result is a floating-point:a%b // the remainder of division a/b
Shift operators ab require integral operands
and result in the binary representation ofa shifted b bitsleft/right; they do not have side-effectsRelational operators == (equal to), != (not equal to), ,= result in 1 (true) or 0 (false)
Bit-wise operators & (and), | (or), ^ (exclusive or) requireintegral operands and operate bit-by-bitLogic operators && (and) and || (or) require numericoperators or pointers and return 0 (false) or 1 (true); theyconsider whether an operand is equal to 0 (False) or not
(True)
Overview of Selected Operators
-
8/4/2019 Introductory Course on C++
123/209
June 2003 Copyright (C) 2003 by Dragan Miliev 123/209
Overview of Selected OperatorsOperator ?: is the only ternary operator:a?b:cFirst, a is evaluated. It must be of integral type or apointer. If its value is not equal to 0 (true), b is evaluatedand returned as the result. If the value ofa is equal to 0
(false), c is evaluated and returned as the result. Note thatonly one of the operands is evaluated, never both
Sequence operator (,) is a binary operator: a,b evaluatesa first, then b, and returns the result ofb as its result. It
groups from left to right:a,b,c // evaluated as (a,b),c
It is used when the syntax requires one expression, andyou want to do several operations:for (int i=0, j=0; i
-
8/4/2019 Introductory Course on C++
124/209
June 2003 Copyright (C) 2003 by Dragan Miliev 124/209
Summary of OperatorsThe following table presents all operators in C++. Theoperators are grouped into groups of the same priority,while the groups are ordered by priority (decreasing). Thetable gives: the operator and its meaning
the way of grouping: L: from left to right R: from right to left
N/A: not applicable, because the result of the operator cannot be usedas an operand of the same operator
lvalue: whether the result is an lvalue:
Y: always N: never
Y/N: depends on one of the operands
usage: the way of usage; if an operand is expr, the operand is anexpression that does not need to have an lvalue result; if anoperand is lvalue, an lvalue expression is required as the operand
Summary of Operators
-
8/4/2019 Introductory Course on C++
125/209
June 2003 Copyright (C) 2003 by Dragan Miliev 125/209
Summary of Operators
rator Meaning Grouping Lvalue Usage:: scope resolution L Y/N class_name:: member
:: global name access Y/N :: name
[] indexing L Y expr[expr]
() function call L Y/N expr(list_of_expr)
() object construction N type_name(list_of_expr). member access L Y/N expr. name-> indirect member access L Y/N expr-> name
++postfix increment L N lvalue++
-- postfix decrement L N lvalue--
++ prefix increment R Y ++ lvalue
-- prefix decrement R Y --lvaluesizeof size ofobject R N sizeofexpr
sizeof size oftype R N sizeof(type)
new dynamic object creation N newtypedelete dynamic object destruction N delete expr
~ bitwise complement R N ~expr! logic negation R N !expr
- unary minus R N - expr
+ unary plus R N + expr
& address of R N &lvalue
* pointer dereferencing R Y *expr
-
8/4/2019 Introductory Course on C++
126/209
Summary of Operators
-
8/4/2019 Introductory Course on C++
127/209
June 2003 Copyright (C) 2003 by Dragan Miliev 127/209
Summary of Operators
= simple assignment R Y lvalue = expr*= multiplication and
assignmentR Y lvalue *= expr
/= division and assignment R Y lvalue /= expr
%= remainder and assignment R Y lvalue %= expr+= addition and assignment R Y lvalue += expr
-= subtraction and assignment R Y lvalue -= expr
>>= sift right and assignment R Y lvalue >>= expr
-
8/4/2019 Introductory Course on C++
128/209
June 2003 Copyright (C) 2003 by Dragan Miliev 128
Chapter 10: Statements
Basic Statements
Conditional StatementsLoop Statements
Other Statements
Basic Statements
-
8/4/2019 Introductory Course on C++
129/209
June 2003 Copyright (C) 2003 by Dragan Miliev 129/209
Basic StatementsStatements encompass some computation, but do not
produce results as expressionsA declaration is a kind of a statement: a declaration mayoccur wherever a statement may occur (not only at thebeginning of a block)
An expression terminated with ; is a statementA compound statement (a block) is a sequence of statementsenclosed in braces {}. The statements in a block areexecuted in order, sequentially. A block may occur wheneverone statement is expected, and you need more:
{ // start of a blockint a, c=0, d=3; // declaration as a statement;a=(c++)+d; // expression as a statement;int i=a; // declaration as a statement;i++; // expression as a statement;
} // end of the block
Conditional Statements
-
8/4/2019 Introductory Course on C++
130/209
June 2003 Copyright (C) 2003 by Dragan Miliev 130/209
Conditional StatementsConditional statementif:if (expr) then-statement else else-statement
the else else-statement part is optional
if you need more than one statement, use a block
the expr must result in a numeric, Boolean, or pointer value
if the value of expr is not equal to 0 (true), then-statement isexecuted and the if statement is completed; otherwise, else-statement is executed, and the if statement is completed
if (a++) b=a; // equivalent with if (a++ !=0)...
if (c) a=c; // equivalent with if (c!=0)...
else a=c+1;
Conditional Statements
-
8/4/2019 Introductory Course on C++
131/209
June 2003 Copyright (C) 2003 by Dragan Miliev 131/209
Conditional StatementsConditional statementswitch:
switch (expr) {case const1 : list-of-statements1case const2 : list-of-statements2...case const
n: list-of-statements
n
default : list-of-statementsd}
the default part is optional expr must evaluate to an integral value
the control passes directly to the case label that has the guard expri equalto the result of expr, or to the default part otherwise
the execution is continued through the rest of the branches; if you wantonly one branch to be executed, use the break statement to exit the
switch:switch (status) {case ok: commit();break;case failed: alert();break;case refused: retry();break;
}
Loop Statements
-
8/4/2019 Introductory Course on C++
132/209
June 2003 Copyright (C) 2003 by Dragan Miliev 132/209
Loop StatementsLoop statementfor:for (init-statement expr1 ; expr2) statement the init-statement is an expression or a declaration; it always
ends with a semicolon ;
if you need more than one statement in statement, use a block
the expr1 must result in a numeric, Boolean, or pointer value
this is a while loop with an exit on topinit-statement
statement
expr1
expr2
==0
!=0
init-statement, expr2, andstatement may be omitted
expr1 is optional; 1 (true) is assumed if it
is omitted
Loop Statements
-
8/4/2019 Introductory Course on C++
133/209
June 2003 Copyright (C) 2003 by Dragan Miliev 133/209
Loop StatementsExample: a usual counter loop in which the index i goes
from 0 to n-1:for (int i = 0; i
-
8/4/2019 Introductory Course on C++
134/209
June 2003 Copyright (C) 2003 by Dragan Miliev 134/209
Loop StatementsLoop statementwhile is a special case offor:
while (expr) statement
is equivalent tofor (;expr;) statement
Loop statementdo-while is a loop with the exit at the
end:do statementwhile (expr);is equivalent tostatement
while (expr) statement
Example:voidstrcopy (char* p, char* q) {while (*p++ = *q++); // Try to analyze this!
}
Other Statements
-
8/4/2019 Introductory Course on C++
135/209
June 2003 Copyright (C) 2003 by Dragan Miliev 135/209
Other StatementsThe return statement returns from a function, with an
optional result of the associated expression:return expr;
The break statement breaks the first enclosing loop orswitch:
while () { // Endless loop
...if (...)break;...
}
The continue statement skips the rest of a loop bodyand passes to the next loop iteration:for (...) {...if (...) continue;...
}
Other Statements
-
8/4/2019 Introductory Course on C++
136/209
June 2003 Copyright (C) 2003 by Dragan Miliev 136/209
Other StatementsThe goto statement jumps to the specified label. Statements in
functions may be labeled; labels have a function scope (visiblethroughout the entire function body, but not outside)
The goto statement should not be used in structured programming,
except for some structured constructs, such as exits from deeplynested loops:
for (...) {...
for (...) {
...for (...) {
...if
(...)goto
exit;...
}
}}
exit: ...
-
8/4/2019 Introductory Course on C++
137/209
June 2003 Copyright (C) 2003 by Dragan Miliev 137
Chapter 11: Functions
Declaration and Invocation
InliningDefault Argument Values
Function Overloading
Declaration and Invocation
-
8/4/2019 Introductory Course on C++
138/209
June 2003 Copyright (C) 2003 by Dragan Miliev 138/209
Declaration and InvocationFunctions can be members of classes (i.e., have a class
scope) or non-members (global functions)Functions are the only kind of subprograms in C/C++:procedures are special kinds of functions that return noresult (void as the return type)
There is no static function nesting (nesting of functiondefinitions) as in Pascal, for example. Dynamic functionnesting (of function calls) is allowed, including recursion
A function may, but need not have arguments. Argumentsare passed by value (C/C++), or by reference (C++)
A declaration of a function that is not a definition does notneed to have names of arguments (desirable only forreadability purposes):int strcompare (char*,char*);voidstrcopy (char* to, char* from);
Declaration and Invocation
-
8/4/2019 Introductory Course on C++
139/209
June 2003 Copyright (C) 2003 by Dragan Miliev 139/209
Declaration and InvocationA function definition contains the function body, which is ablock. A function may return the result through thereturn statement:int Counter::inc () {
return ++counter;
}
A function is called by the () operator. The result of a
function call is a temporary object, created at the place ofinvocation, at the moment of function return, andinitialized with the result of the return expression. The
semantics of this initialization are the same as any otherinitialization:a = ptrCounter->inc() + b;
Declaration and Invocation
-
8/4/2019 Introductory Course on C++
140/209
June 2003 Copyright (C) 2003 by Dragan Miliev 140/209
The type of a function is determined by: the number and types of formal arguments; T* and T[] are
considered the same as types of arguments
the type of the result; a function cannot return an array, only apointer to (the first element of) an array
Pointers to functions may be defined. At runtime, a pointer
to a function may be redirected to point to differentfunctions of the same type. A function may be called overa pointer to it. This concept is used to dynamically bindfunction calls (the traditional call-back mechanism that isobsolete in OO programming):
int f(int,int), g(int,int);int (*p)(int,int) = &f;(*p)(5,3);p = g;p(7,3);
p is a pointer to a function that acceptsan int and returns an int: int(*)(int,int)
p points to f
call the function pointed to by p; that is f
the same as p = &g, because a function may beconverted into a pointer to the function
the same as (*p)(7,3), because the function calloperator () may accept a function or a pointer to afunction as its first operand
Declaration and Invocation
-
8/4/2019 Introductory Course on C++
141/209
June 2003 Copyright (C) 2003 by Dragan Miliev 141/209
When a function is called, the formal arguments are
created as local automatic objects, initialized with theactual arguments. The semantics of this initialization arethe same as any other initiali