Advanced C++ PDF
Advanced C++ PDF
Cosmin Stan
[email protected]
Topics
OOP in C++
Copying and Conversions
Scope
Delegation
Subscripting
Template functions
Template classes
Template techniques
Iterators and Algorithms
Exception handling
Memory management
Reference counting
Inheritance techniques
Functional abstraction
C++11 language enhancements
Multithreading techniques
2
Day 1
OOP In C++
Example
//
01_01_ClassesAndObjects
#include <iostream>
class Point{ // Point is a class
public:
int x, y;
void print(){
std::cout << "(" << x << "," << y << ")\n";
}
void multiply(int factor){
x *= factor;
y *= factor;
}
};
int main() {
Point p; // p is an object of class Point
p.print();
p.x = 2;
p.y = 3;
p.print();
p.multiply(3);
p.print();
return 0;
}
Output:
(1606416240,32767)
(2,3)
(6,9)
01_01a_ClassesAndObjects
#include <iostream>
class Point{ // Point is a class
public:
int x, y;
//
Point():x(0),y(0){}
Point(){
x = 0;
y = 0;
}
void print(){
std::cout << "(" << x << "," << y << ")\n";
}
};
int main() {
Point p; // p is an object of class Point
p.print();
p.x = 2;
p.y = 3;
p.print();
p.multiply(3);
p.print();
return 0;
}
Output:
(0,0)
(2,3)
(6,9)
01_01b_ClassesAndObjects
#include <iostream>
class Point{ // Point is a class
public:
int x, y;
Point():x(0),y(0){}
Point(int x, int y):x(x), y(y){}
void print(){
std::cout << "(" << x << "," << y << ")\n";
}
};
int main() {
Point p; // p is a object of class Point
p.print();
Point q(1,2); // q is an object of class Point
q.print();
q.multiply(10);
q.print();
return 0;
}
Output:
(0,0)
(1,2)
(10,20)
Abstraction
Access modifiers
Example
//
01_02_Abstraction
Point q(1,2);
q.multiply(10);
q.print();
#include <iostream>
ShowPointContents(&q);
return 0;
void print(){
std::cout << "(" << x << "," << y << ")\n";
}
void multiply(int factor){
x *= factor;
y *= factor;
}
};
void ShowPointContents(Point * p){
std::cout << "(" << p->x << "," << p->y << ")\n";
}
int main() {
Point p;
p.print();
// p.x = 2; // this would not compile
Output:
(0,0)
(10,20)
(10,20)
12
Encapsulation
13
Example
//
01_03_Encapsulation
void printEquation(){
std::cout << "Equation: " << a << "*x^2" << ((b > 0)?"+" :
"" )<< b << "x" << ((c > 0)?"+" : "")<< c << "\n";
}
private:
QuadraticEquation (): a(0), b(0), c(0) { };
int a, b, c, delta;
float x1, x2;
bool isComplex;
};
#include <iostream>
#include <math.h>
class QuadraticEquation{
public:
QuadraticEquation(int a, int b, int c): a(a), b(b), c(c){
delta = b*b - 4*a*c;
isComplex = false;
if (delta > 0){
x1 = ((-b) - sqrt(delta)) / (2*a);
x2 = ((-b) + sqrt(delta)) / (2*a);
}
else if (delta == 0){
x1 = x2 = (-b)/(2*a);
}
else {
isComplex = true;
}
}
return true;
Equation: 1*x^2-4x+1
x1 = 0
x2 = 3
Equation: 1*x^2-2x+1
x1 = 1
x2 = 1
Equation: 1*x^2+1x+1
The solutions to this equation are complex numbers
14
Association
15
16
01_04_Association_Aggregation_Composition
#include <iostream>
"\n";
class Application{
public:
Application(const char *name) : name(name){};
std::string & getName(){
return name;
}
private:
Application() {};
std::string name;
};
class AppStore{
public:
AppStore(const char *name): name(name), appCount(0) {
applications = new Application*[10];
};
}
}
private:
Application ** applications;
int appCount;
std::string name;
AppStore() {};
};
class Smartphone{
public:
Smartphone(const char *name): name(name), appCount(0)
{
applications = new Application*[10];
};
~Smartphone(){
delete [] applications;
}
void installApplication(AppStore &appStore,
std::string const &appName){
Application *newApp =
appStore.getApplication(appName);
if (newApp != nullptr){
applications[appCount++] = newApp;
}
Smartphone() {};
};
~AppStore(){
delete [] applications;
}
void addApplication (Application* app){
applications[appCount++] = app;
}
private:
Application ** applications;
int appCount;
std::string name;
googlePlay.listApps();
appStore.listApps();
void listApps(){
std::cout << "Apps installed on " << name << ":\n";
for (int i = 0; i < appCount; ++i){
std::cout << applications[i]->getName() <<
samsung.listApps();
iphone.listApps();
"\n";
return 0;
}
void listApps(){
17
Inheritance
18
public
protected
private
Same class
YES
YES
YES
Derived classes
YES
YES
NO
Outside
classes
YES
NO
NO
19
Types of inheritance
public inheritance
public members of the base class become public members of the derived
class
protects members of the base class become protected members of the derived
class
protected inheritance
public and protected members of the base class become protected members
of the derived class
private inheritance
public and protected members of the base class become private members of
the derived class
NOTE!
The private members of a class are never accessible to the derived classes. They
are, however, accessible to friend classes or functions.
20
Inheritance Example
//
01_05_Inheritance
};
#include <iostream>
class Phone{
public:
Phone(const char* manufacturer) :
manufacturer(manufacturer){};
std::string const & getManufacturer (){
return manufacturer;
}
protected:
std::string manufacturer;
private:
Phone() : manufacturer("") {};
};
21
22
Drawable
Rectangle
Object
23
01_06_Multiple_Inheritance
#include <iostream>
class Phone{
public:
Phone(const char *manufacturer) :
manufacturer(manufacturer){};
std::string const & getManufacturer (){
return manufacturer;
}
private:
std::string manufacturer;
Phone() : manufacturer("") {};
};
class Computer {
public:
Computer (const char *os) : os(os){};
std::string const & getOS(){
return os;
}
private:
std::string os;
Computer() : os("") {};
};
class Smartphone: public Phone, public Computer {
public:
24
Polymorphism
Polymorphism
Example
//
01_07_Polymorphism
#include <iostream>
};
class Computer {
public:
virtual std::string manufacturer(){
return std::string("Dell");
}
virtual std::string whatAmI(){
return std::string("I'm a computer");
}
std::cout << computer->whatAmI() << " made by " << computer>manufacturer() << "\n";
std::cout << smartphone->whatAmI() << " made by " <<
smartphone->manufacturer() << "\n";
std::cout << iPhone->whatAmI() << " made by " << iPhone>manufacturer() << "\n";
std::cout << tablet->whatAmI() << " made by " << tablet>manufacturer() << "\n";
Output:
I'm a computer made by Dell
I'm a smartphone made by Apple
I'm an iPhone made by Apple
I'm a tablet made by Dell
My network is Orange
27
28
Type casting
Example
//
02_01_Type_Casting
#include <iostream>
class Point{ // Point is a class
public:
Point(int x, int y):x(x), y(y){}
void print(){
std::cout << "(" << x << "," << y << ")\n";
}
private:
int x, y;
Point():x(0),y(0){}
};
int main(int argc, const char * argv[]) {
int nr(10);
Point * p = (Point*)&nr;
p->print();
return 0;
}
Output:
(10,1606416256)
31
static_cast <new_type>(expression)
static_cast <new_type>(expression)
Example
//
02_02_Static_Cast
#include <iostream>
class Animal
{
public:
void toString(){
std::cout << "I'm a generic Animal!\n";
}
};
duck->toString();
human->toString();
Animal *animal = static_cast<Animal *>(duck);
animal->toString();
Animal *anotherAnimal = new Animal();
Duck *anotherDuck = static_cast<Duck *>(anotherAnimal);
//anotherDuck->toString(); // CRASH!!
std::cout << "Address value of human is:" << human << "\n";
void *pToHuman = static_cast<void *>(human);
ShowDetails(pToHuman);
class Human
{
public:
virtual void toString(){
std::cout << "I'm a human and my name is Joe!\n";
}
};
Output:
I'm a duck and my name is Donald!
I'm a human and my name is Joe!
I'm a generic Animal!
Address value of human is:0x100100b50
Address value of human after re-cast is:0x100100b50
I'm a human and my name is Joe!
34
delete duck;
delete human;
return 0;
dynamic_cast <new_type>(expression)
35
dynamic_cast <new_type>(expression)
If the pointer cast fails, it returns a null pointer of the new type.
Can be used to add const-ness, but it cannot remove the const-ness or volatility
of an object
If performed on null, the result will be a null object of the new type
dynamic_cast <new_type>(expression)
Example
//
02_03_Dynamic_Cast
int main(int argc, const char * argv[]) {
Animal *animal = new Animal();
Animal *duck = new Duck();
#include <iostream>
class Animal
{
public:
virtual void toString(){
std::cout << "I'm a generic Animal!\n";
}
};
animal->toString();
duck->toString();
Duck *duckFromDuck = dynamic_cast<Duck *>(duck);
if (duckFromDuck == nullptr) std::cout << "Invalid cast
Duck from Duck!\n";
else duckFromDuck->toString();
virtual ~Duck(){
delete name;
}
delete animal;
delete duck;
return 0;
}
private:
std::string *name;
};
Output:
I'm a generic Animal!
I'm a duck and my name
I'm a duck and my name
I'm a duck and my name
Invalid cast Duck from
is Donald!
is Donald!
is Donald!
Animal!
38
Example - References
//
02_03_Dynamic_Cast_References
int main(int argc, const char * argv[]) {
Animal animal = Animal();
Duck duck = Duck();
#include <iostream>
class Animal
{
public:
virtual void toString(){
std::cout << "I'm a generic Animal!\n";
}
};
animal.toString();
duck.toString();
try {
Animal &animalFromDuck = dynamic_cast<Animal &>(duck);
animalFromDuck.toString();
Duck &duckFromAnimal = dynamic_cast<Duck &>(animal);
duckFromAnimal.toString();
virtual ~Duck(){
delete name;
}
private:
std::string *name;
};
Output:
I'm a generic Animal!
I'm a duck and my name is Donald!
I'm a duck and my name is Donald!
Exception: std::bad_cast
39
reinterpret_cast <new_type>(expression)
Example
//
02_04_Reinterpret_Cast
#include <iostream>
class Animal
{
public:
void toString(){
std::cout << "I'm a generic Animal!\n";
}
};
duck->toString();
human->toString();
Animal *animal = reinterpret_cast<Animal *>(duck);
animal->toString();
Animal *anotherAnimal = new Animal();
Duck *anotherDuck = reinterpret_cast<Duck *>(anotherAnimal);
//anotherDuck->toString(); // CRASH!!
virtual ~Duck(){
delete name;
}
private:
std::string *name;
};
class Human
{
public:
virtual void toString(){
std::cout << "I'm a human and my name is Joe!\n";
}
};
Output:
I'm a duck and my name is Donald!
I'm a human and my name is Joe!
I'm a generic Animal!
Address value of human is:0x1002000b0
Address value of human after re-cast is:0x1002000b0
I'm a human and my name is Joe!
41
delete duck;
delete human;
return 0;
const_cast <new_type>(expression)
42
const_cast <new_type>(expression)
Two possibly multilevel pointers to the same type may be converted between each
other, regardless of cv-qualifiers at each level.
lvalue of any type T may be converted to a lvalue or rvalue reference to the same
type T, more or less cv-qualified. Likewise, an rvalue may be converted to a more or
less cv-qualified rvalue reference.
null pointer value may be converted to the null pointer value of new_type
a prvalue otherwise
43
Example
//
02_05_Const_Cast
return 0;
#include <iostream>
Output:
I have to print this: Const Random string
I have to print this: Radom string
I have to print this in uppercase: RADOM STRING
44
typeid
Example
//
02_06_Typeid
#include <iostream>
#include <cxxabi.h>
class Animal
{
public:
virtual void toString(){
std::cout << "I'm a generic Animal!\n";
}
};
std::cout
std::cout
std::cout
"\n";
std::cout
delete animal;
delete duck;
return 0;
}
private:
std::string *name;
};
Output:
P4Duck
Animal*
Duck
int
46
Mutable objects
48
Example
//
02_07_Logical_Const
std::cout << "Nr of uses for the sum function is: " <<
addition.numberOfUses() << \n";
#include <iostream>
delete a;
class Addition{
public:
Addition (int a, int b) : a(a), b(b), nrOfUses(0) {};
return 0;
}
Output:
Addition result is 7
Nr of uses for the sum function is: 1
49
Implicit conversion
Sometimes, the conversion does not represent the same value exactly:
From negative to unsigned
From/to bool considers false to be 0 (or null, for pointers), and true
for all other values. From bool, true is converted to 1
Floating to integer (the decimal part is discarded)
50
Implicit conversion
Constructor conversions
Example
//
02_08_Implicit_Conversion
double f = 2.4f;
IntNumber x;
IntNumber y(2);
IntNumber z = 4;
IntNumber t = f;
int a = x + 2 * y + z;
float b = y + 2.4f;
Point p1 {2, a};
Point p2 = {y, z};
Point p3(p2);
#include <iostream>
class IntNumber {
public:
IntNumber() : value(0) {}
IntNumber(int val) : value(val) {}
operator int() {return value;}
IntNumber & operator=(int val) {value = val; return *this;}
private:
int value;
};
std::cout
std::cout
std::cout
std::cout
std::cout
std::cout
std::cout
std::cout
std::cout
class Point{
public:
Point():x(0),y(0){}
Point(int x, int y):x(x), y(y){}
Point(const Point &p): x(p.x), y(p.y){}
void print(){
std::cout << "(" << x << "," << y << ")\n";
}
private:
int x, y;
};
<<
<<
<<
<<
<<
<<
<<
<<
<<
if (t == 2){
std::cout << "t is 0" << "\n";
}
PrintBoolValue(y);
PrintBoolValue(f);
return 0;
Output:
x = 0
y = 2
z = 4
t = 2
a = 8
b = 4.4
p1 = (2,8)
p2 = (2,4)
p3 = (2,4)
t is 0
bool val is true
bool val is true
54
explicit keyword
Example
//
02_09_Explicit_Keyword
#include <iostream>
class IntNumber {
public:
IntNumber() : value(0) {}
explicit IntNumber(int val) : value(val) {}
explicit operator int() {return value;}
IntNumber & operator=(int val) {value = val; return *this;}
private:
int value;
};
class Point{
public:
std::cout
std::cout
std::cout
std::cout
explicit Point():x(0),y(0){}
explicit Point(int x, int y):x(x), y(y){}
explicit Point(const Point &p): x(p.x), y(p.y){}
void print(){
std::cout << "(" << x << "," << y << ")\n";
}
private:
int x, y;
};
<<
<<
<<
<<
if ((int)y == 2){
std::cout << "t is 0" << "\n";
}
//PrintBoolValue(y); // ERROR: No matching function for call to
'PrintBoolValue'
PrintBoolValue(f);
Output:
x = 0
y = 2
p3 = (3,9)
p4 = (3,9)
t is 0
bool val is true
56
return 0;
57
Rule of three
58
Rule of five
Example
//
02_10_Rule_Of_Five
}
virtual ~SmartStudent(){
free(name);
}
void printName(){
std::cout << "My name is " << name << "\n";
}
private:
SmartStudent(): name(nullptr){};
char *name;
};
#include <iostream>
class Student{
public:
Student(const char *_name){
name = strdup(_name);
}
virtual ~Student(){
free(name);
}
void printName(){
std::cout << "My name is " << name << "\n";
}
private:
Student(): name(nullptr){};
char *name;
};
class SmartStudent{
public:
SmartStudent(const char *_name){
name = strdup(_name);
}
SmartStudent(const SmartStudent &stud){
name = strdup(stud.name);
}
SmartStudent(SmartStudent &&stud){
name = stud.name;
stud.name = nullptr;
}
SmartStudent & operator=(const SmartStudent &stud){
name = strdup(stud.name);
return *this;
}
SmartStudent & operator=(SmartStudent &&stud){
name = stud.name;
stud.name = nullptr;
return *this;
{
}
barney.printName();
}
Output:
x = 0
y = 2
p3 = (3,9)
p4 = (3,9)
t is 0
bool val is true
60
return 0;
Exercise 1
Day 2
Scope
Example
//
03_01_Static_Members
#include <iostream>
class Animal{
public:
Animal() {nrOfInstances++;}
static int nrOfInstances;
};
int Animal::nrOfInstances = 0;
int main(int argc, const char * argv[]) {
std::cout << "Nr of Animal instances:" <<
Animal::nrOfInstances << "\n";
Animal wolf;
Animal zebra, lion;
std::cout << "Nr of Animal instances:" <<
zebra.nrOfInstances << "\n";
Animal monkey((Animal(lion)));
std::cout << "Nr of Animal instances:" <<
Animal().nrOfInstances << "\n";
return 0;
}
Output:
Nr of Animal instances:0
Nr of Animal instances:3
Nr of Animal instances:4
65
66
67
Diagram
68
03_02_A_Singleton_Pattern_Pointers
#include <iostream>
class Logger{
public:
void logMessage(const char *message){
std::cout << message;
}
static Logger* getInstance(){
if (loggerInstance == nullptr){
loggerInstance = new Logger();
}
return loggerInstance;
}
private:
Logger() {};
Logger (Logger const &);
Logger & operator=(Logger const &);
static Logger *loggerInstance;
};
Logger *Logger::loggerInstance = 0;
int main(int argc, const char * argv[]) {
// insert code here...
Logger::getInstance()->logMessage("Log message\n");
Output:
Log message
Log another message
69
03_02_B_Singleton_Pattern_References
#include <iostream>
class Logger{
public:
void logMessage(const char *message){
std::cout << message;
}
static Logger& getInstance(){
static Logger loggerInstance;
return loggerInstance;
}
private:
Logger() {};
Logger (Logger const &);
Logger & operator=(Logger const &);
};
int main(int argc, const char * argv[]) {
// insert code here...
Logger::getInstance().logMessage("Log message\n");
Logger::getInstance().logMessage("Log another message\n");
return 0;
}
Output:
Log message
Log another message
70
Nested classes
Nested classes are not visible outside the scope of their enclosing
classes
Friend functions in a nested class are not friend functions for the
enclosing class, so they do not have any special privileges in the
enclosing class
71
72
Example
//
03_03_Nested_Classes
#include <iostream>
last = newNode;
}
void printAll(){
std::cout << "All values:";
Node *current = first;
while (current != nullptr) {
std::cout << current->value << " ";
current = current->next;
}
std::cout << "\n";
}
private:
class Node{
public:
int value;
Node *prev, *next;
Node(): prev(nullptr), next(nullptr), value(0) {}
};
Node *first;
Node *last;
};
class DoubleLinkedList{
public:
DoubleLinkedList(): first(nullptr), last(nullptr) {}
virtual ~DoubleLinkedList(){
Node *currentNode = first;
while (currentNode != nullptr) {
Node *nextNode = currentNode->next;
delete currentNode;
currentNode = nextNode;
}
};
void addFront(int value){
Node *newNode = new Node();
newNode->value = value;
newNode->prev = nullptr;
newNode->next = first;
if (first == nullptr){
first = last = newNode;
} else {
first->prev = newNode;
first = newNode;
}
}
void addBack(int value){
Node *newNode = new Node();
newNode->value = value;
newNode->prev = last;
newNode->next = nullptr;
if (last == nullptr){
first = last = newNode;
} else {
last->next = newNode;
Output:
All values:12 20 10 3
73
Example
//
//
DoubleLinkedList.hpp
03_04_ Cheshire_Cat
//
//
main.cpp
03_04_ Cheshire_Cat
#ifndef DoubleLinkedList_hpp
#define DoubleLinkedList_hpp
#include <iostream>
#include "DoubleLinkedList.hpp"
#include <iostream>
class DoubleLinkedList{
public:
DoubleLinkedList();
virtual ~DoubleLinkedList();
void addFront(int value);
void addBack(int value);
void printAll();
private:
class Node;
Node *first;
Node *last;
};
#endif /* DoubleLinkedList_hpp */
Output:
All values:12 20 10 3
75
Namespaces
using declaration
Example
//
03_05_Namespaces
#include <iostream>
#include <math.h>
namespace RealConstants{
double pi = 3.14159;
double e = 2.71828;
}
namespace GeometricalFigures {
class Circle{
public:
Circle(double r): radius(r){}
double Area(){
using namespace RealConstants;
return pi * radius * radius;
}
private:
Circle();
double radius;
};
}
using namespace std;
int main(int argc, const char * argv[]) {
GeometricalFigures::Circle circle(1);
cout << "Ln(e) = " << log(RealConstants::e) << "\n";
cout << "Area of circle with radius 1: " << circle.Area()
<< "\n";
return 0;
}
Output:
Ln(e) = 0.999999
Area of circle with radius 1: 3.14159
78
Delegation
Diagram
81
Example
//
04_01_Object_Adapter_Pattern
StudentAdapter(Student *_student){
student = _student;
}
virtual string toString(){
return string(student->getName());
}
private:
Student *student;
StudentAdapter() {student = nullptr;}
};
#include <iostream>
using namespace std;
class Student{
public:
Student(const char *_name): name(_name){}
const string &getName(){
return name;
}
private:
Student(): name(""){}
string name;
};
class Printable {
public:
virtual string toString(){
return string("");
};
};
void PrintList(Printable* list[], int nrOfValues){
for (int i = 0; i < nrOfValues; ++i){
cout << i << ". " << list[i]->toString() << "\n";
}
}
class StudentAdapter: public Printable{
public:
Output:
0.
1.
2.
3.
John
Michael
Andrew
Mark
82
Diagram
84
Example
//
04_02_Null_Object_Pattern
}
};
#include <iostream>
using namespace std;
class Student{
public:
Student(const char *_name): name(_name){}
string toString(){
return string(name);
}
private:
Student(): name(""){}
string name;
};
class PageFormatter {
public:
virtual void printHeader() {
cout << "===== List header =====\n";
}
virtual void printFooter(){
cout << "===== List footer =====\n";
}
};
class NullPageFormatter: public PageFormatter{
public:
void printHeader() {
}
void printFooter() {
Output:
List with format:
===== List header =====
0. John
1. Michael
2. Andrew
3. Mark
===== List footer =====
List without format:
0. John
1. Michael
2. Andrew
3. Mark
85
Proxy Pattern
Proxy types
Proxy types
Diagram
89
Example
//
04_03_Proxy_Pattern
}else{
player->addPoints(nrOfAddedPoints);
}
#include <iostream>
using namespace std;
}
int getNrOfPoints(){return player->getNrOfPoints();}
string getName(){return player->getName();}
bool isFemale(){return player->isFemale();}
virtual ~PlayerProxy() {delete player;}
private:
PlayerProxy() {}
Player *player;
};
enum Sex {
Male = 0,
Female = 1
};
class Player{
public:
Player(string _name, Sex _sex): name(_name), sex(_sex),
points(0){}
void addPoints(int nrOfAddedPoints) {points +=
nrOfAddedPoints;}
int getNrOfPoints() {return points;}
string getName(){return name;}
bool isFemale(){ return (sex == Female)? true : false; }
private:
Player() {}
string name;
Sex sex;
int points;
};
class PlayerProxy{
public:
PlayerProxy(string _name, Sex _sex): player(new Player(_name,
_sex)) {}
void addPoints(int nrOfAddedPoints){
if (player->isFemale()){
player->addPoints(nrOfAddedPoints * 2);
Output:
John has 10 points
Jane has 12 points
Bob has 5 points
Alice has 24 points
90
return 0;
Example
//
04_04_Overloading_Member_Access_Operator
#include <iostream>
player->addPoints(nrOfAddedPoints);
}
Player* operator->(){
return player;
}
class Player{
public:
Player(string _name, Sex _sex): name(_name), sex(_sex),
points(0){}
void addPoints(int nrOfAddedPoints) {points +=
nrOfAddedPoints;}
int getNrOfPoints() {return points;}
string getName(){return name;}
bool isFemale(){ return (sex == Female)? true : false; }
private:
Player() {}
string name;
Sex sex;
int points;
};
class PlayerProxy{
public:
PlayerProxy(string _name, Sex _sex): player(new Player(_name,
_sex)) {}
void addPoints(int nrOfAddedPoints){
if (player->isFemale()){
player->addPoints(nrOfAddedPoints * 2);
}else{
Output:
John has 10 points
Jane has 12 points
Bob has 5 points
Alice has 34 points
92
Smart pointers
Example
//
04_05_Smart_Pointers
operator Student*(){
return student;
}
#include <iostream>
using namespace std;
private:
StudentPtr() {};
Student *student;
};
class Student{
public:
Student(const char *_name): name(_name){}
const string &getName(){
return name;
}
private:
Student(): name(""){}
string name;
};
class StudentPtr{
public:
StudentPtr(Student *student_) {
student = student_;
}
~StudentPtr(){
delete student;
}
Student &operator*(){
return *student;
}
Student *operator->(){
return student;
}
PrintStudentName(john);
PrintStudentName(jane);
PrintStudentName(jill);
delete john;
return 0;
}
Output:
The name is John
The name is Jane
The name is Jill
94
Smart references
Example
//
04_06_Smart_References
#include <iostream>
using namespace std;
class StudentRef{
public:
StudentRef(const char *name) {
student = new Student(name);
}
~StudentRef(){
delete student;
}
StudentRef(const StudentRef & studentRef){
student = new Student((studentRef.student)>getName().c_str());
}
StudentRef& operator= (const StudentRef &studentRef){
delete student;
student = new Student((studentRef.student)>getName().c_str());
return *this;
}
const string &getName(){
return student->getName();
}
private:
class Student{
public:
Student(const char *_name): name(_name){}
StudentRef() {};
Student *student;
};
int main(int argc, const char * argv[]) {
StudentRef john("John");
cout << "My name is: " << john.getName() << "\n";
return 0;
}
Output:
My name is: John
96
97
Diagram
98
Example
//
04_07_Template_Method_Pattern
#include <iostream>
using namespace std;
class Downloader{
public:
void Download(){
Connect();
DownloadFile();
Disconnect();
}
private:
virtual void Connect() {};
virtual void DownloadFile() {};
virtual void Disconnect() {}
};
class HttpDownloader: public Downloader{
private:
virtual void Connect(){
cout << "Connecting to HTTP server...\n";
}
virtual void DownloadFile(){
cout << "Downloading file from HTTP server...\n";
cout << "Download finished\n";
}
virtual void Disconnect(){
cout << "Disconnecting from HTTP server...\n";
}
};
Output:
Connecting to HTTP server...
Downloading file from HTTP server...
Download finished
Disconnecting from HTTP server...
Connecting to SCP server using private key testkey123...
Downloading file from SCP server...
Download finished
Disconnecting from SCP server...
99
delete httpDownloader;
delete scpDownloader;
return 0;
Factory objects
100
Diagram
101
Example
//
04_08_Factory_Objects
};
#include <iostream>
class DeviceBuilder{
public:
Computer *getDevice(DeviceType deviceType){
switch (deviceType) {
case DeviceType::DTSmartphone:
return new Smartphone();
break;
case DeviceType::DTIPhone:
return new IPhone("white");
break;
case DeviceType::DTTablet:
return new Tablet(10.1f);
default:
return new Computer();
}
}
};
= 0, DTIPhone,
class Computer {
public:
virtual void whatAmI(){ cout << "I'm a computer\n"; }
};
class Smartphone: public Computer{
public:
virtual void whatAmI(){ cout << "I'm a smartphone\n"; }
};
class IPhone: public Smartphone {
public:
IPhone(string color_): color(color_) {}
virtual void whatAmI(){ cout << "I'm a " << color << " iPhone\n";
}
private:
IPhone(){}
string color;
};
smartphone->whatAmI(); tablet->whatAmI();computer>whatAmI();iPhone->whatAmI();
delete iPhone; delete computer; delete tablet; delete smartphone;
}
Output:
I'm
I'm
I'm
I'm
a
a
a
a
double diagonalSize;
smartphone
tablet with a 10.1 diagonal
computer
white iPhone
102
return 0;
Subscripting
104
Example
//
//
DoubleLinkedList.hpp
05_01_Overloading_Subscript_Operator
#ifndef DoubleLinkedList_hpp
#define DoubleLinkedList_hpp
class DoubleLinkedList{
public:
DoubleLinkedList();
virtual ~DoubleLinkedList();
void addFront(int value);
void addBack(int value);
void printAll();
//
//
main.cpp
05_01_Overloading_Subscript_Operator
#include <iostream>
#include "DoubleLinkedList.hpp"
using namespace std;
#endif /* DoubleLinkedList_hpp */
//DoubleLinkedList.cpp
int & DoubleLinkedList::operator[] (const int index){
int i = 0;
Node *currentNode = first;
while (currentNode != nullptr) {
if (i == index){
break;
}
currentNode = currentNode->next;
++i;
}
if (currentNode == nullptr){
Output:
All values:12 20 10 3
The third element in list is: 10
All values:12 40 10 3
libc++abi.dylib: terminating with uncaught exception of type
char const*
105
Multi-dimensional subscripting
Example
//
//
DoubleLinkedList.hpp
05_02_Multidimensional_Subscripting
#ifndef DoubleLinkedList_hpp
#define DoubleLinkedList_hpp
class DoubleLinkedList{
public:
DoubleLinkedList();
virtual ~DoubleLinkedList();
void addFront(std::string value);
void addBack(std::string value);
void printAll();
if (currentNode == nullptr){
throw "Index of bounds!";
}
return currentNode->value;
#endif /* DoubleLinkedList_hpp */
//DoubleLinkedList.cpp
string & DoubleLinkedList::operator[] (const int index){
int i = 0;
Node *currentNode = first;
while (currentNode != nullptr) {
if (i == index){
break;
}
currentNode = currentNode->next;
++i;
}
Output:
All values:12 20 10 3
The third element in list is: 10
The first letter in the second element is 2
All values:1A 40 10 3
libc++abi.dylib: terminating with uncaught exception of type
char const*
107
Associative arrays
Example
//
//
DoubleLinkedDict.hpp
05_03_Associative_Arrays
#ifndef DoubleLinkedDict_hpp
#define DoubleLinkedDict_hpp
class DoubleLinkedDict{
public:
DoubleLinkedDict();
virtual ~DoubleLinkedDict();
void addFront(const std::string & key, int value);
void addBack(const std::string & key, int value);
void printAll();
if (currentNode == nullptr){
addBack(index, 1);
return last->value;
}
return currentNode->value;
#include <iostream>
#include "DoubleLinkedDict.hpp"
using namespace std;
int main(int argc, const char * argv[]) {
DoubleLinkedDict age;
age.addBack("John", 10);
age.addFront("Jane", 20);
age.addBack("Mike", 30);
age.addFront("Luke", 15);
age.printAll();
cout << "Mike's age is " << age["Mike"] << "\n";
age["Alice"] = 21;
age.printAll();
return 0;
}
#endif /* DoubleLinkedDict_hpp */
// DoubleLinkedDict.cpp
int & DoubleLinkedDict::operator[] (const string & index){
Node *currentNode = first;
while (currentNode != nullptr) {
if (currentNode->key == index){
break;
}
currentNode = currentNode->next;
}
Output:
All values:
Luke: 15
Jane: 20
John: 10
Mike: 30
Mike's age is 30
All values:
Luke: 15
Jane: 20
John: 10
Mike: 30
Alice: 21
109
Exercise 2
Implement a national bank that decides debts and has all banks registered to it
Hide the transaction (make it nested in one of the other classes and hide its
implementation)
Improve the method by which the contracts are created (use a factory method)
Implement subscripting and an associative array in the national bank for getting the
information about any of the banks in the system
110
Day 3
Template functions
Example
//
06_01_Using_Template_Functions
#include <iostream>
using namespace std;
template <typename T>
void Sort(T array[], int length){
bool sorted = false;
while (!sorted){
sorted = true;
for (int i = 0; i < (length - 1); ++i){
if (array[i] > array[i+1]) {
T aux = array[i];
array[i] = array[i+1];
array[i+1] = aux;
sorted = false;
}
}
}
}
template <typename T>
void printList(T array[], int length){
cout << "Array: [";
for (int i = 0; i < length - 1; ++i){
cout << array[i] << ", ";
}
cout << array[length-1] << "]\n";
}
int main(int argc, const char * argv[]) {
Output:
Array:
Array:
Array:
Array:
[0, -2, 5, 2, 7]
[0.4, 7, 4, 1.6]
[-2, 0, 2, 5, 7]
[0.4, 1.6, 4, 7]
114
115
Example
//
06_02_Specialising_Template_Functions
#include <iostream>
using namespace std;
template<>
void Sort(char* array[], int length){
bool sorted = false;
while (!sorted){
sorted = true;
for (int i = 0; i < (length - 1); ++i){
if (strcmp(array[i], array[i+1]) > 0) {
char* aux = array[i];
array[i] = array[i+1];
array[i+1] = aux;
sorted = false;
}
Output:
Array:
Array:
Array:
Array:
Array:
Array:
[0, -2, 5, 2, 7]
[0.4, 7, 4, 1.6]
[test, abc, jack]
[-2, 0, 2, 5, 7]
[0.4, 1.6, 4, 7]
[abc, jack, test]
116
Two function templates with the same return type and the
same parameter list are distinct and can be distinguished
with explicit template argument list
117
Example
//
06_03_Overloading_Template_Functions
#include <iostream>
using namespace std;
template<typename T1, typename T2>
void f( T1, T2 ){
cout << "I was called: " << __PRETTY_FUNCTION__
}
template<typename T> void f( T )
{
cout << "I was called: " << __PRETTY_FUNCTION__
}
template<typename T> void f( T, T ){
cout << "I was called: " << __PRETTY_FUNCTION__
}
template<typename T> void f( T* ){
cout << "I was called: " << __PRETTY_FUNCTION__
}
template<typename T> void f( T*, T ){
cout << "I was called: " << __PRETTY_FUNCTION__
}
template<typename T> void f( T, T* ){
cout << "I was called: " << __PRETTY_FUNCTION__
}
template<typename T> void f( int, T* ){
cout << "I was called: " << __PRETTY_FUNCTION__
}
template<> void f<int>( int ){
cout << "I was called: " << __PRETTY_FUNCTION__
}
<< "\n";
<< "\n";
<< "\n";
<< "\n";
<< "\n";
<< "\n";
<< "\n";
f( i ) ... \n";
f<int>( i ) ... \n";
f( i, i ) ... \n";
f( c ) ... \n";
f( i, ff ) ... \n";
f( i, d ) ... \n";
f( c, &c ) ... \n";
f( i, &d ) ... \n";
f( &d, d ) ... \n";
f( &d ) ... \n";
f( d, &i ) ... \n";
f( &i, &i ) ... \n";
<< "\n";
Output:
Calling f( i ) ...
I was called: void f(int)
Calling f<int>( i ) ...
I was called: void f(int)
Calling f( i, i ) ...
I was called: void f(T, T) [T = int]
Calling f( c ) ...
I was called: void f(T) [T = C]
Calling f( i, ff ) ...
I was called: void f(T1, T2) [T1 = int, T2 = float]
Calling f( i, d ) ...
I was called: void f(int, double)
Calling f( c, &c ) ...
118
f( i );
f<int>( i );
f( i, i );
f( c );
f( i, ff );
f( i, d );
f( c, &c );
f( i, &d );
f( &d, d );
f( &d );
f( d, &i );
f( &i, &i );
Example
//
//
Templates.hpp
06_04_Template_Instantiation
}
template <typename T>
void printList(T array[], int length){
cout << "Array: [";
for (int i = 0; i < length - 1; ++i){
cout << array[i] << ", ";
}
cout << array[length-1] << "]\n";
}
#ifndef Templates_hpp
#define Templates_hpp
template <typename T>
void Sort(T array[], int length);
template <typename T>
void printList(T array[], int length);
template
template
template
template
#endif /* Templates_hpp */
//
//
Templates.cpp
06_04_Template_Instantiation
//
//
#include <iostream>
#include "Templates.hpp"
main.cpp
06_04_Template_Instantiation
#include <iostream>
#include "Templates.hpp"
Output:
Array:
Array:
Array:
Array:
void
void
void
void
[0, -2, 5, 2, 7]
[0.4, 7, 4, 1.6]
[-2, 0, 2, 5, 7]
[0.4, 1.6, 4, 7]
120
Template classes
122
Example
//
07_01_Template_Classes_For_Generic_Types
#include <iostream>
using namespace std;
template <typename T>
class Number{
public:
Number(T value_): value(value_) {}
operator T() {return value;}
private:
Number(){}
T value;
};
int main(int argc, const char * argv[]) {
Number<int> intNr(7);
Number<float> floatNr(4.5f);
int sum = intNr + floatNr;
cout << "intNr = " << intNr << "\n";
cout << "floatNr = " << floatNr << "\n";
cout << "sum = " << sum << "\n";
return 0;
}
Output:
intNr = 7
floatNr = 4.5
sum = 11
123
Example
//
07_02_Multiple_Template_Parameters
#include <iostream>
using namespace std;
template <typename T1, typename T2>
class Pair{
public:
T1 first;
T2 second;
Pair(T1 first_, T2 second_): first(first_),
second(second_) {}
void Print(){
cout << "(" << first << ", " << second << ")\n";
}
};
int main(int argc, const char * argv[]) {
Pair<int, float> pair1(1, 1);
Pair<string, int> pair2("test", 3);
pair1.Print();
pair2.Print();
return 0;
}
Output:
(1, 1)
(test, 3)
125
std::vector
Example
//
07_03_Vector
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, const char * argv[]) {
vector<int> v;
v.push_back(10); v.push_back(14);
cout << "Max size is: " << v.max_size() << "\n";
cout << "Capacity is: " << v.capacity() << "\n";
cout << "The elements are: ";
for (int i = 0; i < v.size(); i++) {
cout << v[i] << " ";
}
cout << "\n";
return 0;
}
Output:
Max size is: 4611686018427387903
Capacity is: 2
The elements are: 10 14
127
std::list
Example
//
07_04_List
#include <iostream>
#include <list>
using namespace std;
void printList(list<float> l){
cout << "List is: ";
for (auto it = l.begin(); it!=l.end(); it++){
cout << *it << " ";
}
cout << "\n";
}
int main(int argc, const char * argv[]) {
list<float> l;
l.push_back(10); l.push_back(14);l.push_front(24);
cout << "Max size is: " << l.max_size() << "\n";
printList(l);
l.reverse();
printList(l);
return 0;
}
Output:
Max size is: 9223372036854775807
List is: 24 10 14
List is: 14 10 24
129
std::pair
130
Example
//
07_05_Pair
#include <iostream>
#include <utility>
using namespace std;
int main(int argc, const char * argv[]) {
pair <string, int> pair1("James", 4);
pair <int, float> pair2 = make_pair(10, 4.2);
cout << "Pair 1: ( " << pair1.first << ", " <<
pair1.second << ")\n";
cout << "Pair 2: ( " << pair2.first << ", " <<
pair2.second << ")\n";
return 0;
}
Output:
Pair 1: ( James, 4)
Pair 2: ( 10, 4.2)
131
std::map
Example
//
07_06_Map
#include <iostream>
#include <map>
using namespace std;
void printMap(map<string, int> aMap){
cout << "Map is:\n";
for (auto it = aMap.begin(); it != aMap.end(); it++){
cout << it->first << ": " << it->second << "\n";
}
}
int main(int argc, const char * argv[]) {
map<string, int> age;
age.insert(make_pair("Jane", 10));
age.insert(pair<string, int>("Mike", 21));
age["July"] = 12;
cout << "Max size: " << age.max_size() << "\n";
cout << "Size: " << age.size() << "\n";
cout << "Mike's age: " << age["Mike"] << "\n";
printMap(age);
return 0;
}
Output:
Max size: 288230376151711743
Size: 3
Mike's age: 21
Map is:
Jane: 10
July: 12
Mike: 21
133
Functional abstraction
135
Example
//
13_01_Traditional_Callbacks
#include <iostream>
using namespace std;
typedef void (*finishSleeping_fn)(int);
void finishSleeping(int interval){
cout << "I slept for " << interval << " seconds.\n";
}
void wakeUp(int sleepInterval){
cout << "Good morning! I slept for " << sleepInterval << "
seconds.\n";
}
void Sleep(int interval, finishSleeping_fn onFinishSleeping){
cout << "Will sleep for " << interval << " seconds...\n";
sleep(interval);
onFinishSleeping(interval);
}
void GoToSleep(int interval, void(*onWake)(int)){
cout << "Good night! I am going to sleep for " << interval
<< " seconds...zzz\n";
sleep(interval);
onWake(interval);
}
Output:
Will sleep for 2 seconds...
I slept for 2 seconds.
Good night! I am going to sleep for 4 seconds...zzz
Good morning! I slept for 4 seconds.
136
137
Example
//
13_02_Memeber_Function_Pointers
return 0;
}
#include <iostream>
using namespace std;
#define CALL_MEMBER_FN(object,ptrToMember)
((object).*(ptrToMember))
class SleepHandler{
public:
void finishSleeping(int interval){
cout << "I slept for " << interval << " seconds.\n";
}
};
typedef void (SleepHandler::*sleepHandlerFn)(int);
void Sleep(int interval, SleepHandler &sleepHandler,
sleepHandlerFn onFinishSleeping){
cout << "Will sleep for " << interval << " seconds...\n";
sleep(interval);
CALL_MEMBER_FN(sleepHandler, onFinishSleeping)(interval);
//(sleepHandler.*onFinishSleeping)(interval); // we can
also do this
}
int main(int argc, const char * argv[]) {
SleepHandler sleepHandler;
Sleep(2, sleepHandler, &SleepHandler::finishSleeping);
Output:
Will sleep for 2 seconds...
I slept for 2 seconds.
138
Command Pattern
139
Example
//
13_03_Command_Pattern
#include <iostream>
#include <list>
private:
Square *obj;
Action action;
double param;
};
class Transformation{
public:
void AddCommand(Command *c){
commandList.push_back(c);
}
void Apply(){
auto it = commandList.begin();
while (it != commandList.end()){
(*it++)->execute();
}
}
private:
list<Command *> commandList;
};
int main(int argc, const char *
Square *s = new Square(4);
s->Draw();
Transformation t;
t.AddCommand(new Command(s,
t.AddCommand(new Command(s,
t.AddCommand(new Command(s,
t.Apply();
s->Draw();
delete s;
return 0;
}
class Command{
public:
typedef void (Square::*Action)(double);
Command(Square *obj_, Action action_, double param_){
obj = obj_;
action = action_;
param = param_;
}
void execute(){
(obj->*action)(param);
Output:
Drawing a square shape with the size length of 4 and an area of 16
Resizing by 2
Rotating by 45 degrees
Resizing by 4
Drawing a square shape with the size length of 32 and an area of 1024
140
argv[]) {
&Square::Resize, 2));
&Square::Rotate, 45));
&Square::Resize, 4));
Template techniques
Templating on precision
Example
//
16_01_Templating_On_Precision
};
#include <iostream>
Output:
am = -12768
smartAm = 20000
143
Template adapters
144
Example
//
16_02_Template_Adapters
#include <iostream>
#include <math.h>
using namespace std;
class Student{
public:
Student(const char *_name): name(_name){}
string getName(){
return name;
}
protected:
Student(): name(""){}
string name;
};
class Circle{
public:
Circle()=delete;
Circle(double radius_): radius(radius_) {}
double Area() {return radius * radius * M_PI;}
string getInfo(){
return string("Circle with radius: ") + to_string(radius) + " and
area of " + to_string(Area());
}
private:
double radius;
};
class Printable {
public:
virtual string toString() = 0;
virtual ~Printable(){};
};
void PrintList(Printable* list[], int nrOfValues){
for (int i = 0; i < nrOfValues; ++i){
cout << i << ". " << list[i]->toString() << "\n";
}
}
template <typename AdapteeType>
Output:
0.
1.
2.
3.
4.
5.
6.
John
Michael
Andrew
Mark
Circle with radius: 3.000000 and area of 28.274334
Circle with radius: 1.500000 and area of 7.068583
Circle with radius: 10.000000 and area of 314.159265
145
Example
//
16_03_Default_Template_Arguments
#include <iostream>
using namespace std;
}
~Array() {delete [] elements;}
private:
NrType *elements = new NrType[2];
int elementCount = 0;
int currentSize = 2;
ComparatorType comp = ComparatorType();
};
Output:
Array elements: [2 7 7 10 12 14 ]
Array elements: [14 12 10 7 7 2 ]
147
148
RULES:
For integral and arithmetic types, the template argument provided during instantiation
must be a converted constant expression of the template parameter's type (so certain
implicit conversion applies).
For pointers to objects, the template arguments have to designate the address of an
object with static storage duration and a linkage (either internal or external), or a
constant expression that evaluates to the appropriate null pointer or std::nullptr_t value.
For pointers to functions, the valid arguments are pointers to functions with linkage (or
constant expressions that evaluate to null pointer values).
149
Exceptions:
Example
//
16_04_Non_Type_Template_Arguments
});
cout << "]\n";
#include <iostream>
}
~Array() {delete [] elements;}
private:
NrType *elements = new NrType[InitialCapacity];
int elementCount = 0;
ComparatorType comp = ComparatorType();
};
Output:
Array elements: [2 7 7 10 12 14 ]
Current array size is: 8
Array elements: [102 100 14 12 10 8 7 7 2 ]
Current array size is: 16
151
Member templates
Template declarations (class, function and variables, since C++14) can appear
inside a member specification block of any class, struct or union that arent local
classes.
A non-template member function and a template member function with the same
name can be declared. In case of conflict, the non-template member will be
used, unless an explicit template argument is specified
152
Example
//
16_05_Member_Templates
#include <iostream>
capacity *= 2;
}
elements[elementCount++] = elem;
class Student{
public:
Student(string name_):name(name_){}
template <ostream &Output = std::cout>
void toString(){
Output << "My name is: " << name << "\n";
}
private:
string name = "";
};
Output:
My name is: John
My name is: John
Array elements: [3 1 5 2 3 5 ]
153
Trait classes
154
Example
//
16_06_Trait_Classes
};
#include <iostream>
using std::cout;
template <typename T>
struct is_pointer{
static const bool value = false;
};
template <typename T>
struct is_pointer<T*>{
static const bool value = true;
};
template <typename T>
struct is_void{
static const bool value = false;
};
template<>
struct is_void<void>{
static const bool value = true;
};
Output:
I
I
I
I
was
was
was
was
called
called
called
called
a pointer type
f(int)
a pointer type
with a type can't handle: void printSomething(T) [T = double]
155
Template specialisation
Example
//
16_07_Template_Specialisation
toStringMethod = toString_;
}
~PrintableAdapter(){delete object;}
string toString(){
return (object->*toStringMethod)();
}
#include <iostream>
#include <math.h>
using namespace std;
class Student{
public:
Student(const char *_name): name(_name){}
string getName(){
return name;
}
protected:
Student(): name(""){}
string name;
};
private:
AdapteeType *object;
string (AdapteeType::*toStringMethod)();
};
template <>
class PrintableAdapter<IntNumber>: public Printable {
public:
PrintableAdapter()=delete;
PrintableAdapter(IntNumber *obj_, string(IntNumber::*toString_)()){
object = obj_;
toStringMethod = toString_;
}
~PrintableAdapter(){delete object;}
string toString(){
return string("This is an int number: ") + (object->*toStringMethod)();
}
class Circle{
public:
Circle()=delete;
Circle(double radius_): radius(radius_) {}
double Area() {return radius * radius * M_PI;}
string getInfo(){
return string("Circle with radius: ") + to_string(radius) + " and area of " + to_string(Area());
}
private:
double radius;
};
private:
IntNumber *object;
string (IntNumber::*toStringMethod)();
};
class Printable {
public:
virtual string toString() = 0;
virtual ~Printable(){};
};
Output:
0.
1.
2.
3.
4.
5.
6.
John
Michael
Andrew
Mark
Circle with radius: 3.000000 and area of 28.274334
Circle with radius: 1.500000 and area of 7.068583
This is an int number: 13
157
159
Example
//
//
DoubleLinkedList.hpp
08_01_Need_For_Iterators
position = pos;
}
DoubleLinkedList::Iterator & DoubleLinkedList::Iterator::operator++(){
position = position->next;
return *this;
}
int DoubleLinkedList::Iterator::operator*(){
return position->value;
}
bool DoubleLinkedList::Iterator::operator==(Iterator it){
return (position == it.position);
}
bool DoubleLinkedList::Iterator::operator!=(Iterator it){
return (position != it.position);
}
// main.cpp
int SumOfList(DoubleLinkedList *list){
int sum = 0;
for (DoubleLinkedList::Iterator it = list->begin(); it != list->end();
++it){
sum+=*it;
}
return sum;
}
int main(int argc, const char * argv[]) {
DoubleLinkedList *list = new DoubleLinkedList();
list->addBack(10); list->addFront(20);
list->addBack(3); list->addFront(12);
list->printAll();
int sumOfAll = SumOfList(list);
cout << "Sum of all elements is: " << sumOfAll << "\n";
delete list;
return 0;
}
#include <iostream>
class DoubleLinkedList{
private:
class Node;
Node *first;
Node *last;
public:
DoubleLinkedList();
virtual ~DoubleLinkedList();
void addFront(int value);
void addBack(int value);
void printAll();
class Iterator {
friend class DoubleLinkedList;
public:
Iterator & operator ++();
bool operator ==(Iterator);
bool operator !=(Iterator);
int operator*();
private:
Iterator();
Iterator(DoubleLinkedList::Node *);
DoubleLinkedList::Node *position;
};
Iterator begin();
Iterator end();
};
// DoubleLinkedList.cpp
DoubleLinkedList::Iterator DoubleLinkedList::begin(){
return Iterator(first);
}
DoubleLinkedList::Iterator DoubleLinkedList::end(){
return Iterator(nullptr);
}
DoubleLinkedList::Iterator::Iterator(DoubleLinkedList::Node *pos) {
Output:
All values:12 20 10 3
Sum of all elements is: 45
160
161
Iterators - Classification
Category
Properties
copy-constructible, copy-assignable and destructible
All categories
Can be incremented
Suports equality/inequality comparisons
Input
Can be dereferenced as an rvalue
Forward Output
Bidirectional
default-constructible
Random
Access
162
Valid
expressions
X b(a);
b = a;
++a;
a++;
a == b
a != b
*a
a->m
*a = t;
*a++ = t;
X a;
X();
{b = a; *a++;
*b;}
--a; a--;
*a-a + n; n + b;
a - n; a - b;
a < b; a > b;
a <= b; a >= b;
a += n;
a -= n;
a[n];
Example
//
08_02_STL_Iterators
return 0;
}
#include <iostream>
#include <list>
using namespace std;
void printList(list<float> l){
cout << "List is: ";
for (list<float>::iterator it = l.begin(); it!=l.end(); +
+it){
cout << *it << " ";
}
cout << "\n";
}
void printListReverse(list<float> l){
cout << "List in reverse: ";
for (list<float>::reverse_iterator it = l.rbegin(); it !=
l.rend(); ++it){
cout << *it << " ";
}
cout << "\n";
}
int main(int argc, const char * argv[]) {
list<float> l;
l.push_back(10); l.push_back(14);l.push_front(24);
l.push_back(3);l.push_back(7); l.push_back(9);
printList(l);
printListReverse(l);
Output:
List is: 24 10 14 3 7 9
List in reverse: 9 7 3 14 10 24
163
Function Objects
Example
//
08_03_Function_Objects
return 0;
}
#include <iostream>
#include <list>
using namespace std;
void printList(list<float> l){
cout << "List is: ";
for (list<float>::iterator it = l.begin(); it!=l.end(); +
+it){
cout << *it << " ";
}
cout << "\n";
}
template <typename NumberType, int N>
class GreaterThan{
public:
bool operator()(NumberType nr){
return (nr > N);
}
};
int main(int argc, const char * argv[]) {
list<float> l;
l.push_back(10); l.push_back(14);l.push_front(24);
l.push_back(3);l.push_back(7); l.push_back(9);
printList(l);
l.remove_if(GreaterThan<float, 10>());
printList(l);
Output:
List is: 24 10 14 3 7 9
List is: 10 3 7 9
165
Exercise 3
Imagine a file system that contains folders and files (files can be: executables, images,
songs, movies)
Provide a method to sort all the files and folders in a folder alphabetically. Then provide
another method to sort them by size.
We should have a method .Open() that will output different text, depending on the file
type: Showing the movie <movie_name>, Displaying the image <image_name>,
Running the program <program_name> and Playing the song <song_name>). If
called on an folder, it will list all the files and folders contained.
Add a method to delete all the files that meet a given condition
Day 4
Exception handling
Exception handling
An exception can be thrown using the throw keyword from inside a try
block. Exception handlers are declared immediately after the try block,
using the keyword catch
The handler is called for an exception if and only if the type of its parameter
matches the type of the parameter used for the throw.
Multiple handlers can be chained, with different parameter types. Only the
one whose parameter type matches will be called
Exception handling
Use throw only to signal an error (which means specifically that the function
couldnt do what it said it could)
Use catch only to specify error handling actions when you know you can
handle an error
Example
//
09_01_Exception_Handling
#include <iostream>
using namespace std;
double Divide(double a, double b){
if (b == 0){
throw string("Cannot divide by 0");
}
return a/b;
}
int main(int argc, const char * argv[]) {
try {
cout << "1/2 = " << Divide(1,2) << "\n";
cout << "1/0 = " << Divide(1,0) << "\n";
} catch (std::string ex) {
cout << "EXEPTION: " << ex << "\n";
} catch (int ex){
cout << "EXEPTION Nr: " << ex << "\n";
} catch (...) {
cout << "Unknown exception!\n";
}
return 0;
}
Output:
1/2 = 0.5
1/0 = EXCEPTION: Cannot divide by 0
171
RAII Idiom
Example
//
09_02_RAII
}
private:
bool connectionInProgress;
};
#include <iostream>
using namespace std;
class ServerConnection {
public:
ServerConnection(): connectionInProgress(false){}
void Connect() {
cout << "Opening server connection...\n";
connectionInProgress = true;
};
void Disconnect() {
cout << "Closing server connection...\n";
connectionInProgress = false;
}
void Send(string message){
if (connectionInProgress){
cout << "Sending message " << message << "...\n";
}
else {
cout << "Must be connected to send message. Call
Connect() first!\n";
}
}
~ServerConnection(){
if (connectionInProgress){
cout << "~ServerConnection(): Must disconnect!\n";
Disconnect();
}
Output:
Opening server connection...
Sending message test...
Closing server connection...
Opening server connection...
~ServerConnection(): Must disconnect!
Closing server connection...
EXCEPTION:MESSAGE EXEPTION: String must contain somethig!
174
Exceptions in constructors
175
Example
//
09_03_Exception_In_Constructors
#include <iostream>
using namespace std;
class Person {
public:
Person(string name_):name(name_){
cout << "Creating A person named " << name << "\n";
}
virtual ~Person(){
cout << "Destroying THE person named " << name << "\n";
}
protected:
Person(){}
string name;
};
class SpecialisationList{
public:
SpecialisationList(){
cout << "Creating A specialisation list\n";
}
virtual ~SpecialisationList(){
cout << "Distroying THE specialisation list\n";
}
};
Output:
Creating A person named John
Creating A specialisation list
Creating a student named John in year 2
Creating A person named Jack
Creating A specialisation list
Creating a student named Jack in year 0
The student must be in year 1 to 4! Throwing exception!
Distroying THE specialisation list
Destroying THE person named Jack
Destroying
Distroying
Destroying
EXCEPTION:
176
the
THE
THE
The
Exceptions in destructors
Example
//
09_04_Exception_In_Destructors
(lldb) bt
* thread #1: tid = 0x609015, 0x00007fff8e16f0ae
libsystem_kernel.dylib`__pthread_kill + 10, queue =
'com.apple.main-thread', stop reason = signal SIGABRT
frame #0: 0x00007fff8e16f0ae
libsystem_kernel.dylib`__pthread_kill + 10
frame #1: 0x000000010007d43d
libsystem_pthread.dylib`pthread_kill + 90
frame #2: 0x00007fffa026037b libsystem_c.dylib`abort + 129
frame #3: 0x00007fff90b12f81 libc++abi.dylib`abort_message
+ 257
frame #4: 0x00007fff90b38a47 libc+
+abi.dylib`default_terminate_handler() + 267
frame #5: 0x00007fff8f6e5173
libobjc.A.dylib`_objc_terminate() + 124
frame #6: 0x00007fff90b3619e libc+
+abi.dylib`std::__terminate(void (*)()) + 8
frame #7: 0x00007fff90b36213 libc+
+abi.dylib`std::terminate() + 51
* frame #8: 0x0000000100000ec6
09_04_Exception_In_Destructors`__clang_call_terminate + 22
#include <iostream>
using namespace std;
class TheWorstClassEver{
public:
~TheWorstClassEver(){
throw string("Exception in the destructor of class
'~TheWorstClassEver'");
}
};
int main(int argc, const char * argv[]) {
try {
TheWorstClassEver worstClassEver;
throw string("OOPS!");
} catch (string ex) {
cout << "EXCEPTION: " << ex << "\n";
}
return 0;
}
Output:
libc++abi.dylib: terminating with uncaught exception of type
std::__1::basic_string<char, std::__1::char_traits<char>,
std::__1::allocator<char> >
178
180
181
deque
list
map
clear()
nothrow (copy)
nothrow (copy)
nothrow
nothrow
erase()
nothrow (copy)
nothrow (copy)
nothrow
nothrow
1-element insert()
strong (copy)
strong (copy)
strong
strong
N-element insert()
strong (copy)
strong (copy)
strong
basic
merge()
nothrow (comp)
push_back()
strong
strong
strong
strong
strong
push_front()
pop_back()
nothrow
nothrow
nothrow
pop_front()
nothrow
nothrow
remove()
nothrow (comp)
remove_if()
nothrow (pred)
reverse()
nothrow
splice()
nothrow
swap()
nothrow
nothrow
nothrow
unique()
nothrow (comp)
182
Memory management
Example
//
10_01_Object_Lifecycle
year = 1;
}
else if (year > 4){
year = 4;
}
else {
year = year_;
}
cout << "Creating A student named " << name << " in year
" << year << "\n";
}
virtual ~Student(){
cout << "Destroying THE student named " << name << " in
year " << year << "\n";
}
private:
Student() {}
SpecialisationList specialisationList;
int year;
};
#include <iostream>
using namespace std;
class Person {
public:
Person(string name_):name(name_){
cout << "Creating A person named " << name << "\n";
}
virtual ~Person(){
cout << "Destroying THE person named " << name << "\n";
}
protected:
Person(){}
string name;
};
class SpecialisationList{
public:
SpecialisationList(){
cout << "Creating A specialisation list\n";
}
virtual ~SpecialisationList(){
cout << "Distroying THE specialisation list\n";
}
};
Output:
Creating A
Creating A
Creating A
Creating A
Creating A
Creating A
Creating A
Creating A
Creating A
Destroying
Distroying
Destroying
Creating A
Creating A
Creating A
Destroying
Distroying
Destroying
Destroying
Distroying
Destroying
Destroying
Distroying
Destroying
185
Allocation failure
2.
3.
186
Example
//
10_02_Allocation_Failure
#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
int *elements = new(std::nothrow) int[231424324324234];
if (elements == nullptr){
cout << "ALLOCATION ERROR elements: Cannot alloc so much\n";
}
int *elements1 = nullptr;
try {
elements1 = new int[231424324324234];
} catch (std::bad_alloc ex) {
cout << "Cought bad_alloc exception: " << ex.what() << "\n";
}
if (elements1 == nullptr){
cout << "ALLOCATION ERROR elements1: Cannot alloc so much\n";
}
int *elements2 = new int[231424324324234];
if (elements2 == nullptr){
cout << "ALLOCATION ERROR elements2: Cannot alloc so much\n";
}
return 0;
}
Output:
10_02_Allocation_Failure(9798,0x100081000) malloc: ***
mach_vm_map(size=925697297297408) failed (error code=3)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
ALLOCATION ERROR elements: Cannot alloc so much
10_02_Allocation_Failure(9798,0x100081000) malloc: ***
mach_vm_map(size=925697297297408) failed (error code=3)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
187
Example
//
10_03_Customising_Memory_Allocation
#include <iostream>
#include <vector>
#include <chrono>
using namespace std;
class MyAllocator{
public:
MyAllocator():currentBufferPos(0){
buffer = calloc(10000000, sizeof(int));
}
~MyAllocator(){
free(buffer);
}
typedef int value_type;
int* allocate(size_t count){
int *retPtr = (int *)buffer + currentBufferPos;
currentBufferPos += count;
return retPtr;
}
void deallocate(int *mem, size_t size){
currentBufferPos-= size * sizeof(int);
}
private:
void *buffer;
int currentBufferPos;
};
int main(int argc, const char * argv[]) {
Output:
Finished adding elements in 420
Finished adding elements in 306
189
Reference counting
191
Example
//
11_01_Reference_Counting
}
operator Student*(){
return student;
}
#include <iostream>
using namespace std;
class StudentPtr;
class Student{
public:
Student(const char *_name): name(_name), count(0){}
const string &getName(){
return name;
}
int getCount(){
return count;
}
private:
friend class StudentPtr;
Student(): name(""), count(0){}
string name;
int count;
};
class StudentPtr{
public:
StudentPtr(Student *student_) {
student = student_;
}
~StudentPtr(){
if (--student->count == 0) delete student;
}
Student &operator*(){
return *student;
}
Student *operator->(){
return student;
Output:
The name is Jane and I am referenced 2 times
The name is Jill and I am referenced 0 times
192
Example
//
11_02_Reference_Counting_Copy_Optimisation
#include <iostream>
using namespace std;
class Student{
friend void PrintStudentData(Student *student);
public:
Student(const char *name_, int year_): data(new StudentData(name_,
year_)){}
~Student(){
if (--data->count == 0) delete data;
}
Student(const Student &student_):data(student_.data){
++data->count;
}
Student &operator=(const Student &student_){
StudentData *oldData = data;
data = student_.data;
++data->count;
if (--oldData->count == 0) delete oldData;
return *this;
}
const string &getName() const {
return data->name;
}
return 0;
Output:
student
My name
Student
student
My name
student
My name
Student
student
data:
is Jane, my year is 2 and I am referenced 3 times
2's name: Jane
2 data:
is Jane, my year is 2 and I am referenced 3 times
data:
is Jane, my year is 2 and I am referenced 2 times
2's name: Jill
2 data:
194
Where it fails
Example
//
11_03_Smart_Pointers_GC
}
return *this;
#include <iostream>
}
Type &operator*(){
return *data->ptr;
}
Type *operator->(){
return data->ptr;
}
operator Type*(){
return data->ptr;
}
private:
friend void PrintStudentPtr(SmartPtr<Type> & student);
SmartPtr();
class PtrData{
public:
Type *ptr;
int count;
};
PtrData *data;
};
Output:
The name is Jane and I am referenced 3 times
The name is Jill and I am referenced 1 times
Destroying object
Destroying object
197
Inheritance techniques
Subtyping vs Subclassing
Example
//
12_01_Subclassing_Vs_Subtyping
#include <iostream>
cout << "I am: " << justAnAnimal->what() << "\n";
cout << "I am: " << duck->what() << "\n";
duck->Fly();
duck->Talk();
return 0;
Output:
I am: Animal
I am: Bird
I am flying like a bird!
Quack quack!
200
Example
//
12_02_Abstract_And_Concrete_Bases
pen->Write();
return 0;
#include <iostream>
Output:
Text written in Red
202
Example
//
12_03_Inheritance_Scoping_Issues
delete magicNr;
return 0;
#include <iostream>
Output:
Global: The value is 2
204
Multiple inheritance
205
Example
//
12_04_Multiple_Inheritance
private:
string manufacturer;
Phone() : manufacturer("") {};
};
#include <iostream>
using namespace std;
class ConnectedDevice {
public:
ConnectedDevice() : macAddress("") {}
string const &getMacAddress(){
return macAddress;
}
void setMacAddress(const string & macAddr){
macAddress = macAddr;
}
private:
string macAddress;
};
Output:
?
206
207
Example
//
12_05_Virtual_Base_Class
private:
string manufacturer;
Phone() : manufacturer("") {};
};
#include <iostream>
using namespace std;
class ConnectedDevice {
public:
ConnectedDevice() : macAddress("") {}
string const &getMacAddress(){
return macAddress;
}
void setMacAddress(const string & macAddr){
macAddress = macAddr;
}
private:
string macAddress;
};
iPhone.setMacAddress("01:02:03:04:05:06");
galaxyPhone.setMacAddress("00:00:00:00:00:00");
Output:
I am made by Samsung and I run Android. My MAC address is:
00:00:00:00:00:00
I am made by Apple and I run iOS. My MAC address is:
01:02:03:04:05:06
208
galaxyPhone.printDetails();
iPhone.printDetails();
return 0;
Interface classes
Example
//
12_06_Interface_Classes
int main(int argc, const char * argv[]) {
Shape *s = new Square(4);
s->Draw();
s->Resize(2); s->Draw();
s->Resize(0.1); s->Draw();
delete s;
return 0;
}
#include <iostream>
using namespace std;
class Shape{
public:
virtual double Area() = 0;
virtual void Rotate(double) = 0;
virtual void Resize(double) = 0;
virtual void Draw() = 0;
virtual ~Shape() {}
};
class Square: public Shape{
public:
Square(): sideLength(0){}
Square(double sideLength_): sideLength(sideLength_) {}
virtual double Area() {return sideLength * sideLength;}
virtual void Rotate(double) { /* My square does not
support rotate */}
virtual void Resize(double factor) { sideLength *=
factor;}
virtual void Draw(){
cout << "Drawing a square shape with the size length of "
<< sideLength << " and an area of " << Area() << "\n";
}
virtual ~Square() {}
private: double sideLength;
};
Output:
Drawing a square shape with the size length of 4 and an area of 16
Drawing a square shape with the size length of 8 and an area of 64
Drawing a square shape with the size length of 0.8 and an area of 0.64
210
Mix-in classes
Example
//
12_07_Mixin_Classes
#include <iostream>
using namespace std;
class Computer {
public:
Computer (const char *os) : os(os){};
string const & getOS(){
return os;
}
protected:
std::string os;
Computer() : os("") {};
};
Output:
I am made by Samsung and I run Android
I am made by Apple and I run iOS
212
213
Example
//
12_08_RTTI
#include <iostream>
#include <math.h>
using namespace std;
class Shape{
public:
virtual double Area() = 0;
virtual void Rotate(double) = 0;
virtual void Resize(double) = 0;
virtual void Draw() = 0;
virtual ~Shape() {}
};
Output:
I have to
Drawing a
I have to
Drawing a
214
Diagram
216
Example
//
12_09_Class_Adapter_Pattern
#include <iostream>
using namespace std;
class Student{
public:
Student(const char *_name): name(_name){}
const string &getName(){
return name;
}
protected:
Student(): name(""){}
string name;
};
class Printable {
public:
virtual string toString(){
return string("");
};
};
void PrintList(Printable* list[], int nrOfValues){
for (int i = 0; i < nrOfValues; ++i){
cout << i << ". " << list[i]->toString() << "\n";
}
}
class StudentAdapter: public Printable, public Student{
public:
Output:
0.
1.
2.
3.
John
Michael
Andrew
Mark
217
Exercise 4
Element is a class
Create a Matrix that uses an the custom allocator and another one that doesnt.
Make sure the buffer in the matrix is not copied unless its modified
Adapt the Element, the Row and the Matrix to the same printable interface
218
Day 5
C++11 language
enhancements
Example
//
14_01_Auto_Decltype
#include <iostream>
#include <vector>
using namespace std;
auto Sum(vector<int> & numbers) -> int{
int sum = 0;
auto it = numbers.begin();
while(it != numbers.end()){
sum += (*it++);
}
return sum;
}
cout << "Max element in vector is: " << max << "\n";
delete intNumbers;
return 0;
}
Output:
The sum of all elements is: 133
Max element in vector is: 45
222
!=
223
Example
//
14_02_Uniform_Initialization
#include <iostream>
#include <vector>
#include <map>
using namespace std;
template <typename T>
class Numbers{
public:
Numbers(initializer_list<T> initList): numbers(initList)
{}
auto getCount() -> int{
return count;
}
private:
int count = 0;
vector<T> numbers;
};
Output:
The sum of all elements is: 133
224
225
Example
//
14_03_Delete_And_Default
};
int main(int argc, const char * argv[]) {
//Student s; // ERROR: Call to deleted constructor of
'Student'
Student jane("Jane");
Student jenny(jane);
Student jena = jane;
//jena.Heigth(2); // ERROR: Call to deleted member
function 'Heigth'
cout << "Jena's name is: " << jena.Name() << "\n";
return 0;
}
#include <iostream>
using namespace std;
class Person{
public:
Person()=delete;
Person(const string &name_): name(name_){}
Person(const Person &) = default;
Person &operator=(const Person&) = delete;
void Heigth(int h) {heigth = h;}
int Heigth() {return heigth;}
const string &Name(){
return name;
}
private:
string name="";
int heigth = 0;
};
class Student: public Person{
public:
Student()=delete;
Student(const string &name_): Person(name_){}
Student(const Student &) = default;
Student& operator=(const Student&)=default;
void Heigth(int h)=delete;
int Heigth()=delete;
Output:
Jena's name is: Jane
226
nullptr
227
Example
//
14_04_nullptr
#include <iostream>
using namespace std;
void f(int x){
cout << "f(int x) was called\n";
}
void f(char *){
cout << "f(char *) was called\n";
}
int main(int argc, const char * argv[]) {
//f(NULL); // ERROR: Call to 'f' is ambiguous
f(nullptr);
f(0);
return 0;
}
Output:
f(char *) was called
f(int x) was called
228
Delegating constructors
229
Example
//
14_05_Delegating_Constructors
#include <iostream>
#include <string>
using namespace std;
class Student{
public:
Student()=delete;
Student(string name_, int year_): name(name_), year(year_)
{}
Student(string name_): Student(name_, 1){}
Student(int year_):Student("", year_){};
string &&toString(){
return string("Name: ") + name + "; year: " +
to_string(year);
}
private:
string name = "";
int year = 1;
};
int main(int argc, const char * argv[]) {
Student jane("Jane", 2);
Student july("July");
cout << jane.toString() << "\n";
cout << july.toString() << "\n";
return 0;
}
Output:
Name: Jane; year: 2
Name: July; year: 1
230
Lambdas
Example
//
14_06_Lambdas
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, const char * argv[]) {
vector<int> numbers = {2, 12, -3, 4, 4, 2, -5};
int max = numbers[0];
for_each(numbers.begin(), numbers.end(), [&max](int nr){
if (nr > max){
max = nr;
}
});
auto printOutput = [max](){
cout << "The max is " << max << "\n";
};
printOutput();
[](){cout << "Another message\n";}();
int x = 2;
auto y = [&r = x, x = x + 1]()->int { // C++14
r += 2;
return x + 2;
}();
[](int a, int b){
cout << "(" << a << ", " << b << ")\n";
}(x, y);
return 0;
}
Output:
The max is 12
Another message
(4, 5)
232
rvalue references
Example
//
14_07_RValue_References
int &&x = 2 + 3;
x+=2;
#include <iostream>
cout << "X = " << x << "\n";
using namespace std;
void f(int& x)
{
cout << "lvalue reference overload f(" << x << ")\n";
}
void f(const int& x)
{
cout << "lvalue reference to const overload f(" << x << ")
\n";
}
void f(int&& x)
{
cout << "rvalue reference overload f(" << x << ")\n";
}
int main(int argc, const char * argv[]) {
int i = 1;
const int ci = 2;
f(i); // calls f(int&)
f(ci); // calls f(const int&)
f(3); // calls f(int&&)
// would call f(const int&) if f(int&&) overload wasn't
provided
return 0;
Output:
lvalue reference overload f(1)
lvalue reference to const overload f(2)
rvalue reference overload f(3)
X = 7
234
Move constructor
235
Example
//
14_08_Move_Constructor
free(p.name);
}
#include <iostream>
Person & operator=(Person &&p){
cout << "Person & operator=(Person &&p) called!\n";
name = strdup(p.name);
free(p.name);
return *this;
}
private:
char *name;
};
Person f(Person p){
return p;
}
int main(int argc, const char * argv[]) {
Person john("John");
Person johnny(john);
johnny = john;
Person jane(f(Person("Jane")));
jane = f(Person("Jill"));
return 0;
}
Output:
PersonPerson(const char *name_) constructor called!
Person(const Person &p) constructor called!
Person & operator=(const Person &p) called!
PersonPerson(const char *name_) constructor called!
Person(Person&& p) constructor called!
PersonPerson(const char *name_) constructor called!
Person(Person&& p) constructor called!
Person & operator=(Person &&p) called!
236
C++11 still lacks a garbage collector, a very useful XML API (or
a JSON API), sockets, GUI, reflection
237
Example
//
14_09_Additions_To_STL
});
bool noNrPositive = none_of(numbers.begin(),
numbers.end(), [](int nr)->bool{
return (nr >= 0);
});
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
class Person{
public:
Person(string name_):name(name_) {}
const string & Name(){
return name;
}
private:
string name = "";
};
return 0;
}
Output:
Name: John
Name: Jack
Are any numbers positive? YES
Are all numbers positive? NO
Are no numbers positive? NO
238
When used in a class definition, final specifies that this class may
not appear in the base-specifier-list of another class definition (in
other words, cannot be derived from)
Example
//
14_10_Keyword_final
#include <iostream>
#include <math.h>
using namespace std;
class Point final{
public:
int x, y;
void print(){
std::cout << "(" << x << "," << y << ")\n";
}
};
class Circle{
public:
Circle()=delete;
Circle(double radius_): radius(radius_) {}
virtual double Area() final {return radius * radius *
M_PI;}
string getInfo(){
return string("Circle with radius: ") + to_string(radius)
+ " and area of " + to_string(Area());
}
private:
double radius;
int final = 2;
};
Output:
240
Multithreading
techniques
A thread must use a lock, to let other threads know that a resource is
in use, and must release it after finishing the operation
Example
//
15_01_Threads
outputLock.unlock();
}
#include <iostream>
#include <thread>
#include <future>
promiseToPrintSomething.join();
return 0;
Output:
TThhiiss iiss aa nnuummbbeerr:: 31
2
Joined t2
Joined t1
This is a number: 3
Waiting to print something in the future...
This is a number: 12
Joined t3
Joined t4
The number in the future is: 12
244
Producer Consumer
Only one entity (producer or consumer) can read or write in the shared
buffer at any given time (the buffer is EREW)
It is used when constant data is fed from one or multiple sources and
must be processed (like HTTP servers, file servers, database readers
etc)
245
Example
Readers Writers
Example
248
Example
Create 5 philosophers
250
There are three smokers around a table, each of whom has an infinite
supply of one of the three ingredients one smoker has an infinite
supply of tobacco, another has paper, and the third has matches.
251
Example
The barber has one barber chair and a waiting room with a number
of chairs in it. When the barber finishes cutting a customer's hair, he
dismisses the customer and then goes to the waiting room to see if
there are other customers waiting. If there are, he brings one of them
back to the chair and cuts his hair. If there are no other customers
waiting, he returns to his chair and sleeps in it.
Example
Keep track of how long the barber sleeps and cuts hair.
See what happens with the barber if the main thread can
sleep no more than 5 seconds, or at least 10 seconds etc.
What if each haircut lasts for a fixed amount?
254
Bibliography
Bibliography
http://en.cppreference.com/w/
http://www.cplusplus.com/
http://www.stroustrup.com/except.pdf
http://www.stroustrup.com/3rd_safe.pdf
http://www.cs.princeton.edu/courses/archive/fall98/cs441/
mainus/node12.html
http://www.parashift.com/c++-faq/
https://sourcemaking.com/design_patterns
https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms
https://www.wikipedia.org/
http://www.stroustrup.com/bs_faq.html
256
Books
Design Patterns: Elements of Reusable ObjectOriented Software, Erich Gamma, Richard Helm,
Ralph Johnson and John Glissades (The Gang of
Four)