CPP v1.1
CPP v1.1
Modern C++
Object-Oriented Programming
''Combine old and newer features to get the best out of the language''
Margit ANTAL
2017
Course Content
1. Introduction to C++
2
C++ - Object-Oriented Programming
References
– Bjarne Stroustrup, Herb Sutter, C++ Core Guidelines, 2017.
– M. Gregoire, Professional C++, 3rd edition, John Wiley & Sons, 2014.
– S. Lippman, J. Lajoie, B. E. Moo, C++ Primer, 5th edition, Addison
Wesley, , 2013.
– S. Prata, C++ Primer Plus, 6th edition, Addison Wesley, 2012.
– N. Josuttis, The C++ standard library. a tutorial and reference. Pearson
Education. 2012.
– A. Williams, C++ Concurrency in Action:Practical Multithreading.
Greenwich, CT: Manning. 2012.
3
Module 1
Introduction to C++
4
Introduction to C++
Content
– History and evolution
– Overview of the key features
● New built-in types
● Scope and namespaces
● Enumerations
● Dynamic memory: new and delete
● Smart pointers: unique_ptr, shared_ptr..
● Error handling with exceptions
● References
● The const modifier
5
Introduction to C++
History and evolution
– Creator: Bjarne Stroustrup 1983
– Standards:
● The first C++ standard
– 1998 (C++98, major)
– 2003 (C++03, minor)
● The second C++ standard
– 2011 (C++11, major) – significant improvements in language and
library
– 2014 (C++14, minor)
6
Introduction to C+
History and evolution
–
source: https://isocpp.org/std/status
7
Introduction to C++
Standard library
– C++ standard library = C standard library + STL
(Standard Template Library)
– STL – designed by Alexander Stepanov, provides:
● Containers: list, vector, set, map …
● Iterators
● Algorithms: search, sort, …
8
Introduction to C++
Philosophy
– Statically typed
– General purpose
– Efficient
– Supports multiple programming styles:
● Procedural programming
● Object-oriented programming
● Generic programming
9
Introduction to C++
Portability
– Recompilation without making changes in the
source code means portability.
– Hardware specific programs are usually not
portable.
10
Introduction to C++
Creating a program
– Use a text editor to write a program and save it in a
file → source code
– Compile the source code (compiler is a program
that translates the source code to machine
language) → object code
– Link the object code with additional code (libraries)
→ executable code
11
Introduction to C++
Creating a program (using GNU C++ compiler, Unix)
– Source code: hello.cpp
– Compile: g++ -c hello.cpp
● Output: hello.o (object code)
– Compile + Link: g++ hello.cpp
● Output: a.out (executable code)
– C++ 2014: g++ hello.cpp -std=c++14
12
Introduction to C++
The first C++ program
One-line comment
//hello.cpp
int main(){
std::cout<<”Hello”<<std::endl;
return 0;
}
13
Introduction to C++
Building a C++ program: 3 steps
– preprocessor (line starting with #)
– compiler
– linker
14
Introduction to C++
Most common preprocessor directives
– #include [file]
● the specified file is inserted into the code
– #define [key] [value]
● every occurrence of the specified key is replaced
with the specified value
– #ifndef [key] … #endif
● code block is conditionally included
15
Introduction to C++
Header files
– C++ header
● #include <iostream>
– C header
● #include <cstdio>
16
Introduction to C++
Avoid multiple includes
//myheader.h
#ifndef MYHEADER_H
#define MYHEADER_H
// the contents
#endif
17
Introduction to C++
The main() function
– int main(){ … }
or
– int main( int argc, char* argv[] ){ … }
18
Introduction to C++
I/O Streams
– cout: standard output
cout<<”Hello, world!”<<endl; End of line
19
Introduction to C++
Namespaces
– avoid naming conflicts
//my1.h //my2.h
namespace myspace1{ namespace myspace2{
void foo(); void foo();
} }
//my1.cpp //my2.cpp
#include "my1.h" #include "my2.h"
namespace myspace1{ namespace myspace2{
void foo(){ void foo(){
cout<<"myspace1::foo\n"; cout<<"myspace2::foo\n";
} }
} }
myspace1::foo() myspace2::foo()
20
Introduction to C++
Variables
– can be declared almost anywhere in your code
double d; //uninitialized
int i = 10; //initialized
21
Introduction to C++
Variable types
– short, int, long – range depends on compiler, but usually 2, 4, 4
bytes
– long long (C++11) – range depends on compiler – usually 8 bytes
– float, double, long double
– bool
– char, char16_t(C++11), char32_t(C++11), wchar_t
– auto (C++11) – the compiler decides the type automatically (auto i=7;)
– decltype(expr) (C++11)
int i=10;
decltype(i) j = 20; // j will be int
22
Introduction to C++
Variable types
#include
– <iostream>
using namespace std;
23
Introduction to C++
● C++0x/C++11 Support in GCC
– https://gcc.gnu.org/projects/cxx0x.html
24
Introduction to C++
C enumerations (not type-safe)
– always interpreted as integers →
● you can compare enumeration values from completely
different types
enum Fruit{ apple, strawberry, melon};
void foo(){
if( tomato == apple){
cout<<"Hurra"<<endl;
}
}
25
Introduction to C++
C++ enumerations (type-safe)
26
Introduction to C++
Range-based for loop
int elements[]={1,2,3,4,5};
27
Introduction to C++
The std::array
– replacement for the standard C-style array
– cannot grow or shrink at run time
#include <iostream>
#include <array>
using namespace std;
int main() {
array<int, 5 > arr = {10, 20, 30, 40, 50};
cout << "Array size = " << arr.size() << endl;
for(int i=0; i<arr.size(); ++i){
cout<<arr[ i ]<<endl;
}
}
28
Introduction to C++
Pointers and dynamic memory
– compile time array
int ctarray[ 3 ]; //allocated on stack
Stack Heap
rtarray
29
Introduction to C++
Dynamic memory management
– allocation
int * x = new int;
int * t = new int [ 3 ];
– deletion
delete x;
delete [] t;
30
Introduction to C++
Strings
– C-style strings:
● array of characters
● '\0' terminated
● functions provided in <cstring>
– C++ string
● described in <string>
string firstName = "John"; string lastName = "Smith";
31
Introduction to C++
References
– A reference defines an alternative name (alias) for an object.
– A reference must be initialized.
– Defining a reference = binding a reference to its initializer
int i = 10;
32
Introduction to C++
Operations on references
– the operation is always performed on the referred object
int i = 10;
int &ri = i;
++ri;
cout<<i<<endl; // outputs 11
++i;
cout<<ri<<endl; // outputs 12
33
Introduction to C++
References as function parameters
– to permit pass-by-reference:
● allow the function to modify the value of the parameter
● avoid copies
void inc(int &value) bool isShorter(const string &s1,
{ const string &s2)
value++; {
} return s1.size() < s2.size();
}
usage: usage:
int x = 10; string str1 ="apple";
inc( x ); string str2 ="nut";
cout<<str1<<"<"<<str2<<": " <<
isShorter(str1, str2);
34
Introduction to C++
Exceptions
– Exception = unexpected situation
35
Introduction to C++
Exceptions
#include <iostream>
#include
– <stdexcept>
using namespace std;
int main() {
try{
cout<<divide(1,0)<<endl;
}catch( const exception& e){
cout<<"Exception was caught!"<<endl;
}
}
36
Introduction to C++
The const modifier
– Defining constants
const int N =10;
int t[ N ];
– Protecting a parameter
void sayHello( const string& who){
cout<<"Hello, "+who<<endl;
who = "new name"; Compiler error
}
37
Uniform initialization (C++ 11)
brace-init
int n{2};
string s{"alma"};
map<string,string> m {
{"England","London"},
{"Hungary","Budapest"},
{"Romania","Bucharest"}
};
struct Person{
string name;
int age;
};
Person p{"John Brown", 42};
38
Introduction to C++
Using the standard library
#include <string>
–
#include <vector>
#include <iostream>
using namespace std;
const int N =10;
int main() {
int t[ N ];
vector<string> fruits = {"apple","melon"};
fruits.push_back("pear");
fruits.push_back("nut");
–// Iterate over the elements in the vector and print them
for (auto it = fruits.cbegin();
it != fruits.cend(); ++it) {
cout << *it << endl;
}
//Print the elements again using C++11 range-based for loop
for (auto& str : fruits)
cout << str << endl;
return 0;
}
39
Introduction to C++
Programming task:
– Write a program that reads one-word strings from the
standard input, stores them and finally prints them on the
standard output
– Sort the container before printing
● use the sort algorithm
#include <algorithm>
...
vector<string> fruits;
...
sort(fruits.begin(),fruits.end());
–
40
Module 2
Object-Oriented Programming
Classes and Objects
41
Object-Oriented Programming (OOP)
Content
– Classes and Objects
– Advanced Class Features
– Operator overloading
– Object Relationships
– Abstraction
42
OOP: Classes and Objects
Content
– Members of the class. Access levels. Encapsulation.
– Class: interface + implementation
– Constructors and destructors
– const member functions
– Constructor initializer
– Copy constructor
– Object's lifecycle
43
OOP: Types of Classes
Types of calsses:
– Polymorphic Classes:
● Shape, exception, ...
– Value Classes: Margit Antal
● int, complex<double>, ...
44
OOP: Classes and objects
Class = Type ( Data + Operations)
– Members of the class
– Data:
● data members (properties)
Margit Antal
– Operations:
● methods (behaviors)
– Each member is associated with an access level:
● private -
● public +
● protected #
45
OOP: Classes and objects
Object = Instance of a class
– An employee object: Employee emp;
● Properties are the characteristics that describe an
object.
– What makes this object different?
● id, firstName, lastName, salary, hired
● Behaviors answer the question:
– What can we do to this object?
● hire(), fire(), display(), get and set data
members
46
OOP: Classes and objects
class TYPES
Encapsulation
Employee
– an object encapsulates data and functionality. - m Id: int
- m FirstNam e: string
- m LastNam e: string
- m Salary: int
- bHired: b ool
Functionality + Em ployee()
+ display() : void {query}
+ hire() : void
+ fire() : void
+ setFirstNam e(strin g) : void
Data +
+
setLastNam e(strin g) : void
setId(int) : vo id
+ setSalary(int) : vo id
+ getFirstNam e() : string {query}
+ getLastNam e() : string {query}
+ getSalary() : int {query}
+ getIsHired() : bool {query}
+ getId() : i nt {query}
47
OOP: Classes and objects
Class creation
– class declaration - interface
● Employee.h
48
OOP: Classes and objects
Employee.h
class Employee{
public: Methods' declaration
Employee();
void display() const;
void hire();
void fire();
// Getters and setters
void setFirstName( string inFirstName );
void setLastName ( string inLastName );
void setId( int inId );
void setSalary( int inSalary );
string getFirstName() const;
string getLastName() const;
int getSalary() const;
bool getIsHired() const;
int getId() const;
private:
int mId; Data members
string mFirstName;
string mLastName;
int mSalary;
bool bHired;
};
49
OOP: Classes and objects
The Constructor and the object's state
– The state of an object is defined by its data members.
– The constructor is responsible for the initial state of the object
Employee :: Employee() : mId(-1),
mFirstName(""),
mLastName(""), Members are initialized
mSalary(0), through the
bHired(false){ constructor initializer list
}
Employee :: Employee() {
mId = -1; Members are assigned
mFirstName="";
mLastName="";
mSalary =0; Only constructors can
bHired = false; use this initializer-list
}
syntax!!!
50
OOP: Classes and objects
Constructors
– responsibility: data members initialization of a class object
– invoked automatically for each object
– have the same name as the class
– have no return type
– a class can have multiple constructors (function overloading)
– may not be declared as const
● constructors can write to const objects
51
OOP: Classes and objects
Member initialization (C++11)
class C class C
{ {
string s ("abc"); string s;
double d = 0; double d;
char * p {nullptr}; char * p;
int y[5] {1,2,3,4}; int y[5];
public: public:
C(); C() : s("abc"),
}; d(0.0),
p(nullptr),
y{1,2,3,4} {}
};
Compiler
52
OOP: Classes and objects
Defining a member function
– Employee.cpp
– A const member function cannot change the object's
state, can be invoked on const objects
void Employee::hire(){
bHired = true;
}
53
OOP: Classes and objects
Defining a member function
void Employee::display() const {
cout << "Employee: " << getLastName() << ", "
<< getFirstName() << endl;
cout << "-------------------------" << endl;
cout << (bHired ? "Current Employee" :
"Former Employee") << endl;
cout << "Employee ID: " << getId() << endl;
cout << "Salary: " << getSalary() << endl;
cout << endl;
}
54
OOP: Classes and objects
TestEmployee.cpp
– Using const member functions
void foo( const Employee& e){
e.display(); // OK. display() is a const member function
e.fire(); // ERROR. fire() is not a const member function
}
int main() {
Employee emp;
emp.setFirstName("Robert");
emp.setLastName("Black");
emp.setId(1);
emp.setSalary(1000);
emp.hire();
emp.display();
foo( emp );
return 0;
}
55
OOP: Classes and objects
TestEmployee.cpp
– Using const member functions
void foo( const Employee& e){
e.display(); // OK. display() is a const member function
e.fire(); // ERROR. fire() is not a const member function
}
int main() {
Employee emp;
emp.setFirstName("Robert");
emp.setLastName("Black");
emp.setId(1);
emp.setSalary(1000);
emp.hire();
emp.display();
foo( emp );
return 0;
}
56
OOP: Classes and objects
Interface: Employee.h Implementation: Employee.cpp
#ifndef EMPLOYEE_H #include "Employee.h"
#define EMPLOYEE_H
#endif
57
OOP: Classes and objects
Object life cycles:
– creation
– assignment
– destruction
58
OOP: Classes and objects
Object creation:
int main() {
Employee emp;
emp.display();
59
OOP: Classes and objects
Object creation – constructors:
– default constructor (0-argument constructor)
Employee :: Employee() : mId(-1), mFirstName(""),
mLastName(""), mSalary(0), bHired(false){
}
Employee :: Employee() {
}
60
OOP: Classes and objects
Object creation – constructors:
– Compiler-generated default constructor
class Value{
public:
void setValue( double inValue);
double getValue() const;
private:
double value;
};
– if a class does not specify any constructors, the compiler will generate
one that does not take any arguments
61
OOP: Classes and objects
Constructors: default and delete specifiers (C++ 11)
class X{
int i = 4;
int j {5};
public:
X(int a) : i{a} {} // i = a, j = 5
X() = default; // i = 4, j = 5
};
62
OOP: Classes and objects
Constructors: default and delete specifiers (C++ 11)
class X{ class X{
public: public:
X( int x ){} X( int x ){}
}; X( double ) = delete;
};
X x1(10); //OK X x1(10); //OK
X x2(3.14); //OK X x2(3.14); //ERROR
63
OOP: Classes and objects
Best practice: always provide default values for
members! C++ 11
struct Point{ int main() {
int x, y; Foo f;
Point ( int x = 0, int y = 0 ): x(x), y(y){} f.print();
}; return 0;
class Foo{ }
int i {};
double d {};
char c {};
Point p {};
OUTPUT:
public: i: 0
void print(){ d: 0
cout <<"i: "<<i<<endl; c:
cout <<"d: "<<d<<endl;
cout <<"c: "<<c<<endl; p: 0, 0
cout <<"p: "<<p.x<<", "<<p.y<<endl;
}
};
64
OOP: Classes and objects
Constructor initializer
class ConstRef{
public:
ConstRef( int& );
private:
int mI;
const int mCi;
int& mRi;
};
ConstRef::ConstRef( int& inI ): mI( inI ), mCi( inI ), mRi( inI ){}
ctor initializer
65
OOP: Classes and objects
Constructor initializer
– data types that must be initialized in a ctor-initializer
● const data members
● reference data members
● object data members having no default
constructor
● superclasses without default constructor
66
OOP: Classes and objects
A non-default Constructor
Employee :: Employee( int inId, string inFirstName,
string inLastName,
int inSalary, int inHired) :
mId(inId), mFirstName(inFirstName),
mLastName(inLastName), mSalary(inSalary),
bHired(inHired){
}
67
OOP: Classes and objects
Copy Constructor
Employee emp1(1, "Robert", "Black", 4000, true);
– called in one of the following cases:
● Employee emp2( emp1 ); //copy-constructor called
● Employee emp3 = emp2; //copy-constructor called
● void foo( Employee emp );//copy-constructor called
– if you don't define a copy-constructor explicitly, the compiler
creates one for you
● this performs a bitwise copy
68
OOP: Classes and objects
//Stack.h //Stack.cpp
69
OOP: Classes and objects
//TestStack.cpp
#include "Stack.h"
s1: Stack
70
OOP: Classes and objects
Copy constructor: T ( const T&)
//Stack.h //Stack.cpp
71
OOP: Classes and objects
s1: Stack
//TestStack.cpp mCapacity: 3
#include "Stack.h"
mElements
int main(){ mTop
Stack s1(3);
Stack s2 = s1; 0
s1.push(1);
s2.push(2);
1
cout<<"s1: "<<s1.top()<<endl;
cout<<"s2: "<<s2.top()<<endl; s2: Stack 2
}
mCapacity: 3
mElements
mTop
0
1
2
72
OOP: Classes and objects
Destructor
– when an object is destroyed:
● the object's destructor is automatically invoked,
● the memory used by the object is freed.
– each class has one destructor
– usually place to perform cleanup work for the object
– if you don't declare a destructor → the compiler will generate
one, which destroys the object's member
73
OOP: Classes and objects
Destructor
– Syntax: T :: ~T();
Stack::~Stack(){
if( mElements != nullptr ){
delete[] mElements;
mElements = nullptr;
}
}
{ // block begin
Stack s(10); // s: constructor
Stack* s1 = new Stack(5);// s1: constructor
s.push(3);
s1->push(10);
delete s1; //s1: destructor
s.push(16);
} // block end //s: destructor
74
OOP: Classes and objects
Default parameters
– if the user specifies the arguments → the defaults are ignored
– if the user omits the arguments → the defaults are used
– the default parameters are specified only in the method declaration
(not in the definition)
//Stack.h //TestStack.cpp
class Stack{
public: Stack s1(3); //capacity: 3
Stack( int inCapacity = 5 ); Stack s2; //capacity: 5
.. Stack s3( 10 ); //capacity: 10
};
//Stack.cpp
Stack::Stack( int inCapacity ){
mCapacity = inCapacity;
mElements = new double [ mCapacity ];
mTop = mElements;
}
75
OOP: Classes and objects
The this pointer
– every method call passes a pointer to the object for which it
is called as hidden parameter having the name this
– Usage:
● for disambiguation
Stack::Stack( int mCapacity ){
this → mCapacity = mCapacity;
//..
}
76
OOP: Classes and objects
Programming task [Prata]
class Queue
{
enum {Q_SIZE = 10};
private:
// private representation to be developed later
public:
Queue(int qs = Q_SIZE); // create queue with a qs limit
~Queue();
bool isempty() const;
bool isfull() const;
int queuecount() const;
bool enqueue(const Item &item); // add item to end
bool dequeue(Item &item); // remove item from front
};
77
OOP: Classes and objects
Programming task [Prata]
class Queue
{
private:
// class scope definitions
};
78
Module 3
Object-Oriented Programming
Advanced Class Features
79
OOP: Advanced class features
Content
– Inline functions
– Stack vs. Heap
– Array of objects vs. array of pointers
– Passing function arguments
– Static members
– Friend functions, friend classes
– Nested classes
– Move semantics (C++11)
80
OOP: Advanced class features
Inline functions
– designed to speed up programs (like macros)
– the compiler replaces the function call with the
function code (no function call!)
– advantage: speed
– disadvantage: code bloat
● ex. 10 function calls → 10 * function's size
81
OOP: Advanced class features
How to make a function inline?
– use the inline keyword either in function declaration
or in function definition
– both member and standalone functions can be inline
– common practice:
● place the implementation of the inline function
into the header file
– only small functions are eligible as inline
– the compiler may completely ignore your request
82
OOP: Advanced class features
inline function examples
inline double square(double a){
return a * a;
}
class Value{
int value;
public:
inline int getValue()const{ return value; }
83
OOP: Advanced class features
– Stack vs. Heap
– Heap – Dynamic allocation
void draw(){
Point * p = new Point();
p->move(3,3);
//...
delete p;
}
– Stack – Automatic allocation
void draw(){
Point p;
p.move(6,6);
//...
}
84
OOP: Advanced class features
Array of objects
class Point{
int x, y;
public:
Point( int x=0, int y=0);
//...
};
85
OOP: Advanced class features
Array of pointers
Point ** t2 = new Point*[ 4 ];
for(int i=0; i<4; ++i ){
t2[i] = new Point(0,0);
}
for( int i=0; i<4; ++i ){
cout<<*t2[ i ]<<endl;
}
t2
86
OOP: Advanced class features
Static members:
● static methods
● static data
– Functions belonging to a class scope which don't access
object's data can be static
– Static methods can't be const methods (they do not access
object's state)
– They are not called on specific objects they have no this
pointer
87
OOP: Advanced class features
– Static members initializing static class member
//Complex.h
class Complex{
public: //Complex.cpp
Complex(int re=0, int im=0);
static int getNumComplex(); int Complex::num_complex = 0;
// ...
private: int Complex::getNumComplex(){
static int num_complex; return num_complex;
double re, im; }
};
Complex::Complex(int re, int im){
this->re = re;
this->im = im;
instance counter ++num_complex;
}
88
OOP: Advanced class features
– Static method invocation
elegant
non - elegant
89
OOP: Advanced class features
Complex z1(1,2), z2(2,3), z3;
re: 1 num_complex: 3
im: 2
Only one copy of
the static member
re: 0
im: 0
90
OOP: Advanced class features
– Classes vs. Structs
● default access specifier
– class: private
– struct: public
● class: data + methods, can be used polimorphically
● struct: mostly data + convenience methods
91
OOP: Advanced class features
– Classes vs. structures
class list{
private:
struct node
{
node *next;
int val;
node( int val = 0, node * next = nullptr):val(val), next(next){}
};
node * mHead;
public:
list ();
~list ();
void insert (int a);
void printAll()const;
};
92
OOP: Advanced class features
– Passing function arguments
● by value
– the function works on a copy of the variable
● by reference
– the function works on the original variable, may modify it
● by constant reference
– the function works on the original variable, may not modify
(verified by the compiler)
93
OOP: Advanced class features
– Passing function arguments passing primitive values
94
OOP: Advanced class features
– Passing function arguments passing objects
int main(){
Point p1(3,3);
f1(p1);
f2(p1);
f3(p1);
f4(&p1);
return 0;
}
95
OOP: Advanced class features
– friend functions, friend classes, friend member
functions
● friends are allowed to access private members of a class
● Use it rarely
– operator overloading
96
OOP: Advanced class features
– friend vs. static functions
class Test{
private:
int iValue;
static int sValue;
public:
Test( int in ):iValue( in ){}
void print() const;
static void print( const Test& what );
friend void print( const Test& what );
};
97
OOP: Advanced class features
– friend vs. static functions
int Test :: sValue = 0;
int main() {
Test test( 10 );
test.print();
Test::print( test );
print( test );
}
98
OOP: Advanced class features
– friend class vs. friend member function
class List{ class ListElement{
private: private:
ListElement * head; int key;
public: ListElement * next;
bool find( int key ); friend class List;
… ...
}; };
class ListElement{
private:
int key;
ListElement * next;
friend class List::find( int key);
...
};
99
OOP: Advanced class features
– Returning a reference to a const object
// version 1
vector<int> Max(const vector<int> & v1, const vector<int> & v2)
{
if (v1.size() > v2.size()) Copy
return v1;
else constructor
return v2; invocation
}
// version 2
const vector<int> & Max(const vector<int> & v1, const vector<int> & v2)
{
if (v1.size() > v2.size())
return v1; More
else efficient
return v2;
}
100
OOP: Advanced class features
– Nested classes
● the class declared within another class is called a
nested class
● usually helper classes are declared as nested
// Version 1
class Queue
{
private:
// class scope definitions
// Node is a nested structure definition local to this class
struct Node {Item item; struct Node * next;};
...
};
101
OOP: Advanced class features
– Nested classes [Prata] Node visibility!!!
// Version 2
class Queue
{
// class scope definitions
// Node is a nested class definition local to this class
class Node
{
public:
Item item;
Node * next;
Node(const Item & i) : item(i), next(0) { }
};
//...
};
102
OOP: Advanced class features
– Nested classes
● a nested class B declared in a private section of a class A:
– B is local to class A (only class A can use it)
103
OOP: Advanced class features
– Features of a well-behaved C++ class
– implicit constructor
● T :: T(){ … }
– destructor
● T :: ~T(){ … }
– copy constructor
● T :: T( const T& ){ … }
104
OOP: Advanced class features
– Move Semantics (C++11)
class string{ string :: string(const char* p){
char* data; size_t size = strlen(p) + 1;
public: data = new char[size];
string( const char* ); memcpy(data, p, size);
string( const string& ); }
~string(); string :: string(const string& that){
}; size_t size = strlen(that.data) + 1;
data = new char[size];
memcpy(data, that.data, size);
}
string :: ~string(){
delete[] data;
}
105
OOP: Advanced class features
– Constructor delegation (C++11)
// C++03
class A
{
void init() { std::cout << "init()"; }
void doSomethingElse() { std::cout << "doSomethingElse()\n"; }
public:
A() { init(); }
A(int a) { init(); doSomethingElse(); }
};
// C++11
class A
{
void doSomethingElse() { std::cout << "doSomethingElse()\n"; }
public:
A() { ... }
A(int a) : A() { doSomethingElse(); }
};
106
OOP: Advanced class features
– Move Semantics (C++11): lvalue, rvalue
string a(x); // Line 1
string b(x + y); // Line 2
string c(function_returning_a_string()); // Line 3
– lvalue: real object having an address
● Line 1: x
– rvalue: temporary object – no name
● Line 2: x + y
● Line 3: function_returning_a_string()
107
OOP: Advanced class features
– Lvalues:
● Refer to objects accessible at more than one point in a source
code
– Named objects
– Objects accessible via pointers/references
● Lvalues may not be moved from
– Rvalues:
● Refer to objects accessible at exactly one point in source code
– Temporary objects (e.g. by value function return)
● Rvalues may be moved from
108
OOP: Advanced class features
int x;
– Lvalue x = 10; Rvalue
109
OOP: Advanced class features
– Move Semantics (C++11): rvalue reference, move
constructor
// string&& is an rvalue reference to a string
string :: string(string&& that){
data = that.data;
that.data = nullptr;
}
● Move constructor
● Shallow copy of the argument
object
110
OOP: Advanced class features
– Copy constructor vs. move constructor
● Copy constructor: deep copy
● Move constructor: shallow copy + ownership transfer
// constructor
string s=”apple”;
// copy constructor: s is an lvalue
string s1 = s;
// move constructor: right side is an rvalue
string s2 = s + s1;
111
OOP: Advanced class features
– Passing large objects
//– C++98 // C++11
// avoid expense copying // move semantics
–
void makeBigVector(vector<int>& out) vector<int> makeBigVector()
{ {
}
–
... …
vector<int> v; }
–
makeBigVector( v ); auto v = makeBigVector();
112
OOP: Advanced class features
– Rvalues, lvalues, &&
class A {
public:
static A inst;
Reference to a static variable → lvalue
static A& getInst() {return inst;}
http://geant4.web.cern.ch/geant4/collaboration/c++11_guidelines.pdf
113
Module 4
Object-Oriented Programming
Operator overloading
114
OOP: Operator overloading
Content
● Objectives
● Types of operators
● Arithmetic operators
● Increment/decrement
● Inserter/extractor operators
● Assignment operator
● Index operator
● Relational and equality operators
● Conversion operators
115
OOP: Operator overloading
Objective
– To make the class usage easier, more intuitive
● the ability to read an object using the extractor operator (>>)
– Employee e1; cin >> e;
● the ability to write an object using the inserter operator (<<)
– Employee e2; cout<<e<<endl;
● the ability to compare objects of a given class
– cout<< ((e1 < e2) ? "less" : "greater");
116
OOP: Operator overloading
Limitations
– You cannot add new operator symbols. Only the existing operators can
be redefined.
– Some operators cannot be overloaded:
● . (member access in an object)
● ::(scope resolution operator)
● sizeof
● ?:
– You cannot change the arity (the number of arguments) of the operator
– You cannot change the precedence or associativity of the operator
117
OOP: Operator overloading
How to implement?
– write a function with the name operator<symbol>
– alternatives:
● method of your class
● global function (usually a friend of the class)
http://en.cppreference.com/w/cpp/language/operators
118
OOP: Operator overloading
– There are 3 types of operators:
● operators that must be methods (member functions)
– they don't make sense outside of a class:
● operator=, operator(),operator[], operator->
● operators that must be global functions
– the left-hand side of the operator is a variable of different type than your class:
operator<<, operator>>
● cout << emp;
● cout: ostream
● emp: Employee
● operators that can be either methods or global functions
– Gregoire: “Make every operator a method unless you must make it a global
function.”
119
OOP: Operator overloading
– Choosing argument types:
● value vs. reference
– Prefer passing-by-reference instead of passing-by-value.
● const vs. non const
– Prefer const unless you modify it.
– Choosing return types
● you can specify any return type, however
– follow the built-in types rule:
● comparison always return bool
● arithmetic operators return an object representing the result of the arithmetic
120
OOP: Operator overloading
– The Complex class: Complex.h, Complex.cpp
121
OOP: Operator overloading
– Arithmetic operators (member or standalone func.)
● unary minus
● binary minus
Complex Complex::operator-() const{
Complex temp(-this->re, -this->im);
return temp;
}
122
OOP: Operator overloading
– Arithmetic operators (member or standalone func.)
● unary minus
● binary minus
Complex operator-( const Complex& z ){
Complex temp(-z.getRe(), -z.getIm());
return temp;
}
123
OOP: Operator overloading
– Increment/Decrement operators
● postincrement: int i = 10; int j = i++; // j → 10
●
preincrement: int i = 10; int j = ++i; // j → 11
● The C++ standard specifies that the prefix increment and decrement
return an lvalue (left value).
124
OOP: Operator overloading
– Increment/Decrement operators (member func.)
125
OOP: Operator overloading
– Inserter/Extractor operators (standalone func.)
//complex.h
class Complex {
public:
friend ostream& operator<<( ostream& os, const Complex& c);
friend istream& operator>>( istream& is, Complex& c);
//...
};
//complex.cpp
ostream& operator<<( ostream& os, const Complex& c){
os<<c.re<<"+"<<c.im<<"i";
return os;
}
126
OOP: Operator overloading
– Inserter/Extractor operators
– Syntax:
ostream& operator<<( ostream& os, const T& out)
istream& operator>>( istream& is, T& in)
– Remarks:
● Streams are always passed by reference
● Q: Why should inserter operator return an ostream&?
● Q: Why should extractor operator return an istream&?
127
OOP: Operator overloading
– Inserter/Extractor operators
– Usage:
Complex z1, z2;
cout<<"Read 2 complex number:";
//Extractor
cin>>z1>>z2;
//Inserter
cout<<"z1: "<<z1<<endl;
cout<<"z2: "<<z2<<endl;
cout<<"z1++: "<<(z1++)<<endl;
cout<<"++z2: "<<(++z2)<<endl;
128
OOP: Operator overloading
– Assignment operator
● Q: When should be overloaded?
● A: When bitwise copy is not satisfactory (e.g. if you have
dynamically allocated memory
– when we should implement the copy constructor and the
destructor too).
– Ex. our Stack class
129
OOP: Operator overloading
– Assignment operator (member func.)
● Copy assignment
● Move assignment (since C++11)
130
OOP: Operator overloading
– Copy assignment operator (member func.)
● Syntax: X& operator=( const X& rhs);
● Q: Is the return type necessary?
– Analyze the following example code
131
OOP: Operator overloading
– Copy assignment operator example
Stack& Stack::operator=(const Stack& rhs) {
if (this != &rhs) {
//delete lhs – left hand side
delete [] mElements;
mCapacity = 0;
melements = nullptr; // in case next line throws
//copy rhs
mCapacity = rhs.mCapacity;
mElements = new double[ mCapacity ];
int nr = rhs.mTop - rhs.mElements;
std::copy(rhs.mElements, rhs.mElements+nr, mElements);
mTop = mElements + nr;
}
return *this;
}
132
OOP: Operator overloading
– Copy assignment operator vs Copy constructor
133
OOP: Operator overloading
– Move assignment operator (member func.)
● Syntax: X& operator=( X&& rhs) noexcept;
● When it is called?
Complex z1(1,2), z2(3,4); //Constructor
Complex z4(z2); //Copy constructor
z1 = z2; //Copy assignment operator
Complex z3 = z1 + z2; //Move constructor
z3 = z1 + z1; //Move assignment
134
OOP: Operator overloading
– Move assignment operator example
Stack& Stack::operator=(Stack&& rhs) noexcept {
if (this != &rhs) {
//delete lhs – left hand side
delete [] mElements;
//move rhs to this
mCapacity = rhs.mCapacity;
mTop = rhs.mTop;
Melements = rhs.mElements;
//leave rhs in valid state
mElements = nullptr;
rhs.mCapacity = 0;
rhs.mTop = 0;
}
return *this;
}
135
OOP: Operator overloading
– Subscript operator: needed for arrays (member func.)
– Suppose you want your own dynamically allocated C-style
array implement your own CArray
#ifndef CARRAY_H
#define CARRAY_H
class CArray{
public:
CArray( int size = 10 );
~Carray();
CArray( const Carray&) = delete;
CArray& operator=( const Carray&) = delete;
double& operator[]( int index );
double operator[]( int index ) const; Provides read-only access
private:
double * mElems;
int mSize;
};
#endif /* ARRAY_H */`
“If the value type is known to be a built-in type, the const variant should return by value.”
http://en.cppreference.com/w/cpp/language/operators. 136
OOP: Operator overloading
– Implementation
CArray::CArray( int size ){ double CArray::operator[](
if( size < 0 ){ int index ) const{
size = 10; if( index <0 || index >= mSize ){
} throw out_of_range("");
this->mSize = size; }
this->mElems = new double[ mSize ]; return mElems[ index ];
} }
CArray::~CArray(){
if( mElems != nullptr ){
delete[] mElems;
mElems = nullptr;
}
}
137
OOP: Operator overloading
– const vs non-const [] operator
void printArray(const CArray& arr, size_t size) {
for (size_t i = 0; i < size; i++) {
cout << arr[i] << "" ;
// Calls the const operator[] because arr is
// a const object.
}
cout << endl;
}
CArray myArray;
for (size_t i = 0; i < 10; i++) {
myArray[i] = 100;
// Calls the non-const operator[] because
// myArray is a non-const object.
}
printArray(myArray, 10);
138
OOP: Operator overloading
– Non-integral array indices: associative array
– ( Key, Value )
– Ex: Key → string, Value → double
● Homework
139
OOP: Operator overloading
– Relational and equality operators
● used for search and sort
● the container must be able to compare the stored objects
bool operator ==( const Point& p1, const Point& p2){
return p1.getX() == p2.getX() && p1.getY() == p2.getY();
}
vector<Point> v; //...
set<Point> p;
sort(v.begin(), v.end());
140
OOP: Operator overloading
– The function call operator ()
– Instances of classes overloading this operator behave as
functions too (they are function objects = function + object)
#ifndef ADDVALUE_H #include "AddValue.h"
#define ADDVALUE_H
class AddValue{ AddValue::AddValue( int inValue ){
int value; this->value = inValue;
public: }
AddValue( int inValue = 1); void AddValue::operator()( int& what ){
void operator()( int& what ); what += this->value;
}; }
#endif /* ADDVALUE_H */
141
OOP: Operator overloading
– The function call operator
AddValue func(2);
int array[]={1, 2, 3};
for( int& x : array ){
func(x);
}
for( int x: array ){
cout <<x<<endl;
}
142
OOP: Operator overloading
– Function call operator
● used frequently for defining sorting criterion
struct EmployeeCompare{
bool operator()( const Employee& e1, const Employee& e2){
if( e1.getLastName() == e2.getLastName())
return e1.getFirstName() < e2.getFirstName();
else
return e1.getLastName() < e2.getLastName();
}
};
143
OOP: Operator overloading
– Function call operator
● sorted container
set<Employee, EmployeeCompare> s;
144
OOP: Operator overloading
– Sorting elements of a given type:
● A. override operators: <, ==
● B. define a function object containing the comparison
145
OOP: Operator overloading
– Writing conversion operators
class Complex{
public:
operator string() const;
//
};
//usage
Complex z(1, 2), z2;
string a = z;
cout<<a<<endl;
146
OOP: Operator overloading
– After templates
● Overloading operator *
● Overloading operator →
147
OOP: Review
– Find all possible errors or shortcommings!
(1) class Array {
(2) public:
(3) Array (int n) : rep_(new int [n]) { }
(4) Array (Array& rhs) : rep_(rhs.rep_) { }
(5) ~Array () { delete rep_; }
(6) Array& operator = (Array rhs) { rep_= rhs.rep_; }
(7) int& operator [] (int n) { return &rep_[n]; }
(8) private:
(9) int * rep_;
(10) }; // Array
Source: http://www.cs.helsinki.fi/u/vihavain/k13/gea/exer/exer_2.html
148
Solution required!
– It is given the following program!
#include <iostream>
int main(){
std::cout<<”Hello\n”;
return 0;
}
Modify the program without modifying the main function so that the output of
the program would be:
Start
Hello
Stop
149
Singleton Design Pattern
#include <string>
class Logger{
public:
static Logger* Instance();
bool openLogFile(std::string logFile);
void writeToLogFile();
bool closeLogFile();
private:
Logger(){}; // Private so that it can not be called
Logger(Logger const&){}; // copy constructor is private
Logger& operator=(Logger const&){};// assignment operator is private
static Logger* m_pInstance;
};
http://www.yolinux.com/TUTORIALS/C++Singleton.html
150
Singleton Design Pattern
static
class Framewor...
Singleton
- uniqueInstance
- singletonData
+ Instance()
return unique Instance
+ SingletonOperation()
+ GetSingletonData ()
static
● Ensure that only one instance of a class is created.
151
Module 5
Object-Oriented Programming
Public Inheritance
152
OOP: Inheritance
– Inheritance
● is-a relationship - public inheritance
● protected access
● virtual member function
● early (static) binding vs. late (dynamic) binding
● abstract base classes
● pure virtual functions
● virtual destructor
153
class cppinheritance
Employee
OOP: Inheritance -
-
firstNam e: stri ng
lastNam e: stri ng
- salary: do uble
– public inheritance + Em ployee(strin g, string, doubl e)
+ getFirstNam e () : string {query}
● is-a relationship +
+
setFirstNam e(string) : void
getLastNam e () : string {query}
+ setLastNam e(string) : void
● base class: Employee + getSala ry() : double {qu ery}
+ setSalary(d ouble) : void
● derived class: Manager + print(o stream&) : void {query}
● add functionality +
+
M anager()
M anager(string, string, do uble, string)
+ setDepa rtm ent(string) : void
– ex. getDepartment(), setDepartment() + getDe partm ent() : string {query}
+ print(ostream &) : void {query}
● modify methods' behavior
– ex. print()
154
OOP: Inheritance
– protected access
● base class's private members can not be accessed in a
derived class
● base class's protected members can be accessed in a
derived class
● base class's public members can be accessed from
anywhere
155
OOP: Inheritance
– public inheritance
class Employee{
public:
Employee(string firstName = "", string lastName = "",
double salary = 0.0) : firstName(firstName),
lastName(lastName),
salary(salary) {
}
//...
};
156
OOP: Inheritance
– Derived class's constructors
Manager::Manager(){
}
157
OOP: Inheritance
– Derived class's constructors
Manager::Manager(){
}
158
OOP: Inheritance
– How are derived class's objects constructed?
● bottom up order:
Manager
– base class constructor invocation
– member initialization
– derived class's constructor block Employee
● destruction
– in the opposite order
159
OOP: Inheritance
– Method overriding
Employee {
class Employee{
public:
virtual void print( ostream&)const;
print(ostream&) const;
};
160
OOP: Inheritance
– Method overriding
class Employee {
public:
virtual void print( ostream&) const;
};
161
OOP: Inheritance
– Method overriding - virtual functions
● non virtual functions are bound statically
– compile time
● virtual functions are bound dynamically
– run time
162
OOP: Inheritance
– Polymorphism
void printAll( const vector<Employee*>& emps ){
for( int i=0; i<emps.size(); ++i){
emps[i]-> print(cout);
cout<<endl;
}
}
163
OOP: Inheritance
– Polymorphism
● a type with virtual functions is called a polymorphic type
● polymorphic behavior preconditions:
– the member function must be virtual
– objects must be manipulated through
● pointers or
● references
164
OOP: Inheritance
– Polymorphism – Virtual Function Table
vtbl:
class Employee{
Employee::print firstName:””
firstName:””
public:
firstName:”” lastName:””
virtual void print(ostream&) const;
lastName:”” lastName:””
};
//... e1 salary:0.0
m1salary:0.0
salary:0.0
department
department
class Manager:public Employee{ vptr vptr
vtbl
virtual void print(ostream&) const;
//...
}; vtbl:
Employee e1, e2;
Manager m1, m2; Manager::print firstName:””
firstName:””
lastName:”” lastName:””
e2 salary:0.0 m2 salary:0.0
department
Discussion!!! vptr
vptr
Employee * pe;
pe = &e1; pe->print();//???
pe = &m2; pe->print();//???
Each class with virtual functions has its own virtual function table (vtbl). 165
RTTI – Run-Time Type Information
dynamic_cast<>(pointer)
class Base{};
class Derived : public Base{};
derivedPointer = dynamic_cast<Derived*>(basePointer);
if (derivedPointer != nullptr){
cout << "basePointer is pointing to a Derived class object";
}else{
cout << "basePointer is NOT pointing to a Derived class object";
}
Java:
instanceof
166
RTTI – Run-Time Type Information
dynamic_cast<>(reference)
class Base{};
class Derived : public Base{};
Derived derived;
Base& baseRef = derived;
try{
Derived& derivedRef = dynamic_cast<Derived&>(baseRef);
} catch( bad_cast ){
// ..
}
167
OOP: Inheritance
– Abstract classes
● used for representing abstract concepts
● used as base class for other classes
● no instances can be created
168
OOP: Inheritance
– Abstract classes – pure virtual functions
Shape s; //???
169
OOP: Inheritance
– Abstract classes – pure virtual functions
170
OOP: Inheritance
– Abstract class → concrete class
171
OOP: Inheritance
– Abstract class → abstract class
};
172
OOP: Inheritance
– Virtual destructor
● Every class having at least one virtual function should
have virtual destructor. Why?
class X{
public:
// ...
virtual ~X();
};
173
OOP: Inheritance
– Virtual destructor
void deleteAll( Employee ** emps, int size){
for( int i=0; i<size; ++i){
delete emps[ i ]; Which destructor is invoked?
}
delete [] emps;
}
// main
Employee ** t = new Employee *[ 10 ];
for(int i=0; i<10; ++i){
if( i % 2 == 0 )
t[ i ] = new Employee();
else
t[ i ] = new Manager();
}
deleteAll( t, 10);
174
Module 6
Object-Oriented Programming
Object relationships
175
OOP: Object relationships
– Content
● The is-a relationship
● The has-a relationship
● Private inheritance
● Multiple inheritance
176
Super
OOP: Object relationships
– The is-a relationship – Client's view (1)
● works in only one direction:
– every Sub object is also a Super one Sub
– but Super object is not a Sub
foo1(super); //OK
foo1(sub); //OK
foo2(super); //NOT OK
foo2(sub); //OK
177
Super
OOP: Object relationships
– The is-a relationship – Client's view (2)
178
Super
OOP: Object relationships
– The is-a relationship – Sub-class’s view
● the Sub class augments the Super class by
adding additional methods Sub
● the Sub class may override the Super class methods
● the subclass can use all the public and
protected members of a superclass.
179
OOP: Object relationships
– The is-a relationship: preventing inheritance C++11
● final classes – cannot be extended
class Super final
{
};
180
OOP: Object relationships
– The is-a relationship: a client's view of overridden methods(1)
● polymorphism Super super;
super.method1(); //Super::method1()
Sub sub;
class Super{ sub.method1(); //Sub::method1()
public:
Super& ref =super;
virtual void method1();
ref.method1(); //Super::method1();
};
class Sub : public Super{ ref = sub;
public: ref.method1(); //Sub::method1();
virtual void method1();
}; Super* ptr =&super;
ptr->method1(); //Super::method1();
ptr = ⊂
ptr->method1(); //Sub::method1();
181
OOP: Object relationships
– The is-a relationship: a client's view of overridden methods(2)
● object slicing
class Super{ Sub sub;
public: Super super = sub;
super.method1(); // Super::method1();
virtual void method1();
};
class Sub : public Super{ Sub
public:
virtual void method1();
}; Super Super
super sub
182
OOP: Object relationships
– The is-a relationship: preventing method overriding C++11
class Super{
public:
virtual void method1() final;
};
class Sub : public Super{
public:
virtual void method1(); //ERROR
};
183
OOP: Object relationships
– Inheritance for polymorphism
www.javatutorialhub.com
184
OOP: Object relationships
– The has-a relationship
Window Button
185
OOP: Object relationships
– Implementing the has-a relationship
● An object A has an object B
class B; class B; class B;
186
OOP: Object relationships
– Implementing the has-a relationship A B
● An object A has an object B
– strong containment (composition)
187
OOP: Object relationships
– Implementing the has-a relationship A B
● An object A has an object B
– weak containment (aggregation)
class B; B bObject;
A aObject1(bObject);
class A{ A aObject2(bObject);
private:
B& b;
public: bObject: B
A( const B& pb):b(pb){}
};
aObject1: A aObject2: A
188
OOP: Object relationships
– Implementing the has-a relationship
● An object A has an object B
weak containment strong containment
class B; class B;
class A{ class A{
private: private:
B* b; B* b;
public: public:
A( B* pb):b( pb ){} A(){
}; b = new B();
}
~A(){
delete b;
}
};
189
OOP: Object relationships
– Implementing the has-a relationship A B
● An object A has an object B
weak containment
Usage:
class B;
B bObject;
class A{ A aObject1(&bObject);
private: A aObject2(&bObject);
B* b;
public:
A( B* pb):b( pb ){}
}; bObject: B
aObject1: A aObject2: A
190
OOP: Object relationships
– Implementing the has-a relationship A B
● An object A has an object B
strong containment
class B; Usage:
A aObject;
class A{
private:
B* b;
public: anObject: A
A(){
b = new B();
} b: B *
~A(){
delete b;
}
};
191
OOP: Object relationships
– Combining the is-a and the has-a relationships
class Class Mo...
Component
+ Operation() 1..*
Client
+ Add() : Component
+ Rem ove() : Com ponent
+ GetChild() : Com ponent
Leaf Composite
+ Operation() + Operation()
forall g in children -children
g.Operation();
+ Add() : Com ponent
+ Rem ove() : Com ponent
+ GetChild() : Com ponent
192
Composite Design Pattern
class Class Mo...
Component
+ O peration() 1..*
Client
+ Add() : Component
+ Rem ove() : Com ponent
+ G etChild() : Com ponent
Leaf Composite
+ Operation() + Operation()
forall g in children -children
g.Operation();
+ Add() : Com ponent
+ Rem ove() : Com ponent
+ GetChild() : Com ponent
193
Composite Design Pattern
● Examples:
– Menu – MenuItem: Menus that contain menu items, each of which could
be a menu.
– Container – Element: Containers that contain Elements, each of which
could be a Container.
– GUI Container – GUI component: GUI containers that contain GUI
components, each of which could be a container
Source: http://www.oodesign.com/composite-pattern.html
194
Private Inheritance
– another possibility for has-a relationship
public Base class Base class public
public private
inheritance inheritance
195
Private Inheritance
template <typename T>
class MyStack : private vector<T> { Why is public inheritance
public: in this case dangerous???
void push(T elem) {
this->push_back(elem);
}
bool isEmpty() {
return this->empty();
}
void pop() {
if (!this->empty())this->pop_back();
}
T top() {
if (this->empty()) throw out_of_range("Stack is empty");
else return this->back();
}
};
196
Non-public Inheritance
– it is very rare;
– use it cautiously;
– most programmers are not familiar with it;
197
What does it print?
class Super{
public:
Super(){}
virtual void someMethod(double d) const{
cout<<"Super"<<endl;
}
};
class Sub : public Super{
public:
Sub(){}
virtual void someMethod(double d){
cout<<"Sub"<<endl;
}
};
198
What does it print?
class Super{
public:
Super(){}
virtual void someMethod(double d) const{
cout<<"Super"<<endl;
}
}; creates a new method, instead
class Sub : public Super{ of overriding the method
public:
Sub(){}
virtual void someMethod(double d){
cout<<"Sub"<<endl;
}
};
199
The override keyword C++11
class Super{
public:
Super(){}
virtual void someMethod(double d) const{
cout<<"Super"<<endl;
}
};
class Sub : public Super{
public:
Sub(){}
virtual void someMethod(double d) const override{
cout<<"Sub"<<endl;
}
};
200
Module 7
Generic Programming: Templates
201
Outline
– Templates
● Class template
● Function template
● Template metaprogramming
202
Templates
203
Templates
http://www.stroustrup.com/
204
Templates
– Allow generic programming
● to write code that can work with all kind of objects
205
Template
Function Template parameter
template<class T>
const T max(const T& x, const T& y) {
return x < y ? y : x;
}
206
Function Template
template<class T>
const T max(const T& x, const T& y) {
return x < y ? y : x;
}
207
Function Template
template<class T>
const T max(const T& x, const T& y) {
return x < y ? y : x;
}
● Usage:
– cout<<max(2, 3)<<endl; // max: T → int
– string a(“alma”); string b(“korte”);
cout<<max(a, b)<<endl; // max: T → string
– Person p1(“John”,”Kennedy”),p2(“Abraham”, “Lincoln”);
cout<<max(p1,p2)<<endl;// max: T-> Person
208
Function Template
template<class T>
void swap(T& x, T& y) {
const T tmp = x;
x = y;
y = tmp;
}
209
Function Template
– Allows writing function families
● polymorphism: compile time
210
Function Template
– What does it do? [Gregoire]
211
Class Template
– Allow writing class families
template<typename T>
class Array {
T* elements;
int size;
public:
explicit Array(const int size);
...
};
212
Class Template
– Template class's method definition
template<typename T>
class Array {
T* elements;
int size;
public:
explicit Array(const int size);
...
};
template<typename T>
Array<T>::Array(const int size):size(size),
elements(new T[size]){
}
213
Class Template
– Template parameters
● type template parameters
214
Class Template
– Distributing Template Code between Files
● Normal class:
– Person.h → interface
– Person.cpp → implementation
● Template class:
– interface + implementation go in the same file e. g. Array.h
● it can be a .h file → usage: #include “Array.h”
● it can be a .cpp file → usage: #include “Array.cpp”
215
Class Template+ Function Template
template<class T1, class T2>
struct pair { #include <utility>
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
pair();
pair(const T1& x, const T2& y);
...
};
216
Advanced Template
● template template parameter
template<typename T, typename Container>
class Stack{
Container elements;
public:
void push( const T& e ){
elements.push_back( e );
}
...
};
Usage:
Stack<int, vector<int> > v1;
Stack<int, deque<int> > v2;
217
Advanced Template
● template template parameter
template<typename T, typename Container=vector<T> >
class Stack{
Container elements;
public:
void push( const T& e ){
elements.push_back( e );
}
...
};
218
Advanced Template
● What does it do?
template < typename Container >
void foo( const Container& c, const char * str="")
{
typename Container::const_iterator it;
cout<<str;
for(it = c.begin();it != c.end(); ++it)
cout<<*it<<' ';
cout<<endl;
}
219
Advanced Template
● What does it do?
template < typename Container >
void foo( const Container& c, const char * str="")
{
typename Container::const_iterator it;
cout<<str;
for(auto& a: c ){
cout<< a <<' ';
}
cout<<endl;
}
220
Examples
221
More Advanced Template
● Template Metaprogramming
template<unsigned int N> struct Fact{
static const unsigned long int
value = N * Fact<N-1>::value;
};
template<> struct Fact<0>{
static const unsigned long int value = 1;
};
// Fact<8> is computed at compile time:
const unsigned long int fact_8 = Fact<8>::value;
int main()
{
cout << fact_8 << endl;
return 0;
}
222
Module 8
STL – Standard Template Library
223
Alexander Stepanov
https://www.sgi.com/tech/stl/drdobbs-interview.html
224
Outline
– Containers
– Algorithms
– Iterators
225
STL – General View
226
STL – General View
227
Basic STL Containers
– Sequence containers
● linear arrangement
– vector, deque, list <vector> <deque> <list>
Container
adapters – stack, queue, priority_queue <stack> <queue>
– Associative containers
● provide fast retrieval of data based on keys
– set, multiset, map, multimap <set> <map>
228
Sequence Containers
229
Associative Containers
230
STL Containers C++11
231
STL Containers
– homogeneous:
● vector<Person>, vector<Person*>
– polymorphism
● vector<Person*>
class Person{};
class Employee: public Person{};
class Manager : public Employee{};
232
STL Containers
vector<Person>
Person Person Person homogenous
– ...
233
STL Containers
vector<Person>
Person Person Person homogenous
– ...
vector<Person *>
... homogenous
234
The vector container - constructors
vector<T> v;
//empty vector
vector<T> v(n);
//vector with n copies of default for T
235
The vector container – add new elements
vector<int> v;
v.begin() v.end()
1 2 3 4 5
236
The vector container
vector<int> v( 10 );
cout<<v.size()<<endl;//???
for( int i=0; i<v.size(); ++i ){
cout<<v[ i ]<<endl;
}
for( auto& a: v ){
cout<< a <<” “;
}
237
The vector container: typical errors
– Find the error and correct it!
vector<int> v;
cout<<v.size()<<endl;//???
for( int i=0; i<10; ++i ){
v[ i ] = i;
}
cout<<v.size()<<endl;//???
for( int i=0; i<v.size(); ++i ){
cout<<v[ i ]<<endl;
}
238
The vector container: capacity and size
vector<int> v;
v.reserve( 10 );
239
The vector container: capacity and size
vector<int> v;
v.reserve( 10 );
--------------------------------------
240
The vector - indexing
int Max = 100;
vector<int> v(Max);
//???...
for (int i = 0; i < 2*Max; i++) {
cout << v[ i ]<<” ”;
}
--------------------------------------
241
The vector - indexing
int Max = 100;
vector<int> v(Max);
//???...
for (int i = 0; i < 2*Max; i++) {
cout << v[ i ]<<” ”; Efficient
}
--------------------------------------
out_of_range exception
242
The list container
– doubly linked list
list<int> l;
for( int i=1; i<=5; ++i){
l.push_back( i );
}
l.begin() l.end()
1 2 3 4 5
243
The deque container
– double ended vector
deque<int> l;
for( int i=1; i<=5; ++i){
l.push_front( i );
}
244
Algorithms - sort
template <class RandomAccessIterator>
void sort ( RandomAccessIterator first,RandomAccessIterator last );
245
Algorithms - sort
struct Rec {
string name;
string addr;
};
vector<Rec> vr;
// …
sort(vr.begin(), vr.end(), Cmp_by_name());
sort(vr.begin(), vr.end(), Cmp_by_addr());
–
246
Algorithms - sort
struct Cmp_by_name{
bool operator()(const Rec& a, const Rec& b) const
{
return a.name < b.name;
} function object
};
struct Cmp_by_addr{
bool operator()(const Rec& a, const Rec& b) const
{
return a.addr < b.addr;
– }
};
247
Strategy Design Pattern
class ceepus_iterator
Strategy
Context +strategy
+ Algorith mInterface()
+ ContextIn terface()
● Strategy lets the algorithm vary independently from clients that use it.
248
Strategy Design Pattern
class ceepus_iterator
sort
Strategy
Context +strategy
+ Algorith mInterface()
+ ContextIn terface()
● Strategy lets the algorithm vary independently from clients that use it.
249
Strategy Design Pattern
class ceepus_iterator
bool operator()(
sort const T&,
Strategy const T&)
Context +strategy
+ Algorith mInterface()
+ ContextIn terface()
● Strategy lets the algorithm vary independently from clients that use it.
250
Strategy Design Pattern
class ceepus_iterator
bool operator()(
sort const T&,
Strategy const T&)
Context +strategy
+ Algorith mInterface()
+ ContextIn terface()
Cmp_by_name Cmp_by_addr
251
Iterators
252
Iterator - the glue
int x[]={1,2,3,4,5}; vector<int>v(x, x+5);
int sum1 = accumulate(v.begin(), v.end(), 0);
v.begin() v.end()
1 2 3 4 5
l.begin() l.end()
1 2 3 4 5
253
Iterator - the glue
254
The set container
Source:http://www.cpp-tutor.de/cpp/le18/images/set.gif
255
The set container - usage
#include <set>
using namespace std;
set<int> intSet;
set<Person> personSet1;
256
The set container - usage
<
#include <set>
set<int> intSet;
set<Person> personSet1;
257
The set container - usage
<
#include <set>
set<Person> personSet1;
258
The set container - usage
<
#include <set>
set<Person> personSet1;
struct PersonComp{
bool operator() ( const Person&, const Person& );
};
259
The set container - usage
#include <set>
set<int> mySet;
while( cin >> nr ){
mySet.insert( nr );
}
set<int>::iterator iter;
for (iter=mySet.begin(); iter!=mySet.end(); ++iter){
cout << *iter << endl;
}
260
The set container - usage
set<int>::iterator iter;
for (iter=mySet.begin(); iter!=mySet.end(); ++iter){
cout << *iter << endl;
}
----------------------------------------------------
for( auto& i: mySet ){
cout<<i<<endl;
}
261
The multiset container - usage
multiset<int> mySet;
size_t nrElements = mySet.count(12);
multiset<int>::iterator iter; ?
iter = mySet.find(10);
if (iter == mySet.end()){
cout<<"The element does not exist"<<endl;
}
262
The multiset container - usage
multiset<int> mySet;
auto a = mySet.find(10);
if (a == mySet.end()){
cout<<"The element does not exist"<<endl;
}
263
The set container - usage
class PersonCompare;
class Person {
friend class PersonCompare;
string firstName;
string lastName;
int yearOfBirth;
public:
Person(string firstName, string lastName, int yearOfBirth);
friend ostream& operator<<(ostream& os, const Person& person);
};
264
The set container - usage
class PersonCompare {
function object
public:
enum Criterion { NAME, BIRTHYEAR};
private:
Criterion criterion; state
public:
PersonCompare(Criterion criterion) : criterion(criterion) {}
bool operator()(const Person& p1, const Person& p2) {
behaviour
switch (criterion) {
case NAME: //
case BIRTHYEAR: //
}
}
};
265
The set container - usage
266
The map container
map< Key, Value[,Comp = less<Key>]>
usually implemented as a balanced binary tree
map: associative array multimap: allows duplicates
?
Source: http://www.cpp-tutor.de/cpp/le18/images/map.gif
267
The map container - usage
#include <map>
map<string,int> products;
products.insert(make_pair("tomato",10));
----------------------------------------------
products["cucumber"] = 6;
cout<<products["tomato"]<<endl;
268
The map container - usage
#include <map>
map<string,int> products;
products.insert(make_pair("tomato",10));
----------------------------------------------
products["cucumber"] = 6;
cout<<products["tomato"]<<endl;
Difference between
[ ] and insert!!!
269
The map container - usage
#include <map>
using namespace std;
int main ()
{
map < string , int > m;
cout << m. size () << endl; // 0
if( m["c++"] != 0 ){
cout << "not 0" << endl;
}
cout << m. size () << endl ; // 1
}
[ ] side effect
270
The map container - usage
271
The multimap container - usage
272
The multimap container - usage
273
The multimap container - usage
multimaps do not provide
operator[ ]
multimap<string, string> cities; Why???
cities.insert(make_pair("HU", "Budapest"));
cities.insert(make_pair("HU", "Szeged"));
cities.insert(make_pair("RO", "Seklerburg"));
cities.insert(make_pair("RO", "Neumarkt"));
cities.insert(make_pair("RO", "Hermannstadt"));
274
The set/map container - removal
275
The set – pointer key type
Output??
276
The set – pointer key type
Corrected
struct StringComp{
bool operator()(const string* s1,
const string * s2){
return *s1 < *s2;
}
};
set<string*, StringComp> animals;
animals.insert(new string("monkey"));
animals.insert(new string("lion"));
animals.insert(new string("dog"));
animals.insert(new string("frog"));
-------------------------------------------------------------------
for( auto& i: animals ){
cout<<*i<<endl;
}
277
Hash Tables
collision
http://web.eecs.utk.edu/~huangj/CS302S04/notes/extendibleHashing.htm
278
Hash Tables
Collision resolution by chaining
Source: http://integrator-crimea.com/ddu0065.html
279
Unordered Associative Containers - Hash Tables
– unordered_set
– unordered_multiset C++
2011
– unordered_map
– unordered_multimap
280
Unordered Associative Containers
281
Hash Function
282
The unordered_map container
template <class Key, class T,
class Hash = hash<Key>,
class Pred = std::equal_to<Key>,
class Alloc= std::allocator<pair<const Key, T>>>
class unordered_map;
Template parameters:
283
The unordered_set container
template <class Key,
class Hash = hash<Key>,
class Pred = std::equal_to<Key>,
class Alloc= std::allocator<pair<const Key, T>>>
class unordered_set;
Template parameters:
284
Problem
285
Solutions
286
#include <chrono>
Elapsed time
287
class Class Mo...
RandomNumbers
# size: int
- num bers: set<dou ble> - num bers: uno rdered_set<do uble> - num bers: vector<d ouble>
+ SetRandom Num bers(int) + Unordered SetRandom Num bers(int) + VectorRandom Num bers(int)
+ generate() : vo id + generate () : void + generate () : void
+ getSize() : int + getSize() : in t + getSize() : in t
288
Ellapsed time
289
Which container to use?
290
Which container to use?
– Usage:
PhoneBook pbook;
pbook.addItem("kata","123456");
pbook.addItem("timi","444456");
pbook.addItem("kata","555456");
pbook.addItem("kata","333456");
pbook.addItem("timi","999456");
pbook.addItem("elod","543456");
cout<<pbook<<endl;
291
unordered_map: example
class PhoneBook{
unordered_map<string, vector<string> > book;
public:
void addItem( string name, string phone);
void removeItem( string name, string phone);
vector<string> findItem( string name );
friend ostream& operator<<( ostream& os,
const PhoneBook& book);
};
292
unordered_map: example
typedef unordered_map<string, vector<string> >::iterator Iterator;
293
unordered_map: example
typedef unordered_map<string, vector<string> >::iterator Iterator;
phone will be
inserted into the
map 295
C++/Java
C++ Java
296
Algorithms
297
Algorithms
298
Algorithms – why separation?
STL principles:
– algorithms and containers are independent
– (almost) any algorithm works with (almost) any container
– iterators mediate between algorithms and containers
● provides a standard interface to traverse the elements of
a container in sequence
299
Algorithms
Which one should be used?
set<int> s;
set<int>::iterator it = find(s.begin(), s.end(), 7);
if( it == s.end() ){
//Unsuccessful
}else{
//Successful
}
set<int> s;
set<int>::iterator it = s.find(7);
if( it == s.end() ){
//Unsuccessful
}else{
//Successful
}
300
Algorithms
O(n)
Which one should be used?
set<int> s;
set<int>::iterator it = find(s.begin(), s.end(), 7);
if( it == s.end() ){
//Unsuccessful
}else{
//Successful
}
set<int> s;
set<int>::iterator it = s.find(7);
if( it == s.end() ){
//Unsuccessful
}else{
//Successful
}
O(log n)
301
Algorithm categories
– Utility algorithms
– Non-modifying algorithms
● Search algorithms
● Numerical Processing algorithms
● Comparison algorithms
● Operational algorithms
– Modifying algorithms
● Sorting algorithms
● Set algorithms
302
Utility Algorithms
– min_element()
– max_element()
– minmax_element() C++11
– swap()
303
Utility Algorithms
304
Non-modifying algorithms
Search algorithms
305
Non-modifying algorithms
Search algorithms - Example
int main () {
vector<int> myvector={1,2,3,4,5};
VIT it= find_if (myvector.begin(), myvector.end(), isEven);
cout << "The first even value is " << *it << '\n';
return 0;
}
auto
306
Non-modifying algorithms
Numerical Processing algorithms
– count(), count_if()
– accumulate()
– ...
307
Non-modifying algorithms
Numerical Processing algorithms - Example
int main () {
vector<int> myvector={1,2,3,4,5};
int n = count_if (myvector.begin(), myvector.end(), isEven);
cout << "myvector contains " << n << " even values.\n";
return 0;
}
308
Non-modifying algorithms
Comparison algorithms
– equal()
– mismatch()
– lexicographical_compare()
309
Non-modifying algorithms
Problem
Questions:
● How to represent the alphabet (which container and why)?
alphabet.
310
Non-modifying algorithms
Comparison algorithms - Example
311
Non-modifying algorithms
Comparison algorithms - Example
312
Non-modifying algorithms
Operational algorithms
– for_each()
void doubleValue( int& x){
x *= 2;
}
vector<int> v ={1,2,3};
for_each(v.begin(), v.end(), doubleValue);
313
Non-modifying algorithms
Operational algorithms
– for_each()
void doubleValue( int& x){
x *= 2;
}
vector<int> v ={1,2,3};
for_each(v.begin(), v.end(), doubleValue);
314
Modifying algorithms
– copy(), copy_backward()
– move(), move_backward() C++11
– fill(), generate()
– unique(), unique_copy()
– rotate(), rotate_copy()
– next_permutation(), prev_permutation()
– nth_element() -nth smallest element
315
Modifying algorithms
Permutations
void print( const vector<int>& v){
for(auto& x: v){
cout<<x<<"\t";
}
cout << endl;
}
int main(){
vector<int> v ={1,2,3};
print( v );
while( next_permutation(v.begin(), v.end())){
print( v );
}
return 0;
}
316
Modifying algorithms
nth_element
double median(vector<double>& v) {
int n = v.size();
if( n==0 ) throw domain_error("empty vector");
int mid = n / 2;
// size is an odd number
if( n % 2 == 1 ){
nth_element(v.begin(), v.begin()+mid, v.end());
return v[mid];
} else{
nth_element(v.begin(), v.begin()+mid-1, v.end());
double val1 = v[ mid -1 ];
nth_element(v.begin(), v.begin()+mid, v.end());
double val2 = v[ mid ];
return (val1+val2)/2;
}
}
317
Iterators
318
Outline
319
Iterator Design Pattern
class Framewor...
Aggregate Iterator
+ CreateIterator() + First()
+ Next()
+ IsDone()
+ CurrentItem()
ConcreteAggregate ConcreteIterator
+ CreateIterato r()
return new
ConcretIterator(this)
● The abstraction provided by the iterator pattern allows you to modify the
320
collection implementation without making any change
Iterator Design Pattern - Java
class Framewor...
java.util.Collection java.util.Iterator
Aggregate Iterator
+ CreateIterator() + First()
+ Next()
+ IsDone()
+ CurrentItem()
java.util.LinkedList java.util.ListIterator
ConcreteAggregate ConcreteIterator
+ CreateIterato r()
return new
ConcretIterator(this)
321
Iterator Design Pattern - C++
class Framewor... <iterator>
class iterator
Aggregate Iterator
+ CreateIterator() + First()
+ Next()
+ IsDone()
+ CurrentItem()
list<T> list<T>::iterator
ConcreteAggregate ConcreteIterator
+ CreateIterato r()
return new
ConcretIterator(this)
322
Definition
323
Base class
template <class Category, class T,
class Distance = ptrdiff_t,
class Pointer = T*,
class Reference = T&>
struct iterator {
typedef T value_type;
typedef Distance difference_type;
typedef Pointer pointer;
typedef Reference reference;
typedef Category iterator_category;
};
324
Iterator Categories
– Input Iterator
– Output Iterator
– Forward Iterator
– Bidirectional Iterator
– Random Access Iterator
325
Iterator Categories
326
Basic Operations
327
Input Iterator
template<class InIt, class T>
InIt find( InIt first, InIt last, T what)
{
for( ; first != last; ++first )
if( *first == what ){
return first;
}
return first;
}
328
Input Iterator
template<class InIt, class Func>
Func for_each( InIt first, InIt last,
Func f){
for( ;first != last; ++first){
f( *first );
}
return f;
}
329
Output Iterator
template <class InIt, class OutIt>
OutIt copy( InIt first1, InIt last1,
OutIt first2){
while( first1 != last1 ){
*first2 = *first1;
first1++;
first2++;
}
return first2;
}
330
Forward Iterator
template < class FwdIt, class T >
void replace ( FwdIt first, FwdIt last,
const T& oldv, const T& newv ){
for (; first != last; ++first){
if (*first == oldv){
*first=newv;
}
}
}
331
Bidirectional Iterator
template <class BiIt, class OutIt>
OutIt reverse_copy ( BiIt first, BiIt
last, OutIt result){
while ( first!=last ){
--last;
*result = *last;
result++;
}
return result;
}
332
Find the second element!
template <class T, class It>
It findSecond(It first, It last, const T& what){
???
}
333
Find the second element!
template <class T, class It>
It findSecond(It first, It last, const T& what){
while( first != last && *first != what ){
++first;
}
if( first == last ){
return last;
}
++first;
while( first != last && *first != what ){
++first;
}
return first;
}
334
Containers & Iterators
335
Iterator adapters
– Reverse iterators
– Insert iterators
– Stream iterators
336
Reverse iterators
337
Insert iterators
338
Insert iterator - Example
//Incorrect
int x[] = {1, 2, 3};
vector<int> v;
copy( x, x+3, v.begin());
//Correct
int x[] = {1, 2, 3};
vector<int> v;
copy( x, x+3, back_inserter(v));
339
Insert iterator - Example
340
Types of insert iterators
*pos = value;
341
Stream iterators
342
Stream iterator - examples
vector<int> v;
copy(v.begin(), v.end(),
ostream_iterator<int>(cout, ","));
copy(istream_iterator<int>(cin),
istream_iterator<int>(),
back_inserter(v));
343
Problem 1.
● It is given a CArray class
string str[]=
{"apple", "pear", "plum",
"peach", "strawberry", "banana"};
344
Problem 1.
● It is given a Smart API too
Smart<string> smart;
smart.doIt( ? );
345
Problem 1. - Solution
347
Problem 2.
● It is given a Smarter API
class Smarter{
public:
template <class RaIt>
void doIt( RaIt first, RaIt last ){
while( first != last ){
cout<< *first <<std::endl;
++first;
}
}
};
348
Problem 2.
● Call the doIt function in the given way!
349
Problem 2. - Solution A.
template<class T>
class CArray{
public:
class iterator{
T* poz;
public: ...
};
350
Problem 2. - Solution A.
class CArray{
public:
class iterator{
T* poz;
public:
iterator( T* poz=0 ): poz( poz ){}
iterator( const iterator& it ){ poz = it.poz; }
iterator& operator=( const iterator& it ){
if( &it == this ) return *this;
poz = it.poz; return *this;}
iterator operator++(){ poz++; return *this; }
iterator operator++( int p ){
iterator temp( *this ); poz++; return temp;}
bool operator == ( const iterator& it )const{
iteratorreturn
begin(){
poz ==return iterator(array);}
it.poz;}
iterator end(){ !=
bool operator return iterator(array+size);}
( const iterator& it )const{
private: return poz != it.poz; }
T * T&
array;
operator*() const { return *poz;}
}; size;
int
};
351
Problem 2. - Solution B.
class CArray{
public:
typedef T * iterator;
352
Carray → iterator
template <class T>
class CArray{
T * data;
int size;
public:
...
typedef T* iterator;
typedef T value_type;
typedef T& reference;
typedef ptrdiff_t difference_type;
typedef T * pointer;
};
353
Module 9
Function Objects & Lambdas
354
Function object
class
– FunctionObjectType {
public:
return_type operator() (parameters) {
Statements
}
};
355
Function pointer vs. function object
356
Function object as a sorting criteria
class PersonSortCriterion {
public:
bool operator() (const Person& p1, const Person& p2)
const {
if (p1.lastname() != p2.lastname() ){
return p1.lastname() < p2.lastname();
} else{
return p1.firstname()<p2.firstname());
}
};
357
Function object with internal state
class IntSequence{
private:
int value;
public:
IntSequence (int initialValue) : value(initialValue) {
}
int operator() () {
return ++value;
}
};
358
Function object with internal state
[Josuttis]
list<int> coll;
359
Function object with internal state
[Josuttis]
list<int> coll;
???
360
Function object with internal state + for_each
[Josuttis]
class MeanValue {
private:
long num; // number of elements
long sum; // sum of all element values
public:
MeanValue () : num(0), sum(0) {}
void operator() (int elem) {
++num; // increment count
sum += elem; // add value
}
double value () {
return static_cast<double>(sum) / num;
}
};
361
function object with internal state + for_each
[Josuttis]
int main()
{
vector<int> coll = { 1, 2, 3, 4, 5, 6, 7, 8 };
362
Predicates
363
Predefined function objects
Expression Effect Expression Effect
364
Syntactic sugar
Lambdas
C++
2011
#include <iostream>
int main()
{
auto func = [] () { cout << "Hello world"; };
func(); // now call the function
}
365
Syntactic sugar
Lambdas
366
Syntactic sugar
Lambda syntax
[ ] ( )opt -> opt
{ }
[ captures ]
( params )
-> ret
{ statements; }
Herb Sutter: nwcpp.org/may-2011.html
The body of the lambda
367
Syntactic sugar
Examples
lamb();
int i = 42;
368
Syntactic sugar
Lambdas == Functors
class __functor {
private:
CaptureTypes __captures;
public:
__functor( CaptureTypes captures )
: __captures( captures ) { }
369
Syntactic sugar
Capture Example
class __functor {
private:
C1 __c1; C2& __c2;
public:
__functor( C1 c1, C2& c2 )
: __c1(c1), __c2(c2) { }
370
Syntactic sugar
Parameter Example
class __functor {
public:
void operator() ( P1 p1, const P2& p2) {
f(p1, p2);
}
371
Syntactic sugar
Type of Lambdas
372
Syntactic sugar
Type of Lambdas
373
Example
int x = 5;
int y = 12;
auto pos = find_if (
coll.cbegin(), coll.cend(), // range
[=](int i){return i > x && i < y;}// search criterion
);
cout << "first elem >5 and <12: " << *pos << endl;
374
Example
375
Module 10
Advanced C++
376
Outline
– Casting. RTTI
– Handling Errors
– Smart Pointers
– Random Numbers
– Regular Expressions
377
Casting & RTTI
378
Casting
379
static_cast<>() vs. C-style cast
380
Run Time Type Information
381
Casting Up and Down
class Super{
public:
virtual void m1();
};
class Sub: public Super{
public:
virtual void m1();
void m2();
};
Sub mySub;
//Super mySuper = mySub; // SLICE
Super& mySuper = mySub; // No SLICE
mySuper.m1(); // calls Sub::m1() - polymorphism
mySuper.m2(); // ???
382
dynamic_cast<>
class Base{};
class Derived : public Base{};
derivedPointer = dynamic_cast<Derived*>(basePointer);
if (derivedPointer != nullptr){
cout << "basePointer is pointing to a Derived class object";
}else{
cout << "basePointer is NOT pointing to a Derived class object";
}
383
dynamic_cast<>
class Person{
public: virtual void print(){cout<<”Person”;};
};
class Employee:public Person{
public: virtual void print(){cout<<”Employee”;};
};
class Manager:public Employee{
public: virtual void print(){cout<<”Manager”;};
};
vector<Person*> v;
v.push_back(new Person());
v.push_back(new Employee());
v.push_back( new Manager());
...
384
dynamic_cast<>
class Person{
public: virtual void print(){cout<<”Person”;};
};
class Employee:public Person{
public: virtual void print(){cout<<”Employee”;};
};
class Manager:public Employee{
public: virtual void print(){cout<<”Manager”;};
};
385
dynamic_cast<>
class Person{
public: virtual void print(){cout<<”Person”;};
}; Write a code that counts
class Employee:public Person{ the number of employees!
public: virtual void print(){cout<<”Employee”;};
};
class Manager:public Employee{
public: virtual void print(){cout<<”Manager”;};
}; Employee * p = nullptr;
for( Person * sz: v ){
vector<Person*> v; p = dynamic_cast<Employee *>( sz );
v.push_back(new Person()); if( p != nullptr ){
v.push_back(new Employee());
++counter;
v.push_back( new Manager());
... }
}
386
Which solution is better? (Solution 1)
….
Bird bird; Dog d;
speak(bird); speak( dog ); ???
387
Which solution is better? (Solution 2)
class Animal{
public:
virtual void speak()=0;
};
class Dog:public Animal{
public:
virtual void speak(){cout<<"VauVau"<<endl;};
};
class Bird: public Animal{
public:
virtual void speak(){cout<<"Csirip"<<endl;};
};
388
typeid
class Person{
public: virtual void print(){cout<<”Person”;};
}; Write a code that counts the number of
class Employee:public Person{
employees (the exact type of the objects is
public: virtual void print(){cout<<”Employee”;};
Employee)!
};
class Manager:public Employee{
public: virtual void print(){cout<<”Manager”;};
};
counter = 0;
vector<Person*> v; for( Person * sz: v ){
v.push_back(new Person()); if( typeid(*sz) == typeid(Employee) ){
v.push_back(new Employee()); ++counter;
v.push_back( new Manager());
... }
}
389
Typeid usage
a and b are of different types:
#include <iostream> a is: Pi
#include <typeinfo> b is: i
using namespace std;
int main ()
{
int * a;
int b;
a=0; b=0;
if (typeid(a) != typeid(b))
{
cout << "a and b are of different types:\n";
cout << "a is: " << typeid(a).name() << '\n';
cout << "b is: " << typeid(b).name() << '\n';
}
return 0;
}
390
Handling Errors
391
Handling Errors
392
Return type vs. Exceptions
393
<stdexcept>
Exceptions
394
<stdexcept>
Exceptions
395
<stdexcept>
HandExceptions
try {
// Code that can throw exceptions
} catch (const invalid_argument& e) {
// Handle invalid_argument exception
} catch (const runtime_error& e) {
// Handle runtime_error exception
} catch (...) {
// Handle all other exceptions
}
Any exception
396
<stdexcept>
Throw List
397
<stdexcept>
Throw List
http://www.cplusplus.com/doc/tutorial/exceptions/
398
The Standard Exceptions
<stdexcept>
http://cs.stmarys.ca/~porter/csc/ref/cpp_standlib.html
399
User Defined Exception
<stdexcept>
– It is recommended to inherit
exception
directly or indirectly from the standard
exception class
your_exception
400
User Defined Exception
<stdexcept>
401
Smart Pointers
402
Outline
403
Why Smart Pointers?
dangling pointers
● Double-freeing
404
Smart Pointer Types
405
Smart Pointers
– Type of ownership:
● unique
● shared
406
The good old pointer
void oldPointer(){
Foo * myPtr = new Foo();
myPtr->method();
} Memory leak
407
The good Old pointer
void oldPointer1(){
Foo * myPtr = new Foo();
myPtr->method();
} Memory leak
void oldPointer2(){
Foo * myPtr = new Foo(); Could cause
myPtr->method(); memory leak
delete myPtr; When?
}
408
The Old and the New
void oldPointer(){
Foo * myPtr = new Foo();
myPtr->method();
} Memory leak
void newPointer(){
shared_ptr<Foo> myPtr (new Foo());
myPtr->method();
}
409
Creating smart pointers
void newPointer(){
shared_ptr<Foo> myPtr (new Foo());
myPtr->method();
}
void newPointer(){
auto myPtr = make_shared<Foo>();
myPtr->method();
}
Static
factory method 410
unique_ptr
411
shared_ptr
412
Implementing your own smart pointer class
:Person
p: CountedPtr<Person>
"Para Peti"
ptr
count
1
413
Implementing your own smart pointer class
CountedPtr<Person> p1 = p;
CountedPtr<Person> p2 = p;
p :Person
ptr
count "Para Peti"
p1
3
ptr
count
p2
ptr
count
414
Implementation (1)
415
Implementation (2)
CountedPtr( T * p = 0 ):ptr( p ),
count( new long(1)){
}
~CountedPtr(){
--(*count);
if( *count == 0 ){
delete count; delete ptr;
}
}
416
Implementation (3)
CountedPtr<T>& operator=( const CountedPtr<T>& p ){
if( this != &p ){
--(*count);
if( *count == 0 ){ delete count; delete ptr; }
this->ptr = p.ptr;
this->count = p.count;
++(*count);
}
return *this;
}
417
Shared ownership with shared_ptr
Container of Container of
smart pointers smart pointers
sp sp
sp sp
sp sp
o1 o2 o3
http://umich.edu/~eecs381/handouts/C++11_smart_ptrs.pdf
418
Problem with shared_ptr
sp sp
sp
sp
sp sp
http://umich.edu/~eecs381/handouts/C++11_smart_ptrs.pdf
419
Solution: weak_ptr
sp wp
sp
sp
wp wp
http://umich.edu/~eecs381/handouts/C++11_smart_ptrs.pdf
420
weak_ptr
421
How smart pointers work
shared_ptr
Manager object Managed object
sp1
Pointer
Shared count: 3
sp2
Weak count: 2
sp3
wp1 wp2
weak_ptr
http://umich.edu/~eecs381/handouts/C++11_smart_ptrs.pdf
422
Restrictions in using smart pointers
http://umich.edu/~eecs381/handouts/C++11_smart_ptrs.pdf
423
Inheritance and shared_ptr
424
unique_ptr usage
Static
Factory Method 425
unique_ptr usage (2)
unique_ptr<Person> uptr1 =
make_unique<Person>("Mary","Black");
unique_ptr<Person> uptr2 = make_unique<Person>("John","Dee");
cout<<*uptr2<<endl;
426
unique_ptr usage (2)
unique_ptr<Person> uptr1 =
make_unique<Person>("Mary","Black");
unique_ptr<Person> uptr2 = make_unique<Person>("John","Dee");
cout<<*uptr2<<endl;
cout<<"Vec [";
for( auto& e: vec ){
cout<<*e<<" ";
}
cout<<"]"<<endl;
427
Module 11
I/O Streams
428
Outline
– Using Streams
– String Streams
– File Streams
– Bidirectional I/O
429
Using Streams
Prog-
ram
stream:
● is data flow
● direction
430
Using Streams
431
Using Streams
– Stream:
● includes data
432
Using Streams
ios_base basic_streambuf<>
streambuf, wstreambuf
basic_ios<>
ios, wios
basic_istream<> basic_ostream<>
istream, wistream ostream, wostream
basic_iostream<>
iostream, wiostream
433
Using Streams
– Output stream:
● inserter operator <<
● raw output methods (binary):
– put(), write()
434
Using Streams
– Output stream:
● most output streams buffer data (accumulate)
● the stream will flush (write out the accumulated data)
when:
– an endline marker is reached ('\n', endl)
– the stream is destroyed (e.g. goes out of scope)
– the stream buffer is full
– explicitly called flush()
435
Using Streams
– Manipulators:
● objects that modify the behavior of the stream
– setw, setprecision
– hex, oct, dec
– C++11: put_money, put_time
int i = 123;
printf(“This should be ' 123': %6d\n”, i);
cout <<“This should be ' 123': “ << setw(6) << i << endl;
436
Using Streams
– Input stream:
● extractor operator >>
– will tokenize values according to white spaces
● raw input methods (binary): reads an input having
more than one word
– get(): avoids tokenization
437
Using Streams
– Input stream:
● getline(): reads until end of line
string myString;
getline(cin, myString);
438
Using Streams
– Input stream:
● getline(): reads until end of line
string myString;
getline(cin, myString);
439
Using Streams
– Stream's state:
● every stream is an object → has a state
● stream's states:
– good: OK
– eof: End of File
– fail: Error, last I/O failed
– bad: Fatal Error
440
Using Streams
– Find the error!
list<int> a;
int x; Input:
1
while( !cin.eof() ){ 2
cin>>x; 3
a.push_back( x ); (empty line)
} a: 1, 2, 3, 3
441
Using Streams
– Handling Input Errors:
● while( cin )
● while( cin >> ch )
int number, sum = 0; int number, sum = 0;
while ( true ) { while ( cin >> number ){
cin >> number; sum += number;
if (cin.good()){ }
sum += number;
} else{
break;
}
}
442
String Streams
– <sstream>
● ostringstream
● istringstream
● stringstream
443
File Streams
{
ifstream ifs("in.txt");//Constructor
if( !ifs ){
//File open error
}
//Destructor call will close the stream
}
{
ifstream ifs;
ifs.open("in.txt");
//...
ifs.close();
//...
}
444
File Streams
– Byte I/O
ifstream ifs("dictionary.txt");
// ios::trunc means that the output file will be
// overwritten if exists
ofstream ofs("dict.copy", ios::trunc);
char c;
while( ifs.get( c ) ){
ofs.put( c );
}
445
File Streams
– Byte I/O
– Using rdbuf() - quicker
ifstream ifs("dictionary.txt");
– // ios::trunc means that the output file will be
// overwritten if exists
ofstream ofs("dict.copy", ios::trunc);
446
Object I/O
– Operator overloading
istream& operator>>( istream& is, T& v ){
//read v
return is;
}
447