Transcript Lecture 14
OOMPA Lecture 14
Exam solutions
Together demo
Introduction to C++
Together
Together ( http://www.togethersoft.com )
Model-build-deploy tool
Creation, editing of UML diagrams
Synchronization between UML diagrams and source code
GoF patterns
JAVA, C++, C##
Free limited version available at
http://www.togethercommunity.com/
Demo ..\..\..\..\Together5.5\bin\Together.exe
Exam
Master solution available on course webpage
Evaluation scheme will be available
Exam results by November 2nd, 2001
Grading
22 out of 38 betyg 3
26 out of 38 betyg 4
30 out of 38 betyg 5
Question 1
Question 1: (1) Abstract methods have
a. No program code in the subclass FALSE
b. Program code in the defining class FALSE
c. Program code in the subclasses CORRECT
d. No program code in the defining class CORRECT
e. (b) and (c)
f. (c) and (d)
g. (a) and (b)
Correct answer : f
Question 2
Question 2: (1) An association is
a. A straight line in a class diagram FALSE
b. Represented by a noun that describes the interaction FALSE
c. A relationship between instances of classes CORRECT
d. A relationship between classes FALSE
e. (a) and (d)
f.
(b) and (c)
Correct answer: c
Question 3
Question 3: (1) Aggregation
a.
Means an object is built of other objects FALSE
b. Means an object contains other objects CORRECT
c.
Is always of multiplicity 1-* FALSE
d. Is “is a kind of” relationship FALSE
e.
(b) and (c)
f.
(a) and (d)
Correct answer: b
Question 4
Question 4: (1) Which of the following statements are true for
statechart diagrams
a. An event is caused by a transition. FALSE
b. An object has to be in exactly one state at a time. CORRECT
c. A state is a condition needed for a transition to occur. FALSE
d. In a transition one or more attributes change their value. MAYBE
e. (a) and (c)
f.
(b) and (d)
Correct answer: f , but b also counts as a correct answer since
changing state does not necessarily means that the object changes
its attributes, but for example it could simply change the control flow.
Question 5
Question 5: (1) Generalization is
a. building objects from parts FALSE
b. a “has a”-relationship FALSE
c. a “is a kind-of” relationship CORRECT
d. realized by means of inheritance CORRECT
e. realized by means of composition FALSE
f.
(a) and (b)
g. (c) and (d)
h. (a) and (e)
i.
(a), (b) and (e)
Correct answer: g
Question 6
Question 6: (1) Polymorphism
a. requires abstract classes FALSE
b. is realized by means of static binding FALSE
c. is realized by means of dynamic binding CORRECT
d. enables subclasses to override the method of a superclass
CORRECT
e. (a),(c) and (d)
f.
(a) and (c)
g. (c) and (d)
h. (b) and (d)
Correct answer: g
Question 7
Question 7: (4) Which of the following phrases best describe the
design patterns in the list. Match 10 out of 14 phrases with the 10
concepts below.
a. Proxy- Provide a placeholder for another object to control
access to it.
b. Adapter- Convert the interface of a class into another
interface clients expect.
c. Low Coupling- Supports low dependency and low impact of
change.
d. Composite - Lets clients treat individual and group of objects
uniformly.
e. Factory Method - Lets a class defer instantiation to
subclasses.
f.
Abstract Factory - Provide an interface for creating families of
related objects without specifying their concrete classes.
g.
Singleton - Provides global access to a unique instance
Question 7
h. Observer- When one object changes its state the state of
dependant objects is synchronized.
i. Expert - A class that has the information necessary to fulfill
a responsibility.
j. Pure Fabrication - Assign responsibilities to an artificial class
to support high cohesion and low coupling.
k. Controller - An object responsible for receiving or handling
system events.
l. Strategy - Define a family of algorithms and make them
interchangeable.
m. Façade - Provide a unified interface to a set of interfaces
in a subsystem.
n.
Mediator - An intermediate object that decouples other
objects.
Question 8
Question 8: (2) Describe in two sentences what is the
difference between object oriented analysis and design.
OO analysis is concerned with
finding and describing objects or concepts in the
problem domain.
what needs to be done.
defining the problem/requirements (do the right
thing)
OO design is concerned with
defining software objects and how they collaborate
how is it done
conceiving a solution to the problem (do the thing
right)
Question 9
Question 9: (2) What is (usually) the multiplicity (1..*,
*..*, etc.) of the following associations?
a.
Brother is sibling of sister *-*
b.
Child is a descendant of parent 1..*-2
c.
Person is married with person 0,1-0,1
d.
Twin is sibling of twin 1-1
e.
Student attends course *-* or *-1..*
f.
Flight flies to airport *-1 or *-*
g.
Order contains items 1-1..*
h.
Customer purchases product *-* or 0,1-*
Question 10
Question 10: (2) Describe in two sentences the roles
of inception and elaboration within the unified
process.
Answer: Inception is a feasibility study which
envisions the product scope, approximate vision and
business case. Elaboration generates a refined vision,
iterative implementation of core architecture,
resolution of high risks, identification of most
requirements and scope. (see Larman pages 35 and
109).
Question 11
Question 11: (1) In the unified process requirements
are described by
a.
Design model FALSE
b.
Domain model FALSE
c.
Use case model CORRECT
d.
(a) and (b)
e.
(a) and (c)
f.
(b) and (c)
Correct answer: c
Question 12
Question 12: (1) Extreme Programming advocates
a.
continuous integration CORRECT
b.
a sequential, linear lifecycle FALSE
c.
Refactoring CORRECT
d.
(a) and (b)
e.
(a) and (c)
f.
(b) and (c)
g.
(a), (b) and (c)
Correct answer: e
Question 13
Question 13: (8) A vending machine offers two different products A and
B. Product A costs 4 SEK, product B 6 SEK. The customer inserts one coin
at a time into the slot. The machine accepts coins in denominations of 1,
5 or 10 SEK. The machine displays the amount available for purchasing
products. The machine has three buttons, button A to dispense product
A, button B to dispense product B and button C to obtain change. At any
time the customer can press button C to collect her change or amount
paid, even if no purchase occurred previously. The customer can press
buttons A and B at any time, but the machine only dispenses the
corresponding product if the current amount paid is equal to or exceeds
the product price. It is possible to make multiple purchases with one
payment by using the remaining amount for another purchase (for
example inserting a 10 SEK coin and purchasing product A twice and
obtain 2 SEK change or for example inserting a 5 SEK coin, purchasing
product A, inserting another 5 SEK coin and purchasing product B).
a. Draw a state diagram for the vending machine.
b. Draw a system sequence diagram for a scenario in which the
customer inserts two 5 SEK coins, purchases product B and collects her
change. Illustrate the information or product the vending machine shows
or dispenses to the customer.
Question 13 State-Diagram
States : Idle, Coins Inserted, Product A dispensable,
Product A & B dispensable
Events : insert coin, button A, button B, return button
Actions : dispense A, dispense B, return change
Question 13
[total amount < 4 SEK]
insert 1 SEK coin
return button/
return change
Coins
Inserted
[total amount >= 4 SEK < 6 SEK]
insert coin
insert
return button /
1 SEK coin return change
Idle
Product A
insert 5 SEK coin dispensable
insert
return button/
5 or 10 SEK coin
return change
insert
10 SEK coin
Product A or B
dispensable
insert coin
[total amount < 6 SEK]
1 SEK coin
[total amount >= 6 SEK]
insert coin
Question 13
Coins
Inserted
Idle
[change=0 SEK]
button A/
dispense A
[amount >= 1 SEK < 4 SE
button A / dispense A
Product A
dispensable
[amount >= 1 SEK and< 4 SEK]
button A or button B/
dispense A or B
[ a m o u n t = 0 S E K ] Product A or B
[amount >= 4 SEK and
b u t t o n A o r b u t t o n dispensable
B /
button A or button
dispense A or B
dispense A or B
[amount >= 6 SEK]
button A or button B /
dispense A or B
Question 13
:System
Customer
insert(5 SEK)
show amount
insert(5 SEK)
show amount
dispenseB()
product B, show amount
getchange()
change due, show amount
Question 14
Question 14: (4) Draw the collaboration diagram that
corresponds to the following sequence diagram
:ClassA
:ClassB
:ClassC
foo()
bar()
gnu()
plop()
clack()
oink()
nop()
wul()
Question 14
1:bar()->
2:oink()->
foo()->
:ClassA
1.3:clack()<-
:ClassB
2.1.1: wul() ^
1.1: gnu() v
1.2: plop() v
2.1: nop() v
:ClassC
Question 15
Question 15: (8) Draw a domain model as a UML class diagram,
containing concepts, generalizations, named associations with
multiplicity (composition and aggregation where applicable) and
attributes for the following domain. The task is to design a software
that helps you keep track of your collection of audio CDs. One
distinguishes between two different types of releases, namely maxiCDs and album CDs. Each release (album or maxi-CD) contains one or
several recordings, a recording is a particular song performed by a
particular artist, for example the album “Hot Rocks” by the Rolling
Stones contains recordings of the songs “Time is on my side”, “Heart of
Stone”, “Play with Fire” etc. Each recording has a playing time, for
example “Time is on my side” has a playing time of 5:23. The same
recording might occur on different releases, for example the original
studio album and a “best-of” album..
Question 15
The same or a different artist might perform the same song in different
recordings, for example the song “American Pie” by Don Mc Lean and
Madonna or “Sympathy for the Devil” in a live and a studio version by
the Rolling Stones. One distinguishes between solo artists (e.g.
Madonna) and bands composed of artists, for example Paul McCartney,
John Lennon, Ringo Starr and George Harrison are members of the
Beatles. An artist can occur on different recordings in different roles,
either as a solo artist or a band member, for example Sting as a solo
artist or as a member of the band Police. A song has a title and is
composed by one or several composers, for example the song “Hey
Jude” is composed by Paul Mc Cartney and John Lennon. Each release
has a title, release date, music label and a playing time that is
calculated as the accumulated playing time of the recordings on the
release. A release is usually associated with one particular solo artist or
band, for example the album “Abbey Road” with the Beatles. Still, this is
not always the case for example in case of movie sound tracks or
events such as Woodstock, which feature a number of different artists
on the same release
Question 15
Concepts: composer, song, recording, release, artist,
solo artist, band, album, maxi-CD
composes
Composer 1..*
1..*
+name
Song 1
records
+title
features
1..* 1..*
contains
Recording1..*
+duration
records
1 0,1
Artist
1..*
+name
Release
+year
+label
+/playing time
members
Solo Artist
1..*
Band
Album
Maxi-CD
Differences between JAVA and C++
C++ uses pointers instead or in addition to JAVA
references
C++ also uses references but in a different way than
JAVA
C++ has no garbage collection, which means that
objects created with new have to be destroyed with
delete in order to avoid memory leaks
JAVA is an interpreter language (virtual machine),
portable across platforms (byte code is somehow
between assembler code and source code)
C++ programs need to be compiled separately for each
target platform.
Additonal Features of C++
Pointers
Operator overloading
Template methods and classes
Multiple inheritance
Standard Template Library (container classes)
Hello World
#include <iostream> // input-output library
int main()
// function main
{
cout << ”Hello World” << endl;
// standard output stream
}
Output Using Cout
• The identifier cout is actually an object. It is predefined
in C++ and corresponds to the standard output stream.
• A stream is an abstraction that refers to a flow of data.
• The operator << is called the insertion or put operator
and can be cascaded (like arithmetic operators +,-,*,/)
• It directs the contents of the variable to the right to
the object to the left.
string str=”Hello world”;
int i=8;
cout << str << endl; // endl inserts a new line
cout << ”i=” << i << endl; // cascade operator <<
standard
output
device
cout
<<
variable/
constant
Input Using Cin
• The object cin is predefined in C++ and corresponds
to the standard input stream.
• The >> operator is called the extraction or get operator
and takes the value from the stream object to the left
and places it in the variable on its right.
• The stream represents data coming from the keyboard
int temperature;
cout << ”Enter temperature in Celsius: ”;
cin >> temperature;
standard
input
device
cin
>>
variable
Library Functions
• Many activities in C/C++ are carried out by library functions.
• These functions perform file access, data conversion and
mathematical computations.
#include <math> // includes the declaration file for
// mathematical functions
int main()
{
double x=3.14;
cout << ”sin(3.14)= ” << sin(x) << endl;
}
Header Files
• a header file contains the declaration of functions
you want to use in your code
• the preprocessor directive #include takes care of
incorporating a header file into your source file
• example:
#include <math>
#include ”myprog.h”
• the brackets <> indicate that the compiler first searches
the standard include directory which contains the
standard C/C++ header files first
• the quotation marks indicate that the compiler first searches
for header files in the local directory
• if you do not include the appropriate header file
you get an error message from the compiler
Header and Library Files
#include <somelib>
myprog.C
#include ”myprog.h”
library header file
somelib.h
user header file
myprog.h
compiler
object file
myprog.o
library file
linker
executable file
myprog
libm.a
Makefile
A Makefile is a recipe for how to ”cook” a product
The necessary operations are divided into single steps which partially
depend on each other
Example: Change a flat tire on a car
Actions:
get_jack, get_spare_tire, lift_car, remove_flat_tire, attach_spare_tire,
lower_car, stow_away_jack, stow_away_flat_tire, drive_away
Dependencies:
lift_car : get_jack
remove_flat_tire : lift_car
attach_spare_tire : get_spare_tire
stow_away_flat_tire : remove_flat_tire
lower_car : attach_spare_tire
stow_away_jack : lower_car
drive_away : stow_away_flat_tire stow_away_jack
Makefile
user header file
lab1.C
compiler
mat.h
mat.C
#include ”mat.h”
g++ –c mat.C
source
file
compiler
g++ –c lab1.C
lab1.o
mat.o
object file
linker
g++ lab1.o mat.o -lm
a.out
executable
file
libm.a
math library file
Makefile
Assume you have two source files mat.C and lab1.C
from which you are supposed to create a program a.out
all: a.out
# lab1.o depends on lab1.C and mat.h
lab1.o: lab1.C mat.h
g++ -c lab1.C
#mat.o depend on mat.C and mat.h
mat.o: mat.C mat.h
g++ -c mat.C
# a.out depends on lab1.o and mat.o
a.out: lab1.o mat.o
g++ mat.o lab1.o -lm
Makefile
# define a variable CC for the name of the compiler
CC=g++
# define compiler flags for warnings and debugging
CCFLAGS=-Wall -g
# define a variable OBJS for the objects needed to build
the program
OBJS=mat.o lab1.o
# overall target
all: a.out
# explain for all cc source files how to build an object file
%.o: %.C
$(CC) $(CCFLAGS) -c $<
a.out: $(OBJS)
g++ $(OBJS) -lm
Passing by Value
• when passing arguments by value, the function creates
new local variables to hold the values of the variable
argument
• the value of the original variable are not changed
void f(int val) // the parameter val holds a local copy of the
// variable argument
{
val++;
}
int x=4;
f(x); // call function f passing x by value
cout << x; // x still has the value 4
Passing by Reference
• a reference provides an alias –a different name– for a variable
• when passing arguments by reference the local variable
is an alias for the original variable
• the memory address of the variable is passed such that the
function can access the actual variable in the calling program
void swap (int & a, int& b) // call by reference a,b are aliases
{
int tmp;
tmp = a;
a = b;
b = tmp;
}
int x=3; int y=5;
swap(x,y); // call by reference : a,b are aliases for x,y
Const Parameters/Variables
• passing by reference is efficient when passing large data
structures as it avoids copying the variable
• a const reference guarantees that the function cannot
modify the value of the passed argument
• an attempt to change the value of a const variable or
parameter is caught at compile time
void f( int& a, const int& b ) // argument b is constant
{
const int c=8; // defines variable c as a constant
a=5; // ok
b=7; // error: cannot modify const parameter
c=7; // error: cannot modify const variable
}
Class Definition (Interface)
class Date
{
private:
int day, month, year;
public:
Date(int d, int m, int y);
void add_year(int n);
void add_month(int n);
void add_day(int n);
void show_date();
};
// declares class name
// not visible outside the class
// member data
// visible interface
// constructor
// add n years
// add n months
// add n days
// displays date
// do not forget the ; here !!!
Class Implementation
void Date::Date(int d, int m, int y)
{
day=d;
month=m;
year = y;
}
void Date::add_month(int n)
{
month+=n;
year+= (month-1)/12;
month = (month-1) % 12 + 1;
}
Class Implementation
#include <iostream>
void Date::show_date()
// Date:: specifies that show_date is a
// member function of class Date
{
cout << day << ”.” << m << ”.” << y << endl;
}
void Date::add_year(int n)
{
year+=y;
}
void Date::add_day(int n)
{
….
}
Member Initialization
two types of member initialization in class constructor
by initialization : members are initialized before the constructor is executed
(necessary for data members tha have no default constructor)
by assignment : members are created per default constructor first and then
a value is assigned to them
Date::Date(int d, int m, int y) : day(d), month(m), year(y)
{
}
Date::Date(int d, int m, int y) // assignment initialization
{
day=d;
month=m;
year=y;
}
Constant Member Functions
A member function that is declared as constant does
not modify the data of the object
class Date
{
int month() const; // const month() does not modify attributes of Date
void add_year(int n); // non-const add_year() modifies attributes of Date
};
int Date::month() const // defined as const
{ return month; }
int Date::add_year(int n)
{ year+=n; }
Constant Member Functions
A const member function can be invoked for const and
non-const objects, whereas a non-const member
function can only be invoked for non-const objects
Date somedate(12,17,1999);
const Date christmas(24,12,2001);
int i=somedate.month(); // ok
somedate.add_year(2); // ok
int j=christmas.month(); // ok month const member function
christmas.add_year(3); // error add_year non-const member
Lecture 15
C++
Multiple Inheritance
Operator overloading
Templates
Pointers
Dynamic memory allocation
Standard Template Library
Containers
Iterators
Algorithms
Lecture Schedule
Mon 5/11/01 (Bjoern)
VisualWorks/Smalltalk
Mon 12/11/01 (Frank)
C++
Game playing (lab4)
Course evaluation
Tue 20/11/01 (Bjoern)
VisualWorks/Smalltalk
Inheritance
super class
subclass
Feature A
Feature A
Feature B
Feature B
Feature C
Feature D
Inheritance
class Date
{
public: // visible outside class scope
int Year();
…
protected: // visible to sub-classes but hidden from rest of the world
int day, month, year;
};
class DateTime : public Date
{
public:
int Hours();
…
private: // only visible to class DateTime
int hours, minutes
};
Multiple Inheritance
base class A
subclass
Feature A
Feature A
Feature B
Feature B
base class B
Feature C
Feature D
Feature C
Feature D
Multiple Inheritance
class Date
{
public:
int Year();
private:
int day, month, year;
};
class Time
{
public:
int Hours();
private:
int hours, minutes;
};
Multiple Inheritance
class DateTime : public Date, public Time
{
public:
DateTime(int d, int m, int y, int h, int mi);
…
};
DateTime::DateTime(int d, int m, int y, int h, int mi)
: Date(d,m,y), Time(h, mi)
{
}
Ambiguity in Multiple Inheritance
class Date
{
void add(int days);
};
class Time
{
void add(int minutes);
};
Class DateTime : public Date, public Time
{
};
DateTime dt(13,2,1998,23,10);
dt.add(3); // ambiguous -- will not compile
dt.Date::add(4); // uses add of class Date
dt.Time::add(5); // uses add of class Time
Ambiguity in Multiple Inheritance
class A { public: void F(); };
class B : public A { …};
class C : public A { …};
class D : public B, public C {};
D d;
d.F(); // ambiguous - won´t compile
diamond shaped
inheritance tree
class A
class B
class C
class D
Overloading Operator
Operator overloading is a useful feature of object
oriented programming
Operator overloading allows it to give normal C++
operators such as +,-,==,< additional meanings
It makes statements more intuitive and readable
for example:
Date d1(12,3,1989);
Date d2;
d2.add_days(d1,45);
// can be written with the + operator as
d2=d1+45;
Operator Overloading
The name of an operator function is the keyword
operator followed by the operator itself.
class complex
{
double re, im; // re and im part of a complex number
public:
complex (double r, double i) : re(r), im(i) {}; //constructor
complex operator+(complex c); // operator function
};
complex c1(2.2,3.0); // instantiate complex c1
complex c2(1.0,-4.5); // instantiate complex c2
complex c3=c1+c2; // shorthand notation for c1 + c2
complex c4=c1.operator+(c2); // explicit call
Overloading Unary Operators
class Date
{
Date& operator++(); // prefix increment operator
}
Date& Date::operator++ ()
{
if (++day > days_in_month())
{
day=1;
if (++month > 12)
{
month=1;
year++;
}
}
return *this;
}
Date d1(31,12,1999);
++d1; // results in 1.1.2000
Overloading Unary Operators
class Date
{
Date operator++(int); // postfix increment operator
};
Date Date::operator++ (int)
{
Date old(*this);
if (++day > days_in_month())
{
day=1;
if (++month > 12)
{
month=1;
year++;
}
}
return old;
}
Date d1(31,12,1999); Date d2;
Overloading Binary Operators
class Date
{
Date operator+(int days) const;
};
Date Date::operator+(int days) const;
{
Date tmp=*this; // copy object
for (int i=0; i < days; i++)
++tmp;
return tmp;
}
Date d1(1,4,1999);
Date d2=d1+25; // results in 26.4.2000
Overloading Binary Operators
class Date
{
Date& operator+=(int days);
// must be reference as += modifies
// the left hand argument
};
Date& Date::operator+=(int days) // return type reference to object
{
for (int i=0; i < days; i++)
*this++;
return *this; // return reference to object
}
Date d1(1,4,1999);
d1+=25; // results in 26.4.2000
Overloading Relational Operators
class Date
{
bool operator==(Date d)
{
return (day==d.day) && (month=d.month) && (year==d.year);
};
bool operator<(Date d)
{
if (year < d.year)
return true;
else
if (year==d.year) && (month < d.month)
return true;
else
return (month==d.month) && (day < d.day);
};
};
Overloading Binary Operators
int Date::operator-(Date d) const
{
int days=0;
if (*this > d)
while (*this != ++d)
days++;
else
while (*this != --d)
days--;
return days;
}
Date d1(24,4,1988);
Date d2(13,3,1998);
int diff = d1-d2; // diff = 42
Templates
A template is a place-holder for an arbitrary built-in
or user-defined data type
Templates make is possible to use one
function or class to handle many different data types
Function templates allow a parameter to assume an
arbitrary data-type
Class templates allow a member data to assume an
arbitrary data-type
Templates are another example for polymorphism
Function Templates
int max(int a, int b) // one max function for int
{
if (a>b)
return a;
else
return b;
}
double max(double a, double b) // max function for double
{
if (a>b)
return a;
else
return b;
}
Function Templates
template <class Type> // class Type placeholder for concrete data type
Type max( Type a, Type b) // substitute templateType for concrete type
{
if (a>b) return a; else return b; // identical code
}
void main()
{
int a=3, b=2;
Date d1(17,5,1998); // assume operator > is defined for class Date
Date d2(23,6,1997);
int c=max(a,b); // template T replaced with int
char z=max(’f’,’q’); // template T replaced with char
Date d3=max(d1,d2); // template T replaced with date
}
Function Templates
argument type
determines function
instantiation
int i1,i2,i3;
i3=max(i1,i2);
int max(int a, int b)
{ … };
template <class T>
T max(T a, T b)
{ … };
char c1,c2,c3;
c3=max(c1,c2);
char max
(char a, char b)
{ … };
one function template
in source file
Date d1,d2,d3;
d3=max(d1,d2);
Date max
(Date a, Date b)
{ … };
Class Templates Array.h
template <class Type> // template class Type
class Array // array of arbitrary data type
{
public:
Array(unsigned int sz);
Type& operator[](unsigned int i); // returns a reference to i-th element
Type operator()(unsigned int i); // returns the value of i-th element
private:
static int max_size=100;
unsigned int size;
Type array[100]; // placeholder for concrete data type
};
Class Templates Array.C
#include ”Array.h”
template class<Type>
Array<Type>::Array(unsigned int sz) {
if (sz > max_size)
size=max_size;
else
size=sz;
}
template class<Type>
Type& Array<Type>::operator[](unsigned int i) {
if (i<size)
return array[i];
}
template class<Type>
Type Array<Type>::operator()(unsigned int i) {
if (i<size)
return array[i];
}
Class Templates
Array<double> x(20); // instantiates a double array of size 20
Array<Date> dates(10); // instantiates a Date array of size 10
Date christmas(24,12,2001);
x[10]=5.7; // operator [] returns reference can be used on rhs
dates[3]=christmas;
x[11]=x(10)+3.4; // operator () returns value can only be used on lhs
x[0]=1.2;
for (int i=1; i<20;i++)
x[i]=x(i-1)*1.2;
for (int i=0; i<10;i++)
dates[i]++; // increment all dates by one calendar day
Class Templates
G++ has two compiler options
-fexternal-templates
-fno-external-templates
The later compiler directive is the default one and you need to
arrange for all necessary instantiations to appear in the
implementation file (.C) for example in Array.C
#include Array.h
template class<Type>
Array<Type>::Array(unsigned int sz)
{
...
}
...
template class Array<double>; // explictly instantiate Array<double>
template class Array<Date>; // explictly instantiate Array<Date>
Pointers
Pointers
Pointers and Arrays
Pointers and function arguments
Dynamic memory management
New and delete
Pointers
Pointers are used to:
Access array elements
Passing arguments to functions when the function
needs to modify the original argument
Passing arrays and strings to functions
Obtaining memory from the system
Creating data structures such as linked lists
Many operations that require pointers in C can be carried
out without pointes in C++ using reference arguments
instead of pointers, strings instead of char arrays or
vectors instead of arrays
Some operations still require pointers, for example
creating data structures such as linked lists and binary
trees
Pointers
Each variable in a program occupies a part of the computer’s
memory, for example an integer variable occupies 4 bytes of
memory
The location of the piece of memory used to store a variable is
called the address of that variable
An address is some kind of number similar to house numbers in
a street that is used to locate the information stored in that
particular variable
int i;
address of i
char c; address of c
short s; address of s
0x1054
0x1055
0x1056
0x1057
0x1058
0x1059
0x1060
10101011
00001111
10001000
11100011
00111011
10111100
11001100
Pointer Variables
A pointer variable is a variable that holds address
values
Each data type has its own pointer variable, pointer
to int, pointer to double, pointer to char, …
C/C++ uses the address-of operator & to get the
address of an variable
C/C++ uses the indirection or contents-of operator *
to access the value of the variable pointed by
int i=17;
int* ptr; // defines a pointer to an integer variable
ptr= &i; // assign the address of x to pointer
cout << *ptr << endl; // prints contents of variable i
Pointer Variables
int i;
int *ptr;
ptr=&i;
cout << *ptr << endl;
0x1054
17
Pointer Variables
int v; // defines variable v of type int
int w; // defines variable w of type int
int *p; // defines variable p of type pointer to int
p=&v; // assigns address of v to pointer p
v=3; // assigns value 3 to v
*p=7; // assigns value 7 to v
p=&w; // assigns address of w to pointer p
*p=12; // assigns value 12 to w
Using the indirection operator *p to access the
contents of a variable is called indirect addressing
or dereferencing the pointer
Pointers and Arrays
There is a close association between pointers and arrays
Arrays can be accessed using pointers
The name of an array is also a constant pointer to the data
type of the elements stored in the array
int array[5] = { 23, 5, 12, 34, 17 }; // array of 5 ints
for (int i=0; i< 5; i++)
cout << array[i] << endl; // using index to access elements
for (int i=0; i< 5; i++)
cout << *(array+i) << endl; // using pointer to access elements
// array is of type pointer to integer
Pointers as Function Arguments
C/C++ offers three different ways to pass arguments
to a function
by value : void f(int x);
by reference : void f(int& x);
by pointer : void f(int* x);
In passing by value the function obtains only a local
copy of the variable, so that changes to the local
variable have no impact on the argument with which
the function was invoked
In passing by reference and passing by pointer the
function manipulates the original variable rather than
only a copy of it
Pointers as Function Arguments
void swap( double& x, double& y)
{
double tmp=x;
x=y; // access variable by its alias name
y=tmp;
}
void swap( double* ptr1, double* ptr2)
{
double tmp=*ptr1;
*ptr1=*ptr2; // de-referencing pointer
*ptr2=tmp;
}
double a=3.0;
double b=5.0
swap(a,b); // call by reference to variables a and
swap(&a, &b); // call by pointer using the addresses of a and b
BubbleSort
void bsort (double *ptr, int n) // pass pointer to array and
// size of array as arguments to bsort
{
int j,k; // indices to array
for (j=0; j<n-1; j++) // outer loop
for(k=j+1; k<n; k++) // inner loop starts at outer
if(*(ptr+j) > *(ptr+k))
swap(ptr+j,ptr+k);
}
double array[6] = { 2.3, 4.5, 1.2, 6.8, 0.8, 4.9 };
bsort(array,n); // sort the array
Const Modifiers and Pointers
The use of the const modifier with pointers is confusing
as it can mean two things
const int* cptrInt; // cptrInt is a pointer to a const int
You can not the change the value of the integer that
cptrInt points to but you can change the pointer itself
int* const ptrcInt; // ptrcInt is a constant pointer to int
You can change the value of the integer that ptrcInt
points to but you can not change the pointer itself
Memory Management
In order to create an array in C/C++ you have to know
its size in advance during compile time, in other words it
has to be a constant
int size;
cout << ”Enter size of array : ”;
cin >> size;
int array[size]; // ERROR size has to be a constant
Solution in C++, use vector class from the STL which is
expandable
Memory Management
Date* CreateDate() // allows the user to create a date object
{
int day, month, year;
char dummy;
cout << ”Enter dd/mm/yyyy :”;
cin >> day >> dummy >> month >> dummy >> year;
Date date(day, month, year);
return &date; // ERROR!! Scope of date ends with end of function
}
Date *ptr;
ptr=CreateDate(); // call CreateDate() to generate a new date
cout << ”You entered ” << *ptr << endl;
// variable to which ptr points no longer exist , segmentation fault !!!
Memory Management
The new operator in C++ can be used to create objects on the heap
that are ”alive” after returning from a function
Objects allocated in dynamic memory are called heap objects or to be
”on free store” and have a permament existence
Date* CreateDate() // allows the user to create a date object
{
int day, month, year;
char dummy;
cout << ”Enter dd/mm/yyyy :”;
cin >> day >> dummy >> month >> dummy >> year;
Date *tmpptr = new Date(day, month, year);
return tmpptr; // returns pointer to heap object
}
Date *ptr;
ptr=CreateDate(); // call CreateDate() to generate a new date
cout << ”You entered ” << *ptr << endl; // ok, ptr refers to heap object
Memory Management
New can also be used to allocate blocks of memory
The delete operator is used to release the memory
allocated with new once it is no longer needed
#include <cstring>
char *str =”This is an old C-style string”;
int len=strlen(str); // computes the length of str
char *ptr; // create a pointer to char
ptr = new char[len+1]; // set aside memory string + ’\0’
strcpy(ptr,str); // copy str to new memory
cout << ”ptr=” << ptr << endl;
delete [] ptr; // release ptr’s memory
New Operator in Constructors
class String // user-defined string class
{
private:
char* str; // pointer to block of characters
public:
String(char* s) // one-argument constructor
{
int length=strlen(s); // length of string argument
str = new char[length+1]; // allocate memory
strcpy(str,s); // copy argument to it
}
~String()
// destructor
{ delete [] str; }
void Display() { cout << str << endl; }
};
String mystring=”This is my string of Type String”;
mystring.Display();
Pointers to Objects
Pointers can point to objects as well as to built-in data
types
Date date; // define a named Date object
date.Set(12,3,1996); // set the date
date.Display(); // display the date
Date *dateptr; // define a pointer to a Date object
dateptr=new Date; // points to new Date object
dateptr->Set(9,12,1999); // set date using -> operator
dateptr->Display(); // display date
(*dateptr).Display(); // works as well but less elegant
Linked List Example
A linked list is composed of a chain of elements
(links). Each element contains some data and a
pointer to the next element in the list.
In a double linked list, each element also contains a
pointer to its predecessor.
Element
Element
next
data
next
data
Element
next
prev
data
Element
next
prev
data
Element
next
data
Element
next
prev
data
Linked List Example
struct link
// one element of list
{
int data; // data item
link *next; // pointer to next element
};
class linklist
{
private:
link* first; // pointer to first link
public:
linklist() { first = NULL;} // no argument constructor
void push_back(int d);
// add new element to the end of list
int pop_back(); // delete last element and return data value
void push_front(int d);
// add new element to the front of list
int pop(); // delete first element and return data value
void display();
// display all elements in list
}
Linked List Example
void linklist::push(int d) // add data item at the front
{
link* newlink = new link; // create a new link
newlink->data = d;
// assign new data d
newlink->next=first;
// it points to the next link
first = newlink;
// now first points to this link
}
Linked List Example
int linklist::pop() // remove element at the front
{
int tmp_data = first->data;
link* tmp=first;
first=first->next;
delete tmp; // free storage
return tmp_data;
}
int linklist::pop_back() // remove element at the end
{
link* tmp=first;
while (tmp->next != NULL)
tmp=tmp->next;
int tmp_data = tmp->data;
delete tmp; // free storage
return tmp_data;
}
Linked List Example
void linklist::push_back(int d) // add data item at the end
{
link* newlink = new link; // create a new link
newlink->data = d;
// assign new data d
newlink->next = 0; // points to nil
link* tmp=first;
if (tmp == NULL) // empty list
first=newlink;
else
{
while (tmp->next!=NULL)
tmp=tmp->next;
tmp->next=newlink;
// it points to the next link
}
}
Linked List Example
void linklist::display() // display all links
{
link* tmp=first; // set ptr to first link
while(tmp != NULL) // until ptr points beyond last link
{
cout << current->data << ” ”; // print data
current=current->next;
// move to next link
}
}
Linked List Example
template <class T>
struct link
// one element of list
{
T data; // data item
link *next; // pointer to next element
};
template <class T>
class linklist
{
private:
link* first; // pointer to first link
public:
linklist() { first = NULL;} // no argument constructor
void push(T t);
// add data item (one link)
T pop();
void display();
// display all links
Linked List Example
template <class T>
void linklist<T>::push(T t) // add element at the front
{
link* newlink = new link; // create a new link
newlink->data = t;
// give it data d
newlink->next=first;
// it points to the next link
first = newlink;
// now first points to this link
}
template <class T>
void linklist<T>::display() // display all links
{
link* current=first; // set ptr to first link
while(current != NULL) // until ptr points beyond last link
{
cout << current->data << ” ”; // print data
current=current->next;
// move to next link
}
Standard Template Library
The standard template library (STL) contains
Containers
Algorithms
Iterators
A container is a way that stored data is organized in memory,
for example an array of elements.
Algorithms in the STL are procedures that are applied to
containers to process their data, for example search for an
element in an array, or sort an array.
Iterators are a generalization of the concept of pointers, they
point to elements in a container, for example you can
increment an iterator to point to the next element in an array
Containers, Iterators, Algorithms
Algorithms use iterators to interact with objects
stored in containers
Container
Container
Iterator
Algorithm
Iterator
Objects
Iterator
Algorithm
Algorithm
Iterator
Containers
A container is a way to store data, either built-in data
types like int and float, or class objects
The STL provides several basic kinds of containers
<vector> : one-dimensional array
<list> : double linked list
<deque> : double-ended queue
<queue> : queue
<stack> : stack
<set> : set
<map> : associative array
Sequence Containers
A sequence container stores a set of elements in
sequence, in other words each element (except
for the first and last one) is preceded by one
specific element and followed by another, <vector>,
<list> and <deque> are sequential containers
In an ordinary C++ array the size is fixed and can
not change during run-time, it is also tedious to
insert or delete elements. Advantage: quick random
access
<vector> is an expandable array that can shrink or
grow in size, but still has the disadvantage that
inserting or deleting elements in the middle is costly
as it requires to copy chunks of memory
Sequence Containers
<list> is a double linked list (each element has
points to its successor and predecessor), it is
quick to insert or delete elements but provides no
random access (e.g. return 5th element in list)
<deque> is a double-ended queue, that means one
can insert and delete elements from both ends, it
is a kind of combination between a stack (last in
first out) and a queue (first in first out) and
constitutes a compromise between a <vector> and
a <list>
Associative Containers
An associative container is non-sequential but uses
a key to access elements. The keys, typically a
number or a string, are used by the container to
arrange the stored elements in a specific order,
for example in a dictionary the entries are ordered
alphabetically.
Associative Containers
A <set> stores a number of items which contain keys
The keys are the attributes used to order the items,
for example a set might store objects of the class
Person which are ordered alphabetically using their name
A <map> stores pairs of objects: a key object and
an associated value object. A <map> is somehow
similar to an array except instead of accessing its
elements with index numbers, you access them with
indices of an arbitrary type.
<set> and <map> only allow one key of each value,
whereas <multiset> and <multimap> allow multiple
identical key values
Vector Container
int array[5] = {12, 7, 9, 21, 13 };
vector<int> v(array,array+5);
12
7
9
21 13
v.push_back(15);
v.pop_back();
12
7
9
21
12
7
4
0
1
2
3
12
7
9
21 15
v.begin();
v[3]
9
21 15
Vector Container
#include <vector>
#include <iostream>
vector<int> v(3); // create a vector of ints of size 3
v[0]=23;
v[1]=12;
v[2]=9; // vector full
v.push_back(17); // put a new value at the end of array
for (int i=0; i<v.size(); i++) // member function size() of vector
cout << v[i] << ” ”; // random access to i-th element
cout << endl;
Constructors for Vector
A vector can be initialized by specifying its size and
a prototype element or by another vector
vector<Date> x(1000); // creates vector of size 1000,
// requires default constructor for Date
vector<Date> dates(10,Date(17,12,1999)); // initializes
// all elements with 17.12.1999
vector<Date> y(x); // initializes vector y with vector x
Iterators
Iterators are pointer-like entities that are used to
access individual elements in a container.
Often they are used to move sequentially from element to
element, a process called iterating through a container.
vector<int>
array_
17
vector<int>::iterator
4
23
12
size_
4
The iterator corresponding to
the class vector<int> is of
the type vector<int>::iterator
Iterators
The container member functions begin() and end()
return an iterator to the first and past the last
element of a container
vector<int> v
array_
17
v.begin()
4
23
12
size_
4
v.end()
Iterators
One can have multiple iterators pointing to different or
identical elements in the container
vector<int> v
array_
17
4
23
i1
i2
12
size_
4
i3
Iterators
#include <vector>
#include <iostream>
vector<int> v; // initialize empty vector
v.push_back(13);
v.push_back(9);
v.push_back(8);
vector<int>::iterator iter=v.begin(); // iterator for class vector
// define iterator for vector and point it to first element of v
cout << ”first element of v=” << *iter; // de-reference iter
iter++; // move iterator to next element
iter=v.end()-1; // move iterator to last element
Iterators
int max(vector<int>::iterator start, vector<int>::iterator end)
{
int tmpmax=*start;
while(start != stop)
{
if (*start > tmpmax)
tmpmax=*start;
++start;
}
return tmpmax;
}
cout << ”max of v = ” << max(v.begin(),v.end());
Iterator Categories
Not every iterator can be used with every container
for example the list class provides no random access
iterator
Every algorithm requires an iterator with a certain
level of capability for example to use the [] operator
you need a random access iterator
Iterators are divided into five categories in which a
higher (more specific) category always subsumes a
lower (more general) category, e.g. An algorithm that
accepts a forward iterator will also work with a
bidirectional iterator and a random access iterator
input
forward
output
bidirectional
random
access
For_Each() Algorithm
#include <vector>
#include <algorithm>
#include <iostream>
void show(int n)
{
cout << n << ” ”;
}
int arr[] = { 12, 3, 17, 8 }; // standard C array
vector<int> v(arr, arr+4); // initialize vector with C array
for_each (v.begin(), v.end(), show); // apply function show
// to each element of vector v
Find() Algorithm
#include <vector>
#include <algorithm>
#include <iostream>
int key;
int arr[] = { 12, 3, 17, 8, 34, 56, 9 }; // standard C array
vector<int> v(arr, arr+7); // initialize vector with C array
vector<int>::iterator iter;
cout << ”enter value :”;
cin >> key;
iter=find(v.begin(),v.end(),key); // finds integer key in v
if (iter != v.end()) // found the element
cout << ”Element ” << key << ” found” << endl;
else
cout << ”Element ” << key << ” not in vector v” << endl;
Find_If() Algorithm
#include <vector>
#include <algorithm>
#include <iostream>
Bool mytest(int n) { return (n>21) && (n <36); };
int arr[] = { 12, 3, 17, 8, 34, 56, 9 }; // standard C array
vector<int> v(arr, arr+7); // initialize vector with C array
vector<int>::iterator iter;
iter=find_if(v.begin(),v.end(),mytest);
// finds element in v for which mytest is true
if (iter != v.end()) // found the element
cout << ”found ” << *iter << endl;
else
cout << ”not found” << endl;
Count_If() Algorithm
#include <vector>
#include <algorithm>
#include <iostream>
Bool mytest(int n) { return (n>14) && (n <36); };
int arr[] = { 12, 3, 17, 8, 34, 56, 9 }; // standard C array
vector<int> v(arr, arr+7); // initialize vector with C array
int n=count_if(v.begin(),v.end(),mytest);
// counts element in v for which mytest is true
cout << ”found ” << n << ” elements” << endl;
List Container
A list container is a double linked list, in which
each element contains a pointer to its successor and
predecessor.
It is possible to add and remove elements at any
location in the list
Lists do not allow random access but are efficient to
insert new elements and to sort and merge lists
List Container
int array[5] = {12, 7, 9, 21, 13 };
list<int> li(array,array+5);
12
7
9
21
12
7
li.pop_front();
7
9
21 13
li.push_back(15);
li.pop_back();
12
7
9
21
9
21 15
li.push_front(8);
8
12
7
li.insert()
7
12 17
21 23
9
21 15
Sort & Merge
Sort and merge allow you to sort and merge
elements in a container
#include <list>
int arr1[]= { 6, 4, 9, 1, 7 };
int arr2[]= { 4, 2, 1, 3, 8 };
list<int> l1(arr1, arr1+5); // initialize l1 with arr1
list<int> l2(arr2, arr2+5); // initialize l2 with arr2
l1.sort(); // l1 = {1, 4, 6, 7, 9}
l2.sort(); // l2= {1, 2, 3, 4, 8 }
l1.merge(l2); // merges l2 into l1
// l1 = { 1, 1, 2, 3, 4, 4, 6, 7, 8, 9}, l2= {}
Functions Objects
Some algorithms like sort, merge, accumulate can take a
function object as argument.
A function object is an object of a template class that has a
single member function : the overloaded operator ()
It is also possible to use user-defined functions instead of
pre-defined function objects
#include <list>
#include <functional>
int arr1[]= { 6, 4, 9, 1, 7 };
list<int> l1(arr1, arr1+5); // initialize l1 with arr1
l1.sort(greater<int>()); // uses function object greater<int>
// for sorting in reverse order l1 = { 9, 7, 6, 4, 1 }
Function Objects
The accumulate algorithm accumulates data over the
elements of the containing, for example computing the
sum of elements
#include <list>
#include <functional>
#include <numeric>
int arr1[]= { 6, 4, 9, 1, 7 };
list<int> l1(arr1, arr1+5); // initialize l1 with arr1
int sum = accumulate(l1.begin(), l1.end() , 0, plus<int>());
int sum = accumulate(l1.begin(), l1.end(),0); // equivalent
int fac = accumulate(l1.begin(), l1.end() , 0, times<int>());
User Defined Function Objects
class squared _sum // user-defined function object
{
public:
int operator()(int n1, int n2) { return n1+n2*n2; }
};
int sq = accumulate(l1.begin(), l1.end() , 0, squared_sum() );
// computes the sum of squares
User Defined Function Objects
template <class T>
class squared _sum // user-defined function object
{
public:
T operator()(T n1, T n2) { return n1+n2*n2; }
};
vector<complex> vc;
complex sum_vc;
vc.push_back(complex(2,3));
vc.push_back(complex(1,5));
vc.push_back(complex(-2,4));
sum_vc = accumulate(vc.begin(), vc.end() ,
complex(0,0) , squared_sum<complex>() );
// computes the sum of squares of a vector of complex numbers
Associative Containers
In an associative container the items are not
arranged in sequence, but usually as a tree structure
or a hash table.
The main advantage of associative containers is the
speed of searching (binary search like in a dictionary)
Searching is done using a key which is usually a
single value like a number or string
The value is an attribute of the objects in the
container
The STL contains two basic associative containers
sets and multisets
maps and multimaps
Sets and Multisets
#include <set>
string names[] = {”Ole”, ”Hedvig”, ”Juan”, ”Lars”, ”Guido”};
set<string, less<string> > nameSet(names,names+5);
// create a set of names in which elements are alphabetically
// ordered string is the key and the object itself
nameSet.insert(”Patric”); // inserts more names
nameSet.insert(”Maria”);
nameSet.erase(”Juan”); // removes an element
set<string, less<string> >::iterator iter; // set iterator
string searchname;
cin >> searchname;
iter=nameSet.find(searchname); // find matching name in set
if (iter == nameSet.end()) // check if iterator points to end of set
cout << searchname << ” not in set!” <<endl;
else
cout << searchname << ” is in set!” <<endl;
Set and Multisets
string names[] = {”Ole”, ”Hedvig”, ”Juan”, ”Lars”,
”Guido”, ”Patric”, ”Maria”, ”Ann”};
set<string, less<string> > nameSet(names,names+7);
set<string, less<string> >::iterator iter; // set iterator
iter=nameSet.lower_bound(”K”);
// set iterator to lower start value ”K”
while (iter != nameSet.upper_bound(”Q”))
cout << *iter++ << endl;
// displays Lars, Maria, Ole, Patric
Maps and Multimaps
A map stores pairs <key, value> of a key object and
associated value object.
The key object contains a key that will be searched
for and the value object contains additional data
The key could be a string, for example the name of a
person and the value could be a number, for example
the telephone number of a person
Maps and Multimaps
#include <map>
string names[]= {”Ole”, ”Hedvig”, ”Juan”, ”Lars”, ”Guido”, ”Patric”,
”Maria”, ”Ann”};
int numbers[]= {75643, 83268, 97353, 87353, 19988, 76455,
77443,12221};
map<string, int, less<string> > phonebook;
map<string, int, less<string> >::iterator iter;
for (int j=0; j<8; j++)
phonebook[names[j]]=numbers[j]; // initialize map phonebook
for (iter = phonebook.begin(); iter !=phonebook.end(); iter++)
cout << (*iter).first << ” : ” << (*iter).second << endl;
cout << ”Lars phone number is ” << phonebook[”Lars”] << endl;