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 = ⊂
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