what is c++ programming basics to advance ?

© 2013 ANTAL Margit

C++ Object-Oriented Programming

CPP – 101

© 2013 ANTAL Margit

C++ - Object-Oriented Programming

Course content

– Introduction to C++

– Object-oriented programming

– Generic programming

– Object-oriented design

© 2013 ANTAL Margit

C++ - Object-Oriented Programming

References

– M. Gregoire, N. A. Solter, S. J. Kleper, Professional C++, 2nd

edition, John Wiley & Sons, 2011.

– S. Lippman, J. Lajoie, B. E. Moo, C++ Primer, 5th edition,

Addison Wesley, , 2013.

– S. Prata, C++ Primer Plus, 6th edition, Addison Wesley,

2012.

© 2013 ANTAL Margit

Module 1

Introduction to C++

© 2013 ANTAL Margit

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

● Error handling with exceptions

● References

● The const modifier

© 2013 ANTAL Margit

Introduction to C++

History and evolution

– Creator: Bjarne Stroustrup 1983

– Standards:

● The first C++ standard

– 1998 (C++98)

– 2003 (C++03) – technical corrigendum – minor bug fixes

– 2007(TR1) – library extensions

● The second C++ standard

– 2011 (C++11) – significant improvements in language and library

© 2013 ANTAL Margit

Introduction to C++

Philosophy

– Statically typed

– General purpose

– Efficient

– Supports multiple programming styles:

● Procedural programming

● Object-oriented programming

● Generic programming

© 2013 ANTAL Margit

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, …

© 2013 ANTAL Margit

Introduction to C++

Portability

– Recompilation without making changes in the

source code means portability.

– Hardware specific programs are usually not

portable.

© 2013 ANTAL Margit

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

© 2013 ANTAL Margit

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++ 2011: g++ hello.cpp -std=c++0x

© 2013 ANTAL Margit

Introduction to C++

The first C++ program

//hello.cpp

#include <iostream>

using namespace std;

int main(){

cout<<”Hello”<<endl;

return 0;

}

One-line comment

The main function

I/O streams

#include <iostream>

int main(){

std::cout<<”Hello”<<std::endl;

return 0;

}

Preprocessor directive

© 2013 ANTAL Margit

Introduction to C++

Building a C++ program: 3 steps

– preprocessor (line starting with #)

– compiler

– linker

© 2013 ANTAL Margit

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

© 2013 ANTAL Margit

Introduction to C++

Header files

– C++ header

● #include <iostream>

– C header

● #include <cstdio>

– User defined header

● #include "myheader.h"

© 2013 ANTAL Margit

Introduction to C++

Avoid multiple includes

//myheader.h

#ifndef MYHEADER_H

#define MYHEADER_H

// the contents

#endif

© 2013 ANTAL Margit

Introduction to C++

The main() function

– int main(){ … }

or

– int main( int argc, char* argv[] ){ … }

The number

of arguments Result status The arguments

© 2013 ANTAL Margit

Introduction to C++

I/O Streams

– cout: standard output

cout<<”Hello, world!”<<endl;

– cin: standard input

int i; double d;

cin >> i >> d;

End of line

© 2013 ANTAL Margit

Introduction to C++

Namespaces

– avoid naming conflicts

//my1.h

namespace myspace1{

void foo();

}

//my2.h

namespace myspace2{

void foo();

}

//my1.cpp

#include "my1.h"

namespace myspace1{

void foo(){

cout<<"myspace1::foo\n";

}

}

//my2.cpp

#include "my2.h"

namespace myspace2{

void foo(){

cout<<"myspace2::foo\n";

}

}

myspace1::foo() myspace2::foo()

© 2013 ANTAL Margit

Introduction to C++

Variables

– can be declared almost anywhere in your code

double d; //uninitialized

int i = 10; //initialized

© 2013 ANTAL Margit

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

© 2013 ANTAL Margit

Introduction to C++

Variable types

#–include <iostream>

using namespace std;

int main(int argc, char** argv) {

cout<<"short : "<<sizeof( short)<<" bytes"<<endl;

cout<<"int : "<<sizeof( int ) <<" bytes"<<endl;

cout<<"long : "<<sizeof( long) <<" bytes"<<endl;

cout<<"long long: "<<sizeof( long long)<<" bytes"<<endl;

return 0;

}

© 2013 ANTAL Margit

Introduction to C++

C++0x/C++11 Support in GCC

C++0x/C++11 Support in GCC

© 2013 ANTAL Margit

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};

enum Vegetable{ tomato, cucumber, onion};

void foo(){

if( tomato == apple){

cout<<"Hurra"<<endl;

}

}

© 2013 ANTAL Margit

Introduction to C++

C++ enumerations (type-safe)

enum class Mark {

Undefined, Low, Medium, High

};

Mark myMark( int value ){

switch( value ){

case 1: case2: return Mark::Low;

case 3: case4: return Mark::Medium;

case 5: return Mark::High;

default:

return Mark::Undefined;

}

}

© 2013 ANTAL Margit

Introduction to C++

Range-based for loop

int elements[]={1,2,3,4,5};

for( auto& e: elements){

cout<<e<<endl;

}

© 2013 ANTAL Margit

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;

}

}

© 2013 ANTAL Margit

rtarray

Stack Heap

Introduction to C++

Pointers and dynamic memory

– compile time array

int ctarray[ 3 ]; //allocated on stack

– run time array

int * rtarray = new int[ 3 ]; //allocated on heap

© 2013 ANTAL Margit

Introduction to C++

Dynamic memory management

– allocation

int * x = new int;

int * t = new int [ 3 ];

– deletion

delete x;

delete [] t;

© 2013 ANTAL Margit

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";

string name = firstName+ " "+ lastName; cout<<name<<endl;

© 2013 ANTAL Margit

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;

int &ri = i; //OK ri refers to (is another name for) i

int &ri1; //ERROR: a reference must be initialized

© 2013 ANTAL Margit

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

© 2013 ANTAL Margit

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)

{

value++;

}

usage:

int x = 10;

inc( x );

bool isShorter(const string &s1,

const string &s2)

{

return s1.size() < s2.size();

}u

sage:

string str1 ="apple";

string str2 ="nut";

cout<<str1<<"<"<<str2<<": " <<

isShorter(str1, str2);

© 2013 ANTAL Margit

Introduction to C++

Exceptions

– Exception = unexpected situation

– Exception handling = a mechanism for dealing with problems

● throwing an exception – detecting an unexpected situation

● catching an exception – taking appropriate action

© 2013 ANTAL Margit

Introduction to C++

Exceptions

#include <iostream>

#include <stdexcept>

using namespace std;

double divide( double m, double n){

if( n == 0 ){

throw std::exception();

}else{

return m/n;

}

}

int main() {

try{

cout<<divide(1,0)<<endl;

}catch( const exception& e){

cout<<"Exception was caught!"<<endl;

}

}

© 2013 ANTAL Margit

Introduction to C++

The const modifier

– Defining constants

– Protecting a parameter

const int N =10;

int t[ N ];

void sayHello( const string& who){

cout<<"Hello, "+who<<endl;

who = "new name";

}

Compiler error

© 2013 ANTAL Margit

Introduction to C++

Using the standard library

const int N =10;

int t[ N ];

#include <string>

#include <vector>

#include <iostream>

using namespace std;

int main() {

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 iterator = fruits.cbegin();

iterator != fruits.cend(); ++iterator) {

cout << *iterator << endl;

}

//Print the elements again using C++11 range-based for loop

for (auto& str : fruits)

cout << str << endl;

return 0;

}

© 2013 ANTAL Margit

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());

© 2013 ANTAL Margit

Module 2

Object-Oriented Programming

Classes and Objects

© 2013 ANTAL Margit

Object-Oriented Programming (OOP)

Content

– Classes and Objects

– Advanced Class Features

– Operator overloading

– Object Relationships

– Abstraction

© 2013 ANTAL Margit

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

© 2013 ANTAL Margit

OOP: Classes and objects

Class = Type ( Data + Operations)

– Members of the class

– Data:

● data members (properties)

– Operations:

● methods (behaviors)

– Each member is associated with an access level:

● private -

● public +

● protected #

© 2013 ANTAL Margit

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

© 2013 ANTAL Margit

OOP: Classes and objects

Encapsulation

– an object encapsulates data and functionality.

Data

Functionality

class TYPES

Employee

- mId: int

- mFirstName: string

- mLastName: string

- mSalary: int

- bHired: bool

+ Employee()

+ display() : void {query}

+ hire() : void

+ fire() : void

+ setFirstName(string) : void

+ setLastName(string) : void

+ setId(int) : void

+ setSalary(int) : void

+ getFirstName() : string {query}

+ getLastName() : string {query}

+ getSalary() : int {query}

+ getIsHired() : bool {query}

+ getId() : int {query}

© 2013 ANTAL Margit

OOP: Classes and objects

Class creation

– class declaration - interface

● Employee.h

– class definition – implementation

● Employee.cpp

© 2013 ANTAL Margit

OOP: Classes and objects

class Employee{

public:

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;

string mFirstName;

string mLastName;

int mSalary;

bool bHired;

};

Methods' declaration

Data members

Employee.h

© 2013 ANTAL Margit

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(""),

mSalary(0),

bHired(false){

}

Employee :: Employee() {

mId = -1;

mFirstName="";

mLastName="";

mSalary =0;

bHired = false;

}

Members are initialized

through the

constructor initializer list

Members are assigned

Only constructors can use

this initializer-list syntax!!!

© 2013 ANTAL Margit

OOP: Classes and objects

Constructors

– responsibility: data members initialization of a class object

– invoked automatically for ach 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

© 2013 ANTAL Margit

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;

}

string Employee::getFirstName() const{

return mFirstName;

}

© 2013 ANTAL Margit

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;

}

© 2013 ANTAL Margit

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;

}

© 2013 ANTAL Margit

OOP: Classes and objects

#ifndef EMPLOYEE_H

#define EMPLOYEE_H

#include <string>

using namespace std;

class Employee{

public:

Employee();

//...

protected:

int mId;

string mFirstName;

string mLastName;

int mSalary;

bool bHired;

};

#endif

Interface: Employee.h

#include "Employee.h"

Employee::Employee() :

mId(-1),

mFirstName(""),

mLastName(""),

mSalary(0),

bHired(false){

}

string Employee::getFirstName() const{

return mFirstName;

}/

/ ...

Implementation: Employee.cpp

© 2013 ANTAL Margit

OOP: Classes and objects

Object life cycles:

– creation

– assignment

– destruction

© 2013 ANTAL Margit

OOP: Classes and objects

Object creation:

– when an object is created,

● one of its constructors is executed,

● all its embedded objects are also created

int main() {

Employee emp;

emp.display();

Employee *demp = new Employee();

demp->display();

// ..

delete demp;

return 0;

}

object's

lifecycle

© 2013 ANTAL Margit

OOP: Classes and objects

Object creation – constructors:

– default constructor (0-argument constructor)

– when you need

● Employee employees[ 10 ];

● vector<Employee> emps;

Employee :: Employee() : mId(-1), mFirstName(""),

mLastName(""), mSalary(0), bHired(false){

}

Employee :: Employee() {

}

● memory allocation

● constructor call on

each allocated object

© 2013 ANTAL Margit

OOP: Classes and objects

Object creation – constructors:

– Compiler-generated default constructor

– if a class does not specify any constructors, the compiler will generate

one that does not take any arguments

class Value{

public:

void setValue( double inValue);

double getValue() const;

private:

double value;

};

© 2013 ANTAL Margit

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; //OK

mCi = inI; //ERROR: cannot assign to a const

mRi = inI; //ERROR: uninitialized reference member

}

ConstRef::ConstRef( int inI ): mI( inI ), mCi( inI ), mRi( inI ){}

ctor initializer

© 2013 ANTAL Margit

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

© 2013 ANTAL Margit

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{

}

© 2013 ANTAL Margit

OOP: Classes and objects

Copy Constructor

– called in one of the following cases:

● Employee emp1(1, "Robert", "Black", 4000, true);

● Employee emp2( emp1 ); //copy-constructor called

● Employee emp3 = emp2; //copy-constructor called

● void foo( Employee emp );

– if you don't define a copy-constructor explicitly, the compiler

creates one for you

● this performs a bitwise copy

© 2013 ANTAL Margit

OOP: Classes and objects

/ / S tack.h

#ifndef STACK_H

#define STACK_H

class Stack{

public:

Stack( int inCapacity );

void push( double inDouble );

double top();

void pop();

bool isFull();

bool isEmpty();

private:

int mCapacity;

double * mElements;

double * mTop;

};

#endif /* STACK_H */

//Stack.cpp

#include "Stack.h"

Stack::Stack( int inCapacity ){

mCapacity = inCapacity;

mElements = new double [ mCapacity ];

mTop = mElements;

}

void Stack::push( double inDouble ){

if( !isFull()){

*mTop = inDouble;

mTop++;

}

}

© 2013 ANTAL Margit

OOP: Classes and objects

//TestStack.cpp

#include "Stack.h"

int main(){

Stack s1(3);

Stack s2 = s1;

s1.push(1);

s2.push(2);

cout<<"s1: "<<s1.top()<<endl;

cout<<"s2: "<<s2.top()<<endl;

}

mCapacity: 3

mElements

mTop

s1: Stack

0

2

1

mCapacity: 3

mElements

mTop

s2: Stack

© 2013 ANTAL Margit

OOP: Classes and objects

Copy constructor: T ( const T&)

//Stack.h

#ifndef STACK_H

#define STACK_H

class Stack{

public:

//Copy constructor

Stack( const Stack& );

private:

int mCapacity;

double * mElements;

double * mTop;

};

#endif /* STACK_H */

//Stack.cpp

#include "Stack.h"

Stack::Stack( const Stack& s ){

mCapacity = s.mCapacity;

mElements = new double[ mCapacity ];

int nr = s.mTop - s.mElements;

for( int i=0; i<nr; ++i ){

mElements[ i ] = s.mElements[ i ];

}

mTop = mElements + nr;

}

© 2013 ANTAL Margit

OOP: Classes and objects

//TestStack.cpp

#include "Stack.h"

int main(){

Stack s1(3);

Stack s2 = s1;

s1.push(1);

s2.push(2);

cout<<"s1: "<<s1.top()<<endl;

cout<<"s2: "<<s2.top()<<endl;

}

mCapacity: 3

mElements

mTop

s1: Stack

0

2

1

mCapacity: 3

mElements

mTop

s1: Stack

0

2

1

© 2013 ANTAL Margit

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

© 2013 ANTAL Margit

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

© 2013 ANTAL Margit

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

class Stack{

public:

Stack( int inCapacity = 5 );

..

};

//Stack.cpp

Stack::Stack( int inCapacity ){

mCapacity = inCapacity;

mElements = new double [ mCapacity ];

mTop = mElements;

}

//TestStack.cpp

Stack s1(3); //capacity: 3

Stack s2; //capacity: 5

Stack s3( 10 ); //capacity: 10

© 2013 ANTAL Margit

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;

//..

}

© 2013 ANTAL Margit

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

};

© 2013 ANTAL Margit

OOP: Classes and objects

Programming task [Prata]

class Queue

{

private:

// class scope definitions

// Node is a nested structure definition local to this class

struct Node { Item item; struct Node * next;};

enum {Q_SIZE = 10};

// private class members

Node * front; // pointer to front of Queue

Node * rear; // pointer to rear of Queue

int items; // current number of items in Queue

const int qsize; // maximum number of items in Queue

};

© 2013 ANTAL Margit

Module 3

Object-Oriented Programming

Advanced Class Features

© 2013 ANTAL Margit

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

© 2013 ANTAL Margit

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

© 2013 ANTAL Margit

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

© 2013 ANTAL Margit

OOP: Advanced class features

inline function examples

inline double square(double a){

return a * a;

}

class Value{

int value;

public:

inline int getValue(){ return value; }

inline void setValue( int value ){

this->value = value;

}

};

© 2013 ANTAL Margit

OOP: Advanced class features

– Stack vs. Heap

– Heap – Dynamic allocation

– Stack – Automatic allocation

void draw(){

Point * p = new Point();

p->move(3,3);

//...

}

void draw(){

Point p();

p.move(6,6);

//...

}

© 2013 ANTAL Margit

OOP: Advanced class features

Array of objects

class Point{

int x, y;

public:

Point( int x=0, int y=0);

//...

};

:Point :Point :Point :Point

x: 0

y: 0

x: 0

y: 0

x: 0

y: 0

x: 0

y: 0

Point * t1 = new Point[ 4];

t1

Point t1[ 4];

What is the difference between these two arrays?

© 2013 ANTAL Margit

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

:Point

x: 0

y: 0

:Point

x: 0

y: 0

:Point

x: 0

y: 0

:Point

x: 0

y: 0

© 2013 ANTAL Margit

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

© 2013 ANTAL Margit

OOP: Advanced class features

– Static members

/ /Complex.h

class Complex{

public:

static int getNumComplex();

// ...

private:

static int num_complex;

double re, im;

};

//Complex.cpp

int Complex::num_complex = 0;

int Complex::getNumComplex(){

return num_complex;

}

initializing static class member

instance counter

© 2013 ANTAL Margit

OOP: Advanced class features

– Static method invocation

Complex z1(1,2), z2(2,3), z3;

cout<<"Number of complexs:"<<Complex::getNumComplex()<<endl;

cout<<"Number of complexes: "<<z1.getNumComplex()<<endl;

elegant

non - elegant

© 2013 ANTAL Margit

OOP: Advanced class features

Complex z1(1,2), z2(2,3), z3;

re: 1

im: 2

re: 2

im: 3

re: 0

im: 0

num_complex: 3

Each object has

its own re and im

Only one copy of

the static member

© 2013 ANTAL Margit

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

© 2013 ANTAL Margit

OOP: Advanced class features

– Classes vs. structures

class list{

private:

struct node

{

node *next;

int val;

node( int val=0, node * next=NULL):val(val), next(next){}

};

node * head;

public:

list ();

~list ();

void insert (int a);

};

© 2013 ANTAL Margit

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)

© 2013 ANTAL Margit

OOP: Advanced class features

– Passing function arguments

void f1(int x) {x = x + 1;}

void f2(int& x) {x = x + 1;}

void f3(const int& x) {x = x + 1;}

void f4(int *x) {*x = *x + 1;}

int main(){

int y = 5;

f1(y);

f2(y);

f3(y);

f4(&y);

return 0;

}

passing primitive values

© 2013 ANTAL Margit

OOP: Advanced class features

– Passing function arguments

void f1(Point p);

void f2(Point& p);

void f3(const Point& p);

void f4(Point *p);

int main(){

Point p1(3,3);

f1(p1);

f2(p1);

f3(p1);

f4(&p1);

return 0;

}

passing objects

copy constructor will be used on the argument

only const methods of the class can be

invoked on this argument

© 2013 ANTAL Margit

OOP: Advanced class features

– friend functions, friend classes, friend member

functions

● friends are allowed to access private members of a class

● allow you to violate the principle of abstraction

● use rarely

– operator overloading

© 2013 ANTAL Margit

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 );

};

© 2013 ANTAL Margit

OOP: Advanced class features

– friend vs. static functions

int Test :: sValue = 0;

void Test::print() const{

cout<<"Member: "<<iValue<<endl;

}

void Test::print( const Test& what ){

cout<<"Static: "<<what.iValue<<endl;

}

void print( const Test& what ){

cout<<"Friend: "<<what.iValue<<endl;

}

int main() {

Test test( 10 );

test.print();

Test::print( test );

print( test );

}

© 2013 ANTAL Margit

OOP: Advanced class features

– friend class vs. friend member function

c lass List{

private:

ListElement * head;

public:

bool find( int key );

};

class ListElement{

private:

int key;

ListElement * next;

friend class List;

...

};

class ListElement{

private:

int key;

ListElement * next;

friend class List::find( int key);

...

};

© 2013 ANTAL Margit

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())

return v1;

else

return v2;

}

// version 2

const vector<int> & Max(const vector<int> & v1, const vector<int> & v2)

{

if (v1.size() > v2.size())

return v1;

else

return v2;

}

Copy

constructor

invocation

More

efficient

The reference should be to

a non-local object

© 2013 ANTAL Margit

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;};

...

};

© 2013 ANTAL Margit

OOP: Advanced class features

– Nested classes [Prata]

// 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) { }

};

//...

};

Node visibility!!!

© 2013 ANTAL Margit

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)

● a nested class B declared in a protected section of a class A:

– B can be used both in A and in the derived classes of A

● a nested class B declared in a public section of a class A:

– B is available to the outside world ( A :: B b;)

© 2013 ANTAL Margit

OOP: Advanced class features

– Features of a well-behaved C++ class

– implicit constructor

● T :: T(){ … }

– destructor

● T :: ~T(){ … }

– copy constructor

● T :: T( const T& ){ … }

– assignment operator (see next module)

● T :: operator=( const T& ){ … }

© 2013 ANTAL Margit

Module 4

Object-Oriented Programming

Operator overloading

© 2013 ANTAL Margit

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

© 2013 ANTAL Margit

OOP: Operator overloading

Objective

– To make the class usage easier, more intuitive

● the ability to read an object using the inserter operator (>>)

– Employee e1; cin >> e;

● the ability to write an object using the extractor operator (<<)

– Employee e2; cout<<e<<endl;

● the ability compare to objects of a given class

– cout<< ((e1 < e2) ? "less" : "greater");

Operator overloading: a service to the clients of the class

© 2013 ANTAL Margit

OOP: Operator overloading

Limitations

– You cannot add new operator symbols. Only the existing operators

meaning 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

© 2013 ANTAL Margit

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)

© 2013 ANTAL Margit

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:

● assignment 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.”

© 2013 ANTAL Margit

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

© 2013 ANTAL Margit

OOP: Operator overloading

– The Complex class: Complex.h, Complex.cpp

class TYPES

Complex

- re: double

- im: double

+ Complex(double, double)

+ Complex(Complex&)

+ setRe(double) : void

+ setIm(double) : void

+ getRe() : double {query}

+ getIm() : double {query}

+ print() : void {query}

#include "Complex.h"

#include <iostream>

using namespace std;

Complex::Complex( double re, double im):re( re), im(im) {}

Complex::Complex(const Complex& orig):re( orig.re), im(orig.im){}

void Complex::setRe( double re){this->re = re;}

void Complex::setIm( double im){ this->im = im;}

double Complex::getRe() const{ return this->re;}

double Complex::getIm() const{ return this->im;}

void Complex::print() const{ cout<<re<<"+"<<im<<"i";}

© 2013 ANTAL Margit

OOP: Operator overloading

– Arithmetic operators (member func.)

● unary minus

● binary minus

Complex Complex::operator-() const{

Complex temp(-this->re, -this->im);

return temp;

}

Complex Complex::operator-( const Complex& z) const{

Complex temp(this->re - z.re, this->im- z.im);

return temp;

}

© 2013 ANTAL Margit

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).

© 2013 ANTAL Margit

OOP: Operator overloading

– Increment/Decrement operators (member func.)

Complex& Complex::operator++(){ //prefix

(this->re)++;

(this->im)++;

return *this;

}

Complex Complex::operator++( int ){ //postfix

Complex temp(*this);

(this->re)++;

(this->im)++;

return temp;

}

Which one is more efficient?

Why?

© 2013 ANTAL Margit

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;

}

istream& operator>>( istream& is, Complex& c){

is>>c.re>>c.im;

return is;

}

© 2013 ANTAL Margit

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&?

© 2013 ANTAL Margit

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;

© 2013 ANTAL Margit

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

● Syntax: X& operator=( const X& rhs);

© 2013 ANTAL Margit

OOP: Operator overloading

– Assignment operator (member func.)

● Syntax: X& operator=( const X& rhs);

● Q: Is the return type necessary?

– Analyze the following example code

Complex z1(1,2), z2(2,3), z3(1,1);

z3 = z1;

z2 = z1 = z3;

© 2013 ANTAL Margit

OOP: Operator overloading

– Assignment operator example

Stack& Stack::operator=(const Stack& rhs) {

if (this != &rhs) {

//delete lhs

delete [] this->mElements;

//copy rhs

mCapacity = rhs.mCapacity;

mElements = new double[ mCapacity ];

int nr = rhs.mTop - rhs.mElements;

for (int i = 0; i < nr; ++i) {

mElements[ i ] = rhs.mElements[ i ];

}

mTop = mElements + nr;

}

return *this;

}

© 2013 ANTAL Margit

OOP: Operator overloading

– Assignment operator vs Copy constructor

Complex z1(1,2), z2(3,4); //Constructor

Complex z3 = z1; //Copy constructor

Complex z4(z2); //Copy constructor

z1 = z2; //Assignment operator

© 2013 ANTAL Margit

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();

double& operator[]( int index );

double& operator[]( int index ) const;

protected:

double * mElems;

int mSize;

private:

CArray( const CArray&);

CArray& operator=( const CArray&);

};

#endif /* ARRAY_H */

Provides read-only access

© 2013 ANTAL Margit

OOP: Operator overloading

– Implementation

CArray::CArray( int size ){

if( size < 0 ){

size = 10;

}

this->mSize = size;

this->mElems = new double[ mSize ];

}

CArray::~CArray(){

if( this->mElems != NULL ){

delete[] mElems;

}

}

double& CArray::operator[]( int index ){

if( index <0 || index >= mSize ){

throw out_of_range("");

}

return mElems[ index ];

}

#include<stdexcept>

double& CArray::operator[](

int index ) const{

if( index <0 || index >= mSize ){

throw out_of_range("");

}

return mElems[ index ];

}

© 2013 ANTAL Margit

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);

© 2013 ANTAL Margit

OOP: Operator overloading

– Non-integral array indices: associative array

– ( Key, Value )

– Ex: Key → string, Value → double

● Homework

© 2013 ANTAL Margit

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();

}

bool operator <( const Point& p1, const Point& p2){

return p1.distance(Point(0,0)) < p2.distance(Point(0,0));

}

set<Point> p;

vector<Point> v; //...

sort(v.begin(), v.end());

© 2013 ANTAL Margit

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

#define ADDVALUE_H

class AddValue{

int value;

public:

AddValue( int inValue = 1);

void operator()( int& what );

};

#endif /* ADDVALUE_H */

#include "AddValue.h"

AddValue::AddValue( int inValue ){

this->value = inValue;

} void AddValue::operator()( int& what ){

what += this->value;

}

© 2013 ANTAL Margit

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;

}

© 2013 ANTAL Margit

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();

}

};

© 2013 ANTAL Margit

OOP: Operator overloading

– Function call operator

● sorted container

set<Employee, EmployeeCompare> s;

Employee e1; e1.setFirstName("Barbara");

e1.setLastName("Liskov");

Employee e2; e2.setFirstName("John");

e2.setLastName("Steinbeck");

Employee e3; e3.setFirstName("Andrew");

e3.setLastName("Foyle");

s.insert( e1 ); s.insert( e2 ); s.insert( e3 );

for( Employee emp : s){

emp.display();

}

© 2013 ANTAL Margit

OOP: Operator overloading

– Sorting elements of a given type:

● A. override operators: <, ==

● B. define a function object containing the comparison

– Which one to use?

● Q: How many sorted criteria can be defined using method A?

● Q: How many sorted criteria can be defined using method B?

© 2013 ANTAL Margit

OOP: Operator overloading

– Writing conversion operators

class Complex{

public:

operator string() const;

//

};

Complex::operator string() const{

stringstream ss;

ss<<this->re<<"+"<<this->im<<"i";

string s;

ss>>s;

return s;

}

//usage

Complex z(1, 2), z2;

string a = z;

cout<<a<<endl;

© 2013 ANTAL Margit

OOP: Operator overloading

– After templates

● Overloading operator *

● Overloading operator →

© 2013 ANTAL Margit

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

© 2013 ANTAL Margit

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

© 2013 ANTAL Margit

Module 5

Object-Oriented Programming

Inheritance

© 2013 ANTAL Margit

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

© 2013 ANTAL Margit

OOP: Inheritance

– public inheritance

● is-a relationship

● base class: Employee

● derived class: Manager

– You can do with inheritance

● add data

– ex. department

● add functionality

– ex. getDepartment(), setDepartment()

● modify methods' behavior

– ex. print()

class cppinheritance

Employee

- firstName: string

- lastName: string

- salary: double

+ Employee(string, string, double)

+ getFirstName() : string {query}

+ setFirstName(string) : void

+ getLastName() : string {query}

+ setLastName(string) : void

+ getSalary() : double {query}

+ setSalary(double) : void

+ print(ostream&) : void {query}

Manager

- department: string

+ Manager()

+ Manager(string, string, double, string)

+ setDepartment(string) : void

+ getDepartment() : string {query}

+ print(ostream&) : void {query}

© 2013 ANTAL Margit

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

© 2013 ANTAL Margit

OOP: Inheritance

– public inheritance

class Employee{

public:

Employee(string firstName = "", string lastName = "",

double salary = 0.0) : firstName(firstName),

lastName(lastName),

salary(salary) {

}

//...

};

class Manager:public Employee{

string department;

public:

Manager();

Manager( string firstName, string lastName, double salary,

string department );

//...

};

© 2013 ANTAL Margit

OOP: Inheritance

– Derived class's constructors

Manager::Manager(){

}

Manager::Manager(string firstName, string lastName, double salary,

string department): Employee(firstName, lastName, salary),

department(department){

}

Employee's constructor invocation → Default constructor can be invoked implicitly

base class's constructor invocation – constructor initializer list

arguments for the base class's constructor are specified in the definition of a derived class's constructor

© 2013 ANTAL Margit

OOP: Inheritance

– How are derived class's objects constructed?

● bottom up order:

– base class constructor invocation

– member initialization

– derived class's constructor block

● destruction

– in the opposite order

Employee

Manager

© 2013 ANTAL Margit

OOP: Inheritance

– Method overriding

class Employee {

public:

virtual void print( ostream&) const;

};

class Manager:public Employee{

public:

virtual void print(ostream&) const;

};

Employee{

© 2013 ANTAL Margit

OOP: Inheritance

– Method overriding

class Employee {

public:

virtual void print( ostream&) const;

};

void Manager::print(ostream& os) const{

Employee::print(os);

os<<" "<<department;

}

void Employee::print(ostream& os ) const{

os<<this->firstName<<" "<<this->lastName<<" "<<this->salary;

}

class Manager:public Employee{

public:

virtual void print(ostream&) const;

};

© 2013 ANTAL Margit

OOP: Inheritance

– Method overriding - virtual functions

● non virtual functions are bound statically

– compile time

● virtual functions are bound dynamically

– run time

© 2013 ANTAL Margit

OOP: Inheritance

– Polymorphism

void printAll( const vector<Employee*>& emps ){

for( int i=0; i<emps.size(); ++i){

emps[i]->print(cout);

cout<<endl;

}

}

int main(int argc, char** argv) {

vector<Employee*> v;

Employee e("John", "Smith", 1000);

v.push_back(&e);

Manager m("Sarah", "Parker", 2000, "Sales");

v.push_back(&m);

cout<<endl;

printAll( v );

return 0;

}

Output:

John Smith 1000

Sarah Parker 2000 Sales

© 2013 ANTAL Margit

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

– Employee :: print( os ) static binding – no

polymorhism

© 2013 ANTAL Margit

OOP: Inheritance

– Polymorphism – Virtual Function Table

class Employee{

public:

virtual void print(ostream&) const;

//...

};

class Manager:public Employee{

virtual void print(ostream&) const;

//...

};

Employee e1, e2;

Manager m1, m2;

firstName:””

lastName:””

salary:0.0

firstName:””

lastName:””

salary:0.0

e1

e2

Employee::print

Manager::print

firstName:””

lastName:””

salary:0.0

department

vtbl

firstName:””

lastName:””

salary:0.0

department

firstName:””

lastName:””

salary:0.0

department

m1

m2

vtbl

vtbl

vtbl

vtbl

Discussion!!!

Employee * pe;

pe = &e1; pe->print();//???

pe = &m2; pe->print();//???

© 2013 ANTAL Margit

OOP: Inheritance

– Abstract classes

● used for representing abstract concepts

● used as base class for other classes

● no instances can be created

© 2013 ANTAL Margit

OOP: Inheritance

– Abstract classes – pure virtual functions

class Shape{ // abstract class

public:

virtual void rotate(int) = 0; // pure virtual function

virtual void draw() = 0; // pure virtual function

// ...

};

Shape s; //Compiler error

© 2013 ANTAL Margit

OOP: Inheritance

– Abstract class → concrete class

class Point{ /* ... */ };

class Circle : public Shape {

public:

void rotate(int); // override Shape::rotate

void draw(); // override Shape::draw

Circle(Point p, int r) ;

private:

Point center;

int radius;

};

© 2013 ANTAL Margit

OOP: Inheritance

– Abstract class → abstract class

class Polygon : public Shape{

public:

// draw() and rotate() are not overridden

};

Polygon p; //Compiler error

© 2013 ANTAL Margit

OOP: Inheritance

– Virtual destructor

● Every class having at least one virtual function should

have virtual destructor. Why?

class X{

public:

// ...

~X();

};

© 2013 ANTAL Margit

OOP: Inheritance

– Virtual destructor

void deleteAll( Employee ** emps, int size){

for( int i=0; i<size; ++i){

delete emps[ i ];

}

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);

Which destructor is invoked?

© 2013 ANTAL Margit

Module 6

Object-Oriented Programming

Object relationships

© 2013 ANTAL Margit

OOP: Object relationships

– Content

● The is-a relationship

● The has-a relationship

● Private inheritance

● Multiple inheritance

● ...

© 2013 ANTAL Margit

OOP: Object relationships

– The is-a relationship – Client's view (1)

● works in only one direction:

– every Sub object is also a Super one

– but Super object is not a Sub

Super

Sub

void foo1( const Super& s );

void foo2( const Sub& s);

Super super;

Sub sub;

foo1(super); //OK

foo1(sub); //OK

foo2(super); //NOT OK

foo2(sub); //OK

© 2013 ANTAL Margit

OOP: Object relationships

– The is-a relationship – Client's view (2)

Super

class Super{ Sub

public:

virtual void method1();

};

class Sub : public Super{

public:

virtual void method2();

};

Super * p= new Super();

p->method1(); //OK

p = new Sub();

p->method1(); //OK

p->method2(); //NOT OK

((Sub *)p)->method2();//OK

© 2013 ANTAL Margit

OOP: Object relationships

– The is-a relationship – Sub-class’s view

● the Sub class augments the Super class by

adding additional methods

● the Sub class may override the Super class methods

● the subclass can use all the public and

protected members of a superclass.

Super

Sub

© 2013 ANTAL Margit

OOP: Object relationships

– The is-a relationship: preventing inheritance C++11

● final classes – cannot be extended

class Super final

{

};

© 2013 ANTAL Margit

OOP: Object relationships

– The is-a relationship: a client's view of overridden methods(1)

● polymorphism

class Super{

public:

virtual void method1();

};

class Sub : public Super{

public:

virtual void method1();

};

Super super;

super.method1(); //Super::method1()

Sub sub;

sub.method1(); //Sub::method1()

Super& ref =super;

ref.method1(); //Super::method1();

ref = sub;

ref.method1(); //Sub::method1();

Super* ptr =&super;

ptr->method1(); //Super::method1();

ptr = &sub;

ptr->method1(); //Sub::method1();

© 2013 ANTAL Margit

OOP: Object relationships

– The is-a relationship: a client's view of overridden methods(2)

● object slicing

class Super{

public:

virtual void method1();

};

class Sub : public Super{

public:

virtual void method1();

};

Sub sub;

Super super = sub;

super.method1(); // Super::method1();

Sub

Super Super

super sub

© 2013 ANTAL Margit

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

};

© 2013 ANTAL Margit

OOP: Object relationships

– Inheritance for reuse (1) [Gregoire]

//WeatherPrediction.h

class WeatherPrediction

{

public:

virtual void setCurrentTempFahrenheit(int inTemp);

virtual void setPositionOfJupiter(

int inDistanceFromMars);

virtual int getTomorrowTempFahrenheit();

virtual double getChanceOfRain();

virtual void showResult();

virtual std::string getTemperature() const;

protected:

int mCurrentTempFahrenheit;

int mDistanceFromMars;

};

There are 2 problems:

● the temperatures are in

Fahrenheit

● showResult() does not

display the needed information

© 2013 ANTAL Margit

OOP: Object relationships

– Inheritance for reuse (2) [Gregoire]

● adding functionality (new methods)

● replacing functionality (overriding methods)

//WeatherPrediction.h

class MyWeatherPrediction : public WeatherPrediction

{

public:

virtual void setCurrentTempCelsius(int inTemp);

virtual int getTomorrowTempCelsius();

virtual void showResult();

protected:

static int convertCelsiusToFahrenheit(int inCelsius);

static int convertFahrenheitToCelsius(int inFahrenheit);

};

© 2013 ANTAL Margit

OOP: Object relationships

– Inheritance for polymorphism (1)

www.javatutorialhub.com

© 2013 ANTAL Margit

OOP: Object relationships

– The has-a relationship

Window Button

© 2013 ANTAL Margit

OOP: Object relationships

– Implementing the has-a relationship

● An object A has an object B

A B

class B;

class A{

private:

B b;

};

class B;

class A{

private:

B& b;

};

class B;

class A{

private:

B* b;

};

© 2013 ANTAL Margit

OOP: Object relationships

– Implementing the has-a relationship

● An object A has an object B

– strong containment (composition)

A B

class B;

class A{

private:

B b;

};

A anObject;

b: B

anObject: A

© 2013 ANTAL Margit

OOP: Object relationships

– Implementing the has-a relationship

● An object A has an object B

– weak containment (aggregation)

A B

class B;

class A{

private:

B& b;

public:

A( const B& pb):b(pb){}

};

B bObject;

A aObject1(bObject);

A aObject2(bObject);

aObject1: A

bObject: B

aObject2: A

© 2013 ANTAL Margit

OOP: Object relationships

– Implementing the has-a relationship

● An object A has an object B

A B

class B;

class A{

private:

B* b;

public:

A(){

b = new B();

}

~A(){

delete b;

}

};

class B;

class A{

private:

B* b;

public:

A( B* pb):b( pb ){}

};

weak containment strong containment

© 2013 ANTAL Margit

OOP: Object relationships

– Implementing the has-a relationship

● An object A has an object B

A B

Usage:

B bObject;

A aObject1(&bObject);

A aObject2(&bObject);

class B;

class A{

private:

B* b;

public:

A( B* pb):b( pb ){}

};

weak containment

aObject1: A

bObject: B

aObject2: A

© 2013 ANTAL Margit

OOP: Object relationships

– Implementing the has-a relationship

● An object A has an object B

A B

class B;

class A{

private:

B* b;

public:

A(){

b = new B();

}

~A(){

delete b;

}

};

strong containment

b: B *

anObject: A

Usage:

A aObject;

© 2013 ANTAL Margit

OOP: Object relationships

– Combining the is-a and the has-a relationships

class Class Mo...

Component

+ Operation()

+ Add() : Component

+ Remove() : Component

+ GetChild() : Component

Client

Leaf

+ Operation()

Composite

+ Operation()

forall g in children

g.Operation();

+ Add() : Component

+ Remove() : Component

+ GetChild() : Component

-children

1..*

© 2013 ANTAL Margit

OOP: Object relationships

– The Composite Design Pattern

● Compose objects into tree structures to represent part-whole

hierarchies.

● Lets clients treat individual objects and composition of objects

uniformly. Recursive composition

● 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

© 2013 ANTAL Margit

class xo2_1

Jatek

- hanySzimbolum: int

- jatekos: vector<Jatekos>

- logika: Logika&

- tabla: T abla&

+ Jatek(Logika&, T abla&)

+ addJatekos(Jatekos) : void

+ jatszma() : void

Jatekos

- nev: string

- szimbolum: char

- tabla: T abla&

+ Jatekos(char*, char, T abla&)

+ setNev(char*) : void

+ setSzimbolum(char) : void

+ getSzimbolum() : char {query}

+ getNev() : string {query}

+ operator=(Jatekos&) : Jatekos&

+ lepik(int, int) : bool

«friend»

+ operator<<(ostream&, Jatekos&) : ostream&

Logika

- counter: int

- hanySzimbolum: int

- tabla: T abla&

+ Logika(T abla&, int)

+ jatekVege() : bool

+ nyeroE(Jatekos, int, int) : bool

Tabla

- sor: int

- oszlop: int

- cel lak: char ([ MAX ][ MAX ])

+ T abla(int, int)

+ getSor() : int {query}

+ getOszlop() : int {query}

+ getCella(int, int) : char

+ setCella(int, int, char) : void

+ uresE(int, int) : bool

+ torles() : void

+ printT abla(ostream&) : void {query}

«friend»

+ operator<<(ostream&, T abla&) : ostream&

-tabla -tabla

-tabla

-logika

2

jatekos

© 2013 ANTAL Margit

OOP: Object relationships

– Multiple inheritance

© 2013 ANTAL Margit

OOP: Object relationships

– Private inheritance

© 2013 ANTAL Margit

Module 7

Generic Programming: Templates

© 2013 ANTAL Margit

Outline

– Templates

● Class template

● Function template

● Template metaprogramming

© 2013 ANTAL Margit

Templates

© 2013 ANTAL Margit

Templates

– Allow generic programming

● to write code that can work with all kind of objects

● template programmer's obligation: specify the

requirements of the classes that define these objects

● template user's obligation: supplying those operators

and methods that the template programmer requires

© 2013 ANTAL Margit

Function Template

– Allows writing function families

● What are the requirements regarding the type T?

template<typename T>

const T max(const T& x, const T& y) {

return x < y ? y : x;

}

template<class T>

const T max(const T& x, const T& y) {

return x < y ? y : x;

}

Template

parameter

© 2013 ANTAL Margit

Function Template

● Requirements regarding the type T:

– less operator (<)

– copy constructor

template<class T>

const T max(const T& x, const T& y) {

return x < y ? y : x;

}

© 2013 ANTAL Margit

Function Template

● 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

template<class T>

const T max(const T& x, const T& y) {

return x < y ? y : x;

}

© 2013 ANTAL Margit

Function Template

● Requirements regarding the type T:

– copy constructor

– assignment operator

template<class T>

void swap(T& x, T& y) {

const T tmp = x;

x = y;

y = tmp;

}

© 2013 ANTAL Margit

Function Template

– Allows writing function families

● polymorphism: compile time

– How the compiler processes templates?

– cout<<max(2, 3)<<endl; // max: T → int

– cout<<max(2.5, 3.6)<<endl; // max: T → double

– How many max functions does the program have?

Warning: Code bloat!

© 2013 ANTAL Margit

Function Template

– What does it do? [Gregoire]

static const size_t MAGIC = (size_t)(-1);

template <typename T>

size_t Foo(T& value, T* arr, size_t size)

{

for (size_t i = 0; i < size; i++) {

if (arr[i] == value) {

return i;

}

}

return MAGIC;

}

© 2013 ANTAL Margit

Class Template

– Allow writing class families

template<typename T>

class Array {

T* elements;

int size;

public:

explicit Array(const int size);

...

};

© 2013 ANTAL Margit

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]){

}

© 2013 ANTAL Margit

Class Template

– Template parameters

● type template parameters

● non-type template parameters

template<typename T>

class Array {

T* elements;

int size;

public:

Array(const int size);

...

};

template<class T, int MAX=100>

class Stack{

T elements[ MAX ];

public:

...

};

© 2013 ANTAL Margit

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”

© 2013 ANTAL Margit

Class Template+ Function Template

template<class T1, class T2>

struct pair {

typedef T1 first_type;

typedef T2 second_type;

T1 first;

T2 second;

pair();

pair(const T1& x, const T2& y);

...

};

template< class T1, class T2>

pair<T1, T2> make_pair(const T1& x, const T2& y)

{

return pair<T1, T2>(x, y);

}

#include <utility>

© 2013 ANTAL Margit

Advanced Template

● template template parameter

template<typename T, typename Container>

class Stack{

Container elements;

public:

void push( const T& e ){

elements.push_back( e );

}

...

};

Stack<int, vector<int> > v1;

Stack<int, deque<int> > v2;

Usage:

© 2013 ANTAL Margit

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 );

}

...

};

© 2013 ANTAL Margit

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;

}

© 2013 ANTAL Margit

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;

}

© 2013 ANTAL Margit

Module 8

STL – Standard Template Library

© 2013 ANTAL Margit

Outline

– Containers

– Algorithms

– Iterators

© 2013 ANTAL Margit

STL – General View

– library of reusable components

– a support for C++ development

– based on generic programming

© 2013 ANTAL Margit

STL – General View

– Containers – Template Class

● generalized data structures (you can use them for any

type)

– Algorithms – Template Function

● generalized algorithms (you can use them for almost any

data structure)

– Iterators – Glue between Containers and Algorithms

● specifies a position into a container (generalized pointer)

© 2013 ANTAL Margit

Basic STL Containers

– Sequence containers

● linear arrangement

– vector, deque, list

– stack, queue, priority_queue

– Associative containers

● provide fast retrieval of data based on keys

– set, multiset, map, multimap

<vector> <deque> <list>

<set> <map>

<stack> <queue>

Container

adapters

© 2013 ANTAL Margit

Sequence Containers

© 2013 ANTAL Margit

Associative Containers

© 2013 ANTAL Margit

STL Containers C++11

– Sequence containers

– array (C-style array)

– forward-list (singly linked list)

– Associative containers

– unordered_set, unordered_multiset (hash table)

– unordered_map, unordered_multimap (hash table)

<array> <forward-list>

<unordered_set>

<unordered_map>

© 2013 ANTAL Margit

STL Containers

– homogeneous:

● vector<Person>, vector<Person*>

– polymorphism

● vector<Person*>

class Person{};

class Employee: public Person{};

class Manager : public Employee{};

© 2013 ANTAL Margit

STL Containers

Person Person Person

Person Employee Manager

...

...

vector<Person>

vector<Person *>

homogenous

homogenous

heterogenous

© 2013 ANTAL Margit

The vector container - constructors

vector<T> v;

//empty vector

vector<T> v(n, value);

//vector with n copies of value

vector<T> v(n);

//vector with n copies of default for T

© 2013 ANTAL Margit

The vector container – add new elements

vector<int> v;

for( int i=1; i<=5; ++i){

v.push_back( i );

}

1 2 3 4 5

v.begin() v.end()

© 2013 ANTAL Margit

The vector container

vector<int> v( 10 );

cout<<v.size()<<endl;//???

for( int i=0; i<v.size(); ++i ){

cout<<v[ i ]<<endl;

}

for( int i=0; i<10; ++i){

v.push_back( i );

}

cout<<v.size()<<endl;//???

typedef vector<int>::iterator VectIt;

for( VectIt it = v.begin(); it != v.end(); ++it ){

cout<<*it<<endl;

}

© 2013 ANTAL Margit

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;

}

© 2013 ANTAL Margit

The vector container: capacity and size

vector<int> v;

v.reserve( 10 );

cout << v.size() << endl;//???

cout << v.capacity() << endl;//???

--------------------------------------

vector<int> gy( 256 );

ifstream ifs("szoveg.txt"); int c;

while( (c = ifs.get() ) != -1 ){

gy[ c ]++;

}

© 2013 ANTAL Margit

The vector - indexing

int Max = 100;

vector<int> v(Max);

//???...

for (int i = 0; i < 2*Max; i++) {

cout << v[ i ]<<” ”;

}

--------------------------------------

int Max = 100;

vector<int> v(Max);

for (int i = 0; i < 2*Max; i++) {

cout << v.at( i )<<” ”;

}

© 2013 ANTAL Margit

The vector - indexing

int Max = 100;

vector<int> v(Max);

//???...

for (int i = 0; i < 2*Max; i++) {

cout << v[ i ]<<” ”;

}

--------------------------------------

int Max = 100;

vector<int> v(Max);

for (int i = 0; i < 2*Max; i++) {

cout << v.at( i )<<” ”;

}

Efficient

Safe

out_of_range exception

© 2013 ANTAL Margit

The list container

– doubly linked list

1 2 3 4 5

l.begin() l.end()

list<int> l;

for( int i=1; i<=5; ++i){

l.push_back( i );

}

© 2013 ANTAL Margit

The deque container

– double ended vector

deque<int> l;

for( int i=1; i<=5; ++i){

l.push_front( i );

}

© 2013 ANTAL Margit

Algorithms - sort

– what to sort: [first, last)

– how to compare the elements:

● <

● comp

template <class RandomAccessIterator, class Compare>

void sort ( RandomAccessIterator first, RandomAccessIterator last,

Compare comp );

template <class RandomAccessIterator>

void sort ( RandomAccessIterator first,RandomAccessIterator last );

© 2013 ANTAL Margit

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());

© 2013 ANTAL Margit

Algorithms - sort

struct Cmp_by_name{

bool operator()(const Rec& a, const Rec& b) const

{

return a.name < b.name;

}

};

struct Cmp_by_addr{

bool operator()(const Rec& a, const Rec& b) const

{

return a.addr < b.addr;

}

};

function object

© 2013 ANTAL Margit

Iterators

– The container manages the contained objects but does

not know about algorithms

– The algorithm works on data but does not know the

internal structure of containers

– Iterators fit containers to algorithms

© 2013 ANTAL Margit

Iterators

– The container manages the contained objects but does

not know about algorithms

– The algorithm works on data but does not know the

internal structure of containers

– Iterators fit containers to algorithms

© 2013 ANTAL Margit

Iterator - the glue

int x[]={1,2,3,4,5}; vector<int>v(x, x+5);

int sum1 = accumulate(v.begin(), v.end(), 0);

list<int> l(x, x+5);

double sum2 = accumulate(l.begin(), l.end(), 0);

1 2 3 4 5

v.begin() v.end()

1 2 3 4 5

l.begin() l.end()

© 2013 ANTAL Margit

Iterator - the glue

template<class InIt, class T>

T accumulate(InIt first, InIt last, T init)

{

while (first!=last) {

init = init + *first;

++first;

}

return init;

}

© 2013 ANTAL Margit

The set container

set< Key[, Comp = less<Key>]>

usually implemented as a balanced binary tree

Source:http://www.cpp-tutor.de/cpp/le18/images/set.gif

multiset: allows duplicates

© 2013 ANTAL Margit

The set container - usage

bool operator<(const Person&, const Person&)

struct PersonComp{

bool operator() ( const Person&, const Person& );

};

<

#include <set>

set<int> intSet;

set<Person> personSet1;

set<Person, PersonComp> personSet2;

© 2013 ANTAL Margit

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;

}

© 2013 ANTAL Margit

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;

}

© 2013 ANTAL Margit

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);

};

© 2013 ANTAL Margit

The set container - usage

class PersonCompare {

public:

enum Criterion { NAME, BIRTHYEAR};

private:

Criterion criterion;

public:

PersonCompare(Criterion criterion) : criterion(criterion) {}

bool operator()(const Person& p1, const Person& p2) {

switch (criterion) {

case NAME: //

case BIRTHYEAR: //

}

}

};

function object

state

behaviour

© 2013 ANTAL Margit

The set container - usage

set<Person, PersonCompare> s( PersonCompare::NAME);

s.insert(Person("Biro", "Istvan", 1960));

s.insert(Person("Abos", "Gergely", 1986));

s.insert(Person("Gered","Attila", 1986));

set<Person, PersonCompare>::iterator it;

for( it= s.begin(); it != s.end(); ++it){

cout <<*it <<endl;

}

© 2013 ANTAL Margit

The map container

map< Key, Value[,cComp = less<Key>]>

usually implemented as a balanced binary tree

Source: http://www.cpp-tutor.de/cpp/le18/images/map.gif

map: associative array multimap: allows duplicates

© 2013 ANTAL Margit

The map container - usage

#include <map>

map<string,int> products;

products.insert(make_pair("tomato",10));

products["cucumber"] = 6;

cout<<products["tomato"]<<endl;

© 2013 ANTAL Margit

The map container - usage

typedef map<string,int>::iterator MapIt;

for(MapIt it=aruk.begin(); it != aruk.end(); ++it)

{

cout<<(it->first)<<" : "<<(it->second)<<endl;

}

© 2013 ANTAL Margit

The multimap container - usage

multimap<string, string> cities;

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"));

typedef multimap<string, string>::iterator MIT;

pair<MIT, MIT> ret = cities.equal_range("HU");

for (MIT it = ret.first; it != ret.second; ++it) {

cout << (*it).first <<"\t"<<(*it).second<<endl;

}

© 2013 ANTAL Margit

The set/map container - removal

void erase ( iterator position );

size_type erase ( const key_type& x );

void erase ( iterator first, iterator last );

© 2013 ANTAL Margit

The set – pointer key type

Output??

set<string *> allatok;

allatok.insert(new string("majom"));

allatok.insert(new string("szarvas"));

allatok.insert(new string("kutya"));

allatok.insert(new string("béka"));

set<string*>::iterator it1;

for (it1 = allatok.begin();it1 != allatok.end();++it1)

cout << *it1 << endl;

© 2013 ANTAL Margit

The set – pointer key type

Corrected

struct StringComp{

bool operator()(const string* s1,

const string * s2){

return *s1 < *s2;

}

};

set<string*, StringComp> s;

s.insert( new string("alma"));

s.insert( new string("szilva"));

s.insert( new string("dio"));

s.insert( new string("mogyoro"));

set<string*, StringComp>::iterator it;

for( it = s.begin(); it != s.end(); ++it )

cout<<**it<<endl;

© 2013 ANTAL Margit

What is missing from the STL?

– no thread safety (simultaneous access from multiple

threads)

– no generic tree or graph data structure (altough sets

and maps are usually implemented as balanced binary

trees)

– but, STL is extensible

© 2013 ANTAL Margit

Module 9

I/O Streams

© 2013 ANTAL Margit

Outline

– Using Streams

– String Streams

– File Streams

– Bidirectional I/O

© 2013 ANTAL Margit

Using Streams

● file

● keypad

● program

Input Stream Output Stream

● file

● screen

● program

Program

stream:

● is data flow

● direction

● associated source and destination

© 2013 ANTAL Margit

Using Streams

cin An input stream, reads data from the “input console.”

cout A buffered output stream, writes data to the output console.

cerr An unbuffered output stream, writes data to the “error console”

clog A buffered version of cerr.

© 2013 ANTAL Margit

Using Streams

– Stream:

● includes data

● has a current position

– next read or next write

© 2013 ANTAL Margit

Using Streams

basic_iostream<>

iostream, wiostream

ios_base

basic_ios<>

ios, wios

basic_istream<>

istream, wistream

basic_ostream<>

ostream, wostream

basic_streambuf<>

streambuf, wstreambuf

© 2013 ANTAL Margit

Using Streams

– Output stream:

● inserter operator <<

● raw output methods (binary):

– put(), write()

void rawWrite(const char* data, int dataSize){

cout.write(data, dataSize);

}

void rawPutChar(const char* data, int charIndex)

{

cout.put(data[charIndex]);

}

© 2013 ANTAL Margit

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()

© 2013 ANTAL Margit

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;

© 2013 ANTAL Margit

Using Streams

– Input stream:

● extractor operator >>

– will tokenize values according to white spaces

● raw input methods (binary):

– get(): avoids tokenization

string readName(istream& inStream)

{

string name;

char next;

while (inStream.get(next)) {

name += next;

}

return name;

}

reads an input having

more than one word

© 2013 ANTAL Margit

Using Streams

– Input stream:

● getline(): reads until end of line

string myString;

getline(cin, myString);

reads an input having

more than one word

© 2013 ANTAL Margit

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

© 2013 ANTAL Margit

Using Streams

– Find the error!

list<int> a;

int x;

while( !cin.eof() ){

cin>>x;

a.push_back( x );

}

Input:

1

2

3(

empty line)

a: 1, 2, 3, 3

© 2013 ANTAL Margit

Using Streams

– Handling Input Errors:

● while( cin )

● while( cin >> ch )

int number, sum = 0;

while ( true ) {

cin >> number;

if (cin.good()){

sum += number;

} else{

break;

}

}

int number, sum = 0;

while ( cin >> number ){

sum += number;

}

© 2013 ANTAL Margit

String Streams

– <sstream>

● ostringstream

● istringstream

● stringstream

string s =”12.34”;

stringstream ss(s);

double d;

ss >> d;

double d =12.34;

stringstream ss;

ss<<d;

string s = “szam:”+ss.str()

© 2013 ANTAL Margit

File Streams

{

ifstream ifs("in.txt");//Constructor

if( !ifs ){

//File open error

}

//Destructor

}

{

ifstream ifs;

ifs.open("in.txt");

//...

ifs.close();

//...

}

© 2013 ANTAL Margit

File Streams

– Byte I/O

ifstream ifs("in.txt");

if( !ifs ){

cerr<<"File Open Error"<<endl; exit( 1 );

}

char c;

while( ifs.get( c ) ){

cout.put( c );

}

© 2013 ANTAL Margit

Object I/O

– Operator overloading

istream& operator>>( istream& is, T& v ){

//read v

return is;

}

ostream& operator<<(ostream& is, const T& v ){

//write v

return os;

}

© 2013 ANTAL Margit

Module 10

Advanced C++

© 2013 ANTAL Margit

Outline

– Hash Tables

– Algorithms

– Private Inheritance

– Casting. RTTI.

– Lambdas

© 2013 ANTAL Margit

Hash Tables

Source: http://integrator-crimea.com/ddu0065.html

collision

© 2013 ANTAL Margit

Hash Tables

Collision resolution by chaining

Source: http://integrator-crimea.com/ddu0065.html

© 2013 ANTAL Margit

Hash Tables

Collision resolution by chaining

Source: http://integrator-crimea.com/ddu0065.html

© 2013 ANTAL Margit

Unordered Associative Containers - Hash Tables

– unordered_set

– unordered_multiset

– unordered_map

– unordered_multimap

© 2013 ANTAL Margit

Unordered Associative Containers

– The STL standard does not specify which collision

handling algorithm is required

● most of the current implementations use linear chaining

● a lookup of a key involves:

– a hash function call h(key)– calculates the index in the

hash table

– compares key with other keys in the linked list

© 2013 ANTAL Margit

Hash Function

– perfect hash: no collisions

– lookup time: O(1) - constant

– there is a default hash function for each STL hash

container

© 2013 ANTAL Margit

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:

– Key – key type

– T – value type

– Hash – hash function type

– Pred – equality type

© 2013 ANTAL Margit

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:

– Key – key type

– Hash – hash function type

– Pred – equality type

© 2013 ANTAL Margit

Problem

– Read a file containing double numbers. Eliminate the

duplicates.

– Solutions???

© 2013 ANTAL Margit

Solutions

– vector<double> + sort + unique

– set<double>

– unordered_set<double>

– Which is the best? Why?

– What are the differences?

© 2013 ANTAL Margit

Which container to use?

– implement a PhoneBook, which:

● stores names associated with their phone numbers;

● names are unique;

● one name can have multiple phone numbers

associated;

● provides O(1) time search;

© 2013 ANTAL Margit

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;

© 2013 ANTAL Margit

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);

};

© 2013 ANTAL Margit

unordered_map: example

typedef unordered_map<string, vector<string> >::iterator Iterator;

void PhoneBook::addItem( string name, string phone){

Iterator it = this->book.find( name );

if( it != book.end() ){

it->second.push_back( phone );

}else{

vector<string> phones;

phones.push_back(phone);

book.insert( make_pair(name, phones ));

}

}

© 2013 ANTAL Margit

C++/Java

C++ Java

Objects X x;

X * px = new X();

X x = new X();

Parameter passing void f( X x );

void f( X * px);

void f( X& rx);

void f( const X&rx);

void f( X x );

//pass through

reference

run-time binding only for virtual

functions

for each function (except

static functions)

memory management explicit implicit (garbage collection)

multiple inheritance yes no

© 2013 ANTAL Margit

Algorithms

– The STL separates the data (containers) from the

functionality (algorithms)

● only partial separation:

– OOP encapsulates data and functionality

● data + functionality = object

© 2013 ANTAL Margit

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

© 2013 ANTAL Margit

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

}

© 2013 ANTAL Margit

Algorithm categories

– Utility algorithms

– Non-modifying algorithms

● Search algorithms

● Numerical Processing algorithms

● Comparison algorithms

● Operational algorithms

– Modifying algorithms

● Sorting algorithms

● Set algorithms

© 2013 ANTAL Margit

Utility Algorithms

– min_element()

– max_element()

– minmax() C++11

– swap()

© 2013 ANTAL Margit

Non-modifying algorithms

Search algorithms

– find(), find_if(), find_if_not(), find_first_of()

– binary_search()

– lower_bound(), upper_bound(), equal_range()

– all_of(), any_of(), none_of()

– ...

© 2013 ANTAL Margit

Non-modifying algorithms

Search algorithms - Example

– bool isEven (int i) { return ((i%2)==1); }

typedef vector<int>::iterator VIT;

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;

}

© 2013 ANTAL Margit

Non-modifying algorithms

Numerical Processing algorithms

– count(), count_if()

– accumulate()

– ...

© 2013 ANTAL Margit

Non-modifying algorithms

Numerical Processing algorithms - Example

bool isEven (int i) { return ((i%2)==1); }

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;

}

© 2013 ANTAL Margit

Non-modifying algorithms

Comparison algorithms

– equal()

– mismatch()

– lexicographical_compare()

© 2013 ANTAL Margit

Non-modifying algorithms

Comparison algorithms - Example

// 'strange alphabet: 'a' ->3, 'b'->1, c->'2'

// “abc” >”bca”

map<char, int> order;

// Compares two characters based on the strange order

bool compChar( char c1, char c2 ){

return order[c1]<order[c2];

}

// Compares two strings based on the strange order

bool compString(const string& s1, const string& s2){

return lexicographical_compare(

s1.begin(), s1.end(), s2.begin(), s2.end(), compChar);

}

© 2013 ANTAL Margit

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);

© 2013 ANTAL Margit

Modifying algorithms

– copy(), copy_backward()

– move(), move_backward() C++11

– fill(), generate()

– unique(), unique_copy()

– rotate(), rotate_copy()

– next_permutation(), prev_permutation()

– nth_element() ...

© 2013 ANTAL Margit

Modifying algorithms

Permutations

void print( const vector<int>& v){

for(int i=0; i<v.size(); ++i){

cout<<v[ i]<<"\t";

}

cout << endl;

}

int main(){

vector<int> v ={1,2,3};

print( v );

while( next_permutation(v.begin(), v.end())){

print( v );

}

return 0;

}

© 2013 ANTAL Margit

Private Inheritance

– another possibility for has-a relationship

Base class

Derived class

Base class

Derived class

public

inheritance

private

inheritance

public

public

public

private

Derived class inherits the

base class behavior

Derived class hides the

base class behavior

© 2013 ANTAL Margit

Private Inheritance

template <typename T>

class MyStack : private vector<T> {

public:

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();

}

};

© 2013 ANTAL Margit

Non-public Inheritance

– it is very rare;

– use it cautiously;

– most programmers are not familiar with it;

© 2013 ANTAL Margit

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;

}

};

Sub sub; Super super;

Super& ref = sub;ref.someMethod(1);

ref = super; ref.someMethod(1);

© 2013 ANTAL Margit

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;

}

};

Sub sub; Super super;

Super& ref = sub;ref.someMethod(1);

ref = super; ref.someMethod(1);

creates a new method, instead

of overriding the method

© 2013 ANTAL Margit

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;

}

};

Sub sub; Super super;

Super& ref = sub;ref.someMethod(1);

ref = super; ref.someMethod(1);

© 2013 ANTAL Margit

Casting

– converting an expression of a given type into another type

– traditional type casting:

● (new_type) expression

● new_type (expression)

– specific casting operators:

● dynamic_cast <new_type> (expression)

● reinterpret_cast <new_type> (expression)

● static_cast <new_type> (expression)

● const_cast <new_type> (expression)

© 2013 ANTAL Margit

Run Time Type Information

– Available only for polymorphic classes (having at least one

virtual method)

– Operators

● dynamic_cast<>

● typeid

© 2013 ANTAL Margit

dynamic_cast - Usage

– Available only for polymorphic classes (having at least one

virtual method)

– Operators

● dynamic_cast<>

● typeid

© 2013 ANTAL Margit

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(); // ???

© 2013 ANTAL Margit

dynamic_cast<>

class Base{};

class Derived : public Base{};

Base* basePointer = new Derived();

Derived* derivedPointer = nullptr;

//To find whether basePointer is pointing to Derived type of object

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";

}

© 2013 ANTAL Margit

typeid

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;};

};

© 2013 ANTAL Margit

Which solution is better?

void speak(const Animal& inAnimal) {

if (typeid (inAnimal) == typeid (Dog)) {

cout << "VauVau" << endl;

} else if (typeid (inAnimal) == typeid (Bird)) {

cout << "Csirip" << endl;

}

}

Bird bird; Dog d;

speak(bird); speak( dog );

void speak(const Animal& inAnimal) {

inAnimal.speak();

}

Bird bird; Dog d;

speak(bird); speak( dog );

© 2013 ANTAL Margit

Lambda Expressions - C++11

– allows you to write anonymous functions inline,

– removes the need to write a separate function or to write a

function object (e. g. sort, set,...),

– makes the code easier to understand.

© 2013 ANTAL Margit

Lambda Expressions

– Syntax:

[capture_block](parameters) mutable exception_specification -> return_type {body}

– Example

[]{cout << “Hello from Lambda” << endl;}();

● no capture block

● no parameters

● no optional mutable modifier

● no exceptions

● no return type

● () means function is called

© 2013 ANTAL Margit

Lambda Expressions

vector<int> v;

sort( v.begin(), v.end(), [](int a, int b)

{ return a > b;}

);

vector<Person> v;

sort( v.begin(), v.end(),

[](const Person& a, const Person& b)

{ return a.getName() < b.getName();}

);

x

No comments:

Post a Comment